From 37716ddbc38e51c0a9367cc8f2784d4a1d797ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 8 Apr 2022 04:15:40 +0000 Subject: [PATCH 01/11] Bug 1763644 - Add basic @container rule parsing and boilerplate. r=firefox-style-system-reviewers,layout-reviewers,boris For now parse a MediaFeatureCondition. That needs being made more specific, but that is probably worth its own patch. Differential Revision: https://phabricator.services.mozilla.com/D143192 --- dom/webidl/CSSContainerRule.webidl | 14 +++ dom/webidl/moz.build | 1 + layout/inspector/ServoStyleRuleMap.cpp | 2 + layout/style/CSSContainerRule.cpp | 83 +++++++++++++ layout/style/CSSContainerRule.h | 49 ++++++++ layout/style/CSSMediaRule.h | 6 +- layout/style/Rule.cpp | 3 +- layout/style/ServoArcTypeList.h | 1 + layout/style/ServoBindings.h | 1 + layout/style/ServoCSSRuleList.cpp | 3 + layout/style/ServoStyleConstsInlines.h | 1 + layout/style/ServoStyleSet.cpp | 2 + layout/style/moz.build | 2 + servo/components/style/gecko/arc_types.rs | 7 +- .../style/invalidation/stylesheets.rs | 3 +- .../style/stylesheets/container_rule.rs | 79 +++++++++++++ .../style/stylesheets/layer_rule.rs | 2 +- .../style/stylesheets/media_rule.rs | 4 +- servo/components/style/stylesheets/mod.rs | 16 +++ .../style/stylesheets/rule_parser.rs | 23 ++++ .../style/stylesheets/rules_iterator.rs | 4 + .../style/stylesheets/stylesheet.rs | 1 + servo/components/style/stylist.rs | 1 + servo/ports/geckolib/glue.rs | 22 +++- .../aspect-ratio-feature-evaluation.html.ini | 3 - .../at-container-parsing.html.ini | 111 ++++++------------ .../at-container-serialization.html.ini | 6 - .../canvas-as-container-003.html.ini | 2 - .../canvas-as-container-004.html.ini | 2 - .../canvas-as-container-005.html.ini | 2 +- .../canvas-as-container-006.html.ini | 2 +- .../change-display-in-container.html.ini | 2 - .../conditional-container-status.html.ini | 3 - .../container-for-shadow-dom.html.ini | 3 - .../container-inner-at-rules.html.ini | 6 - .../container-nested.html.ini | 36 +++--- .../container-selection.html.ini | 48 ++------ .../counters-in-container-dynamic.html.ini | 2 - .../counters-in-container.html.ini | 2 - ...eep-nested-inline-size-containers.html.ini | 3 +- .../display-contents.html.ini | 3 + .../container-queries/display-none.html.ini | 15 +++ .../fieldset-legend-change.html.ini | 2 - .../font-relative-units-dynamic.html.ini | 8 +- .../font-relative-units.html.ini | 12 -- .../fragmented-container-001.html.ini | 3 - .../container-queries/idlharness.html.ini | 24 ---- .../ineligible-containment.html.ini | 3 + .../inline-size-and-min-width.html.ini | 3 - .../multicol-container-001.html.ini | 3 - .../multicol-inside-container.html.ini | 2 - .../never-match-container.html.ini | 6 + .../orthogonal-wm-container-query.html.ini | 2 +- .../percentage-padding-orthogonal.html.ini | 6 - .../pseudo-elements-003.html.ini | 21 ---- .../query-content-box.html.ini | 12 -- .../query-evaluation.html.ini | 75 ++++++------ ...attach-container-with-dirty-child.html.ini | 3 - ...e-while-content-visibility-hidden.html.ini | 2 - .../size-container-no-principal-box.html.ini | 5 +- .../size-feature-evaluation.html.ini | 88 +++++++------- .../style-change-in-container.html.ini | 3 - ...g-foreignobject-no-size-container.html.ini | 2 + .../svg-g-no-size-container.html.ini | 2 + .../svg-root-size-container.html.ini | 6 - .../top-layer-dialog-backdrop.html.ini | 1 - .../top-layer-dialog-container.html.ini | 2 +- .../top-layer-dialog.html.ini | 2 +- .../top-layer-nested-dialog.html.ini | 5 +- .../transition-style-change-event.html.ini | 3 - .../unsupported-axis.html.ini | 24 +++- .../whitespace-update-after-removal.html.ini | 2 + 72 files changed, 527 insertions(+), 386 deletions(-) create mode 100644 dom/webidl/CSSContainerRule.webidl create mode 100644 layout/style/CSSContainerRule.cpp create mode 100644 layout/style/CSSContainerRule.h create mode 100644 servo/components/style/stylesheets/container_rule.rs delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-003.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-004.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/change-display-in-container.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/conditional-container-status.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/counters-in-container-dynamic.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/counters-in-container.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/fieldset-legend-change.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/font-relative-units.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/fragmented-container-001.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/inline-size-and-min-width.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/multicol-container-001.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/multicol-inside-container.html.ini create mode 100644 testing/web-platform/meta/css/css-contain/container-queries/never-match-container.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/query-content-box.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/resize-while-content-visibility-hidden.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/style-change-in-container.html.ini create mode 100644 testing/web-platform/meta/css/css-contain/container-queries/svg-foreignobject-no-size-container.html.ini create mode 100644 testing/web-platform/meta/css/css-contain/container-queries/svg-g-no-size-container.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/svg-root-size-container.html.ini delete mode 100644 testing/web-platform/meta/css/css-contain/container-queries/transition-style-change-event.html.ini create mode 100644 testing/web-platform/meta/css/css-contain/container-queries/whitespace-update-after-removal.html.ini diff --git a/dom/webidl/CSSContainerRule.webidl b/dom/webidl/CSSContainerRule.webidl new file mode 100644 index 000000000000..8469b3f425d8 --- /dev/null +++ b/dom/webidl/CSSContainerRule.webidl @@ -0,0 +1,14 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://drafts.csswg.org/css-contain-3/#the-csscontainerrule-interface + */ + +// https://drafts.csswg.org/css-contain-3/#the-csscontainerrule-interface +[Exposed=Window, Pref="layout.css.container-queries.enabled"] +interface CSSContainerRule : CSSConditionRule { +}; + diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index b8732600e6b6..8399080efc02 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -475,6 +475,7 @@ WEBIDL_FILES = [ "CSS.webidl", "CSSAnimation.webidl", "CSSConditionRule.webidl", + "CSSContainerRule.webidl", "CSSCounterStyleRule.webidl", "CSSFontFaceRule.webidl", "CSSFontFeatureValuesRule.webidl", diff --git a/layout/inspector/ServoStyleRuleMap.cpp b/layout/inspector/ServoStyleRuleMap.cpp index de7c3f8f7ca0..694fef399e72 100644 --- a/layout/inspector/ServoStyleRuleMap.cpp +++ b/layout/inspector/ServoStyleRuleMap.cpp @@ -86,6 +86,7 @@ void ServoStyleRuleMap::RuleRemoved(StyleSheet& aStyleSheet, case StyleCssRuleType::Media: case StyleCssRuleType::Supports: case StyleCssRuleType::LayerBlock: + case StyleCssRuleType::Container: case StyleCssRuleType::Document: { // See the comment in StyleSheetRemoved. mTable.Clear(); @@ -122,6 +123,7 @@ void ServoStyleRuleMap::FillTableFromRule(css::Rule& aRule) { case StyleCssRuleType::LayerBlock: case StyleCssRuleType::Media: case StyleCssRuleType::Supports: + case StyleCssRuleType::Container: case StyleCssRuleType::Document: { auto& rule = static_cast(aRule); if (ServoCSSRuleList* ruleList = rule.GetCssRules()) { diff --git a/layout/style/CSSContainerRule.cpp b/layout/style/CSSContainerRule.cpp new file mode 100644 index 000000000000..bfe900c5ebe3 --- /dev/null +++ b/layout/style/CSSContainerRule.cpp @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/CSSContainerRule.h" + +#include "mozilla/css/GroupRule.h" +#include "mozilla/dom/CSSContainerRuleBinding.h" +#include "mozilla/ServoBindings.h" + +using namespace mozilla::css; + +namespace mozilla::dom { + +CSSContainerRule::CSSContainerRule(RefPtr aRawRule, + StyleSheet* aSheet, css::Rule* aParentRule, + uint32_t aLine, uint32_t aColumn) + : css::ConditionRule(Servo_ContainerRule_GetRules(aRawRule).Consume(), + aSheet, aParentRule, aLine, aColumn), + mRawRule(std::move(aRawRule)) {} + +CSSContainerRule::~CSSContainerRule() = default; + +NS_IMPL_ADDREF_INHERITED(CSSContainerRule, ConditionRule) +NS_IMPL_RELEASE_INHERITED(CSSContainerRule, ConditionRule) + +// QueryInterface implementation for ContainerRule +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CSSContainerRule) +NS_INTERFACE_MAP_END_INHERITING(ConditionRule) + +#ifdef DEBUG +/* virtual */ +void CSSContainerRule::List(FILE* out, int32_t aIndent) const { + nsAutoCString str; + for (int32_t i = 0; i < aIndent; i++) { + str.AppendLiteral(" "); + } + Servo_ContainerRule_Debug(mRawRule, &str); + fprintf_stderr(out, "%s\n", str.get()); +} +#endif + +StyleCssRuleType CSSContainerRule::Type() const { + return StyleCssRuleType::Container; +} + +void CSSContainerRule::GetConditionText(nsACString& aConditionText) { + Servo_ContainerRule_GetConditionText(mRawRule, &aConditionText); +} + +void CSSContainerRule::SetConditionText(const nsACString& aConditionText, ErrorResult&) { + // FIXME: This shouldn't be here, CSSConditionRule.conditionText should be + // readonly as per: + // https://github.com/w3c/csswg-drafts/issues/6819#issuecomment-1016695585 +} + +/* virtual */ +void CSSContainerRule::GetCssText(nsACString& aCssText) const { + Servo_ContainerRule_GetCssText(mRawRule, &aCssText); +} + +void CSSContainerRule::SetRawAfterClone(RefPtr aRaw) { + mRawRule = std::move(aRaw); + + css::ConditionRule::SetRawAfterClone( + Servo_ContainerRule_GetRules(mRawRule).Consume()); +} + +/* virtual */ +size_t CSSContainerRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { + // TODO Implement this! + return aMallocSizeOf(this); +} + +/* virtual */ +JSObject* CSSContainerRule::WrapObject(JSContext* aCx, + JS::Handle aGivenProto) { + return CSSContainerRule_Binding::Wrap(aCx, this, aGivenProto); +} + +} // namespace mozilla::dom diff --git a/layout/style/CSSContainerRule.h b/layout/style/CSSContainerRule.h new file mode 100644 index 000000000000..c5ddc19c450f --- /dev/null +++ b/layout/style/CSSContainerRule.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_CSSContainerRule_h +#define mozilla_dom_CSSContainerRule_h + +#include "mozilla/css/GroupRule.h" +#include "mozilla/ServoBindingTypes.h" + +namespace mozilla::dom { + +class CSSContainerRule final : public css::ConditionRule { + public: + CSSContainerRule(RefPtr aRawRule, StyleSheet* aSheet, + css::Rule* aParentRule, uint32_t aLine, uint32_t aColumn); + + NS_DECL_ISUPPORTS_INHERITED + +#ifdef DEBUG + void List(FILE* out = stdout, int32_t aIndent = 0) const final; +#endif + + RawServoContainerRule* Raw() const { return mRawRule; } + void SetRawAfterClone(RefPtr); + + // WebIDL interface + StyleCssRuleType Type() const override; + // WebIDL interface + void GetCssText(nsACString& aCssText) const final; + void GetConditionText(nsACString& aConditionText) final; + void SetConditionText(const nsACString& aConditionText, ErrorResult&) final; + + size_t SizeOfIncludingThis(MallocSizeOf) const override; + + JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + private: + virtual ~CSSContainerRule(); + + RefPtr mRawRule; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_CSSContainerRule_h diff --git a/layout/style/CSSMediaRule.h b/layout/style/CSSMediaRule.h index 2801bdd7795e..b16e84f6e825 100644 --- a/layout/style/CSSMediaRule.h +++ b/layout/style/CSSMediaRule.h @@ -10,8 +10,7 @@ #include "mozilla/css/GroupRule.h" #include "mozilla/ServoBindingTypes.h" -namespace mozilla { -namespace dom { +namespace mozilla::dom { class CSSMediaRule final : public css::ConditionRule { public: @@ -51,7 +50,6 @@ class CSSMediaRule final : public css::ConditionRule { RefPtr mMediaList; }; -} // namespace dom -} // namespace mozilla +} // namespace mozilla::dom #endif // mozilla_dom_CSSMediaRule_h diff --git a/layout/style/Rule.cpp b/layout/style/Rule.cpp index 4a8b971a6c52..a107dc3f01b4 100644 --- a/layout/style/Rule.cpp +++ b/layout/style/Rule.cpp @@ -104,7 +104,8 @@ void Rule::AssertParentRuleType() { type == StyleCssRuleType::Document || type == StyleCssRuleType::Supports || type == StyleCssRuleType::Keyframes || - type == StyleCssRuleType::LayerBlock); + type == StyleCssRuleType::LayerBlock || + type == StyleCssRuleType::Container); } } #endif diff --git a/layout/style/ServoArcTypeList.h b/layout/style/ServoArcTypeList.h index f5943cec01ba..cf6f01648610 100644 --- a/layout/style/ServoArcTypeList.h +++ b/layout/style/ServoArcTypeList.h @@ -39,6 +39,7 @@ SERVO_ARC_TYPE(NamespaceRule, RawServoNamespaceRule) SERVO_ARC_TYPE(PageRule, RawServoPageRule) SERVO_ARC_TYPE(SupportsRule, RawServoSupportsRule) SERVO_ARC_TYPE(DocumentRule, RawServoMozDocumentRule) +SERVO_ARC_TYPE(ContainerRule, RawServoContainerRule) SERVO_ARC_TYPE(FontFeatureValuesRule, RawServoFontFeatureValuesRule) SERVO_ARC_TYPE(FontFaceRule, RawServoFontFaceRule) SERVO_ARC_TYPE(CounterStyleRule, RawServoCounterStyleRule) diff --git a/layout/style/ServoBindings.h b/layout/style/ServoBindings.h index 720de4f1ca05..b09f13d8176f 100644 --- a/layout/style/ServoBindings.h +++ b/layout/style/ServoBindings.h @@ -67,6 +67,7 @@ BASIC_RULE_FUNCS(FontFeatureValues) BASIC_RULE_FUNCS(FontFace) BASIC_RULE_FUNCS(CounterStyle) BASIC_RULE_FUNCS(ScrollTimeline) +GROUP_RULE_FUNCS(Container) #undef GROUP_RULE_FUNCS #undef BASIC_RULE_FUNCS diff --git a/layout/style/ServoCSSRuleList.cpp b/layout/style/ServoCSSRuleList.cpp index ce83f9ede828..74136b549ec9 100644 --- a/layout/style/ServoCSSRuleList.cpp +++ b/layout/style/ServoCSSRuleList.cpp @@ -15,6 +15,7 @@ #include "mozilla/dom/CSSLayerBlockRule.h" #include "mozilla/dom/CSSLayerStatementRule.h" #include "mozilla/dom/CSSKeyframesRule.h" +#include "mozilla/dom/CSSContainerRule.h" #include "mozilla/dom/CSSMediaRule.h" #include "mozilla/dom/CSSMozDocumentRule.h" #include "mozilla/dom/CSSNamespaceRule.h" @@ -93,6 +94,7 @@ css::Rule* ServoCSSRuleList::GetRule(uint32_t aIndex) { CASE_RULE(LayerBlock, LayerBlock) CASE_RULE(LayerStatement, LayerStatement) CASE_RULE(ScrollTimeline, ScrollTimeline) + CASE_RULE(Container, Container) #undef CASE_RULE case StyleCssRuleType::Viewport: MOZ_ASSERT_UNREACHABLE("viewport is not implemented in Gecko"); @@ -247,6 +249,7 @@ void ServoCSSRuleList::SetRawAfterClone(RefPtr aNewRules) { CASE_FOR(LayerBlock, LayerBlock) CASE_FOR(LayerStatement, LayerStatement) CASE_FOR(ScrollTimeline, ScrollTimeline) + CASE_FOR(Container, Container) case StyleCssRuleType::Keyframe: MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here"); break; diff --git a/layout/style/ServoStyleConstsInlines.h b/layout/style/ServoStyleConstsInlines.h index d4b66d9c5c53..95120543a7ab 100644 --- a/layout/style/ServoStyleConstsInlines.h +++ b/layout/style/ServoStyleConstsInlines.h @@ -56,6 +56,7 @@ template struct StyleStrong; template struct StyleStrong; template struct StyleStrong; template struct StyleStrong; +template struct StyleStrong; template inline void StyleOwnedSlice::Clear() { diff --git a/layout/style/ServoStyleSet.cpp b/layout/style/ServoStyleSet.cpp index 28e8ab8d844d..5f3eb185347c 100644 --- a/layout/style/ServoStyleSet.cpp +++ b/layout/style/ServoStyleSet.cpp @@ -30,6 +30,7 @@ #include "mozilla/dom/CSSFontFaceRule.h" #include "mozilla/dom/CSSFontFeatureValuesRule.h" #include "mozilla/dom/CSSImportRule.h" +#include "mozilla/dom/CSSContainerRule.h" #include "mozilla/dom/CSSLayerBlockRule.h" #include "mozilla/dom/CSSLayerStatementRule.h" #include "mozilla/dom/CSSMediaRule.h" @@ -949,6 +950,7 @@ void ServoStyleSet::RuleChangedInternal(StyleSheet& aSheet, css::Rule& aRule, CASE_FOR(LayerBlock, LayerBlock) CASE_FOR(LayerStatement, LayerStatement) CASE_FOR(ScrollTimeline, ScrollTimeline) + CASE_FOR(Container, Container) // @namespace can only be inserted / removed when there are only other // @namespace and @import rules, and can't be mutated. case StyleCssRuleType::Namespace: diff --git a/layout/style/moz.build b/layout/style/moz.build index bb54a8b3b0a5..1482934966a6 100644 --- a/layout/style/moz.build +++ b/layout/style/moz.build @@ -121,6 +121,7 @@ EXPORTS.mozilla += [ EXPORTS.mozilla.dom += [ "CSS.h", + "CSSContainerRule.h", "CSSCounterStyleRule.h", "CSSFontFaceRule.h", "CSSFontFeatureValuesRule.h", @@ -166,6 +167,7 @@ UNIFIED_SOURCES += [ "ComputedStyle.cpp", "CounterStyleManager.cpp", "CSS.cpp", + "CSSContainerRule.cpp", "CSSCounterStyleRule.cpp", "CSSFontFaceRule.cpp", "CSSFontFeatureValuesRule.cpp", diff --git a/servo/components/style/gecko/arc_types.rs b/servo/components/style/gecko/arc_types.rs index 4fb08c3a3095..893812ea710e 100644 --- a/servo/components/style/gecko/arc_types.rs +++ b/servo/components/style/gecko/arc_types.rs @@ -15,7 +15,7 @@ use crate::gecko_bindings::structs::{ RawServoKeyframesRule, RawServoLayerBlockRule, RawServoLayerStatementRule, RawServoMediaList, RawServoMediaRule, RawServoMozDocumentRule, RawServoNamespaceRule, RawServoPageRule, RawServoScrollTimelineRule, RawServoStyleRule, RawServoStyleSheetContents, - RawServoSupportsRule, ServoCssRules, + RawServoSupportsRule, RawServoContainerRule, ServoCssRules, }; use crate::gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI, Strong}; use crate::media_queries::MediaList; @@ -26,7 +26,7 @@ use crate::stylesheets::keyframes_rule::Keyframe; use crate::stylesheets::{ CounterStyleRule, CssRules, DocumentRule, FontFaceRule, FontFeatureValuesRule, ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule, MediaRule, NamespaceRule, PageRule, - ScrollTimelineRule, StyleRule, StylesheetContents, SupportsRule, + ScrollTimelineRule, StyleRule, StylesheetContents, SupportsRule, ContainerRule, }; use servo_arc::{Arc, ArcBorrow}; use std::{mem, ptr}; @@ -98,6 +98,9 @@ impl_arc_ffi!(Locked => RawServoScrollTimelineRule impl_arc_ffi!(Locked => RawServoSupportsRule [Servo_SupportsRule_AddRef, Servo_SupportsRule_Release]); +impl_arc_ffi!(Locked => RawServoContainerRule + [Servo_ContainerRule_AddRef, Servo_ContainerRule_Release]); + impl_arc_ffi!(Locked => RawServoMozDocumentRule [Servo_DocumentRule_AddRef, Servo_DocumentRule_Release]); diff --git a/servo/components/style/invalidation/stylesheets.rs b/servo/components/style/invalidation/stylesheets.rs index 53130de7a2e8..3c4ee8450559 100644 --- a/servo/components/style/invalidation/stylesheets.rs +++ b/servo/components/style/invalidation/stylesheets.rs @@ -556,6 +556,7 @@ impl StylesheetInvalidationSet { FontFace(..) | Keyframes(..) | ScrollTimeline(..) | + Container(..) | Style(..) => { if is_generic_change { // TODO(emilio): We need to do this for selector / keyframe @@ -610,7 +611,7 @@ impl StylesheetInvalidationSet { } }, Document(..) | Namespace(..) | Import(..) | Media(..) | Supports(..) | - LayerStatement(..) | LayerBlock(..) => { + Container(..) | LayerStatement(..) | LayerBlock(..) => { // Do nothing, relevant nested rules are visited as part of the // iteration. }, diff --git a/servo/components/style/stylesheets/container_rule.rs b/servo/components/style/stylesheets/container_rule.rs new file mode 100644 index 000000000000..e2e21735b3bb --- /dev/null +++ b/servo/components/style/stylesheets/container_rule.rs @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! A [`@container`][container] rule. +//! +//! [container]: https://drafts.csswg.org/css-contain-3/#container-rule + +use crate::media_queries::MediaCondition; +use crate::shared_lock::{ + DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard, +}; +use crate::values::specified::ContainerName; +use crate::str::CssStringWriter; +use crate::stylesheets::CssRules; +use cssparser::SourceLocation; +#[cfg(feature = "gecko")] +use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf}; +use servo_arc::Arc; +use std::fmt::{self, Write}; +use style_traits::{CssWriter, ToCss}; + +/// A container rule. +#[derive(Debug, ToShmem)] +pub struct ContainerRule { + /// The container name. + pub name: ContainerName, + /// The container query. + pub condition: ContainerCondition, + /// The nested rules inside the block. + pub rules: Arc>, + /// The source position where this rule was found. + pub source_location: SourceLocation, +} + +impl ContainerRule { + /// Measure heap usage. + #[cfg(feature = "gecko")] + pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize { + // Measurement of other fields may be added later. + self.rules.unconditional_shallow_size_of(ops) + + self.rules.read_with(guard).size_of(guard, ops) + } +} + +impl DeepCloneWithLock for ContainerRule { + fn deep_clone_with_lock( + &self, + lock: &SharedRwLock, + guard: &SharedRwLockReadGuard, + params: &DeepCloneParams, + ) -> Self { + let rules = self.rules.read_with(guard); + Self { + name: self.name.clone(), + condition: self.condition.clone(), + rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))), + source_location: self.source_location.clone(), + } + } +} + +impl ToCssWithGuard for ContainerRule { + fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result { + dest.write_str("@container ")?; + { + let mut writer = CssWriter::new(dest); + if !self.name.is_none() { + self.name.to_css(&mut writer)?; + writer.write_char(' ')?; + } + self.condition.to_css(&mut writer)?; + } + self.rules.read_with(guard).to_css_block(guard, dest) + } +} + +/// TODO: Factor out the media query code to work with containers. +pub type ContainerCondition = MediaCondition; diff --git a/servo/components/style/stylesheets/layer_rule.rs b/servo/components/style/stylesheets/layer_rule.rs index ebff5bb9addb..6a91f406f624 100644 --- a/servo/components/style/stylesheets/layer_rule.rs +++ b/servo/components/style/stylesheets/layer_rule.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -//! A [`@layer`][layer] urle. +//! A [`@layer`][layer] rule. //! //! [layer]: https://drafts.csswg.org/css-cascade-5/#layering diff --git a/servo/components/style/stylesheets/media_rule.rs b/servo/components/style/stylesheets/media_rule.rs index ea7441a5c097..cde60a16bf73 100644 --- a/servo/components/style/stylesheets/media_rule.rs +++ b/servo/components/style/stylesheets/media_rule.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -//! An [`@media`][media] urle. +//! An [`@media`][media] rule. //! //! [media]: https://drafts.csswg.org/css-conditional/#at-ruledef-media @@ -18,7 +18,7 @@ use servo_arc::Arc; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; -/// An [`@media`][media] urle. +/// An [`@media`][media] rule. /// /// [media]: https://drafts.csswg.org/css-conditional/#at-ruledef-media #[derive(Debug, ToShmem)] diff --git a/servo/components/style/stylesheets/mod.rs b/servo/components/style/stylesheets/mod.rs index d48b75047970..c72f182ebf03 100644 --- a/servo/components/style/stylesheets/mod.rs +++ b/servo/components/style/stylesheets/mod.rs @@ -12,6 +12,7 @@ pub mod font_feature_values_rule; pub mod import_rule; pub mod keyframes_rule; pub mod layer_rule; +pub mod container_rule; mod loader; mod media_rule; mod namespace_rule; @@ -53,6 +54,7 @@ pub use self::import_rule::ImportRule; pub use self::keyframes_rule::KeyframesRule; pub use self::layer_rule::{LayerBlockRule, LayerStatementRule}; pub use self::loader::StylesheetLoader; +pub use self::container_rule::ContainerRule; pub use self::media_rule::MediaRule; pub use self::namespace_rule::NamespaceRule; pub use self::origin::{Origin, OriginSet, OriginSetIterator, PerOrigin, PerOriginIter}; @@ -253,6 +255,7 @@ pub enum CssRule { Import(Arc>), Style(Arc>), Media(Arc>), + Container(Arc>), FontFace(Arc>), FontFeatureValues(Arc>), CounterStyle(Arc>), @@ -287,6 +290,10 @@ impl CssRule { lock.unconditional_shallow_size_of(ops) + lock.read_with(guard).size_of(guard, ops) }, + CssRule::Container(ref lock) => { + lock.unconditional_shallow_size_of(ops) + lock.read_with(guard).size_of(guard, ops) + }, + CssRule::FontFace(_) => 0, CssRule::FontFeatureValues(_) => 0, CssRule::CounterStyle(_) => 0, @@ -344,6 +351,7 @@ pub enum CssRuleType { LayerBlock = 16, LayerStatement = 17, ScrollTimeline = 18, + Container = 19, } #[allow(missing_docs)] @@ -373,6 +381,7 @@ impl CssRule { CssRule::LayerBlock(_) => CssRuleType::LayerBlock, CssRule::LayerStatement(_) => CssRuleType::LayerStatement, CssRule::ScrollTimeline(_) => CssRuleType::ScrollTimeline, + CssRule::Container(_) => CssRuleType::Container, } } @@ -460,6 +469,12 @@ impl DeepCloneWithLock for CssRule { lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), )) }, + CssRule::Container(ref arc) => { + let rule = arc.read_with(guard); + CssRule::Container(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), + )) + }, CssRule::Media(ref arc) => { let rule = arc.read_with(guard); CssRule::Media(Arc::new( @@ -545,6 +560,7 @@ impl ToCssWithGuard for CssRule { CssRule::LayerBlock(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::LayerStatement(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::ScrollTimeline(ref lock) => lock.read_with(guard).to_css(guard, dest), + CssRule::Container(ref lock) => lock.read_with(guard).to_css(guard, dest), } } } diff --git a/servo/components/style/stylesheets/rule_parser.rs b/servo/components/style/stylesheets/rule_parser.rs index 31d553e4c149..5cbc4a844f63 100644 --- a/servo/components/style/stylesheets/rule_parser.rs +++ b/servo/components/style/stylesheets/rule_parser.rs @@ -13,6 +13,7 @@ use crate::properties::parse_property_declaration_list; use crate::selector_parser::{SelectorImpl, SelectorParser}; use crate::shared_lock::{Locked, SharedRwLock}; use crate::str::starts_with_ignore_ascii_case; +use crate::stylesheets::container_rule::{ContainerRule, ContainerCondition}; use crate::stylesheets::document_rule::DocumentCondition; use crate::stylesheets::font_feature_values_rule::parse_family_name_list; use crate::stylesheets::import_rule::ImportLayer; @@ -28,6 +29,7 @@ use crate::stylesheets::{ }; use crate::values::computed::font::FamilyName; use crate::values::{CssUrl, CustomIdent, KeyframesName, TimelineName}; +use crate::values::specified::ContainerName; use crate::{Namespace, Prefix}; use cssparser::{ AtRuleParser, BasicParseError, BasicParseErrorKind, CowRcStr, Parser, ParserState, @@ -162,6 +164,8 @@ pub enum AtRulePrelude { CounterStyle(CustomIdent), /// A @media rule prelude, with its media queries. Media(Arc>), + /// A @container rule prelude. + Container(ContainerName, ContainerCondition), /// An @supports rule, with its conditional Supports(SupportsCondition), /// A @viewport rule prelude. @@ -428,6 +432,15 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { "font-face" => { AtRulePrelude::FontFace }, + "container" if static_prefs::pref!("layout.css.container-queries.enabled") => { + // FIXME: This is a bit ambiguous: + // https://github.com/w3c/csswg-drafts/issues/7203 + let name = input.try_parse(|input| { + ContainerName::parse(self.context, input) + }).ok().unwrap_or_else(ContainerName::none); + let condition = ContainerCondition::parse(self.context, input)?; + AtRulePrelude::Container(name, condition) + }, "layer" if static_prefs::pref!("layout.css.cascade-layers.enabled") => { let names = input.try_parse(|input| { input.parse_comma_separated(|input| { @@ -607,6 +620,16 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { }, )))) }, + AtRulePrelude::Container(name, condition) => { + Ok(CssRule::Container(Arc::new(self.shared_lock.wrap( + ContainerRule { + name, + condition, + rules: self.parse_nested_rules(input, CssRuleType::Container), + source_location: start.source_location(), + }, + )))) + }, AtRulePrelude::Layer(names) => { let name = match names.len() { 0 | 1 => names.into_iter().next(), diff --git a/servo/components/style/stylesheets/rules_iterator.rs b/servo/components/style/stylesheets/rules_iterator.rs index 417185953a01..c86d4dc96c30 100644 --- a/servo/components/style/stylesheets/rules_iterator.rs +++ b/servo/components/style/stylesheets/rules_iterator.rs @@ -88,6 +88,10 @@ where } Some(doc_rule.rules.read_with(guard).0.iter()) }, + CssRule::Container(ref lock) => { + let container_rule = lock.read_with(guard); + Some(container_rule.rules.read_with(guard).0.iter()) + }, CssRule::Media(ref lock) => { let media_rule = lock.read_with(guard); if !C::process_media(guard, device, quirks_mode, media_rule) { diff --git a/servo/components/style/stylesheets/stylesheet.rs b/servo/components/style/stylesheets/stylesheet.rs index d46fbff4eced..9f5fa2191911 100644 --- a/servo/components/style/stylesheets/stylesheet.rs +++ b/servo/components/style/stylesheets/stylesheet.rs @@ -359,6 +359,7 @@ impl SanitizationKind { CssRule::Media(..) | CssRule::Supports(..) | CssRule::Import(..) | + CssRule::Container(..) | // TODO(emilio): Perhaps Layer should not be always sanitized? But // we sanitize @media and co, so this seems safer for now. CssRule::LayerStatement(..) | diff --git a/servo/components/style/stylist.rs b/servo/components/style/stylist.rs index 02610fe7a127..f74a090a0443 100644 --- a/servo/components/style/stylist.rs +++ b/servo/components/style/stylist.rs @@ -2828,6 +2828,7 @@ impl CascadeData { CssRule::Style(..) | CssRule::Namespace(..) | CssRule::FontFace(..) | + CssRule::Container(..) | CssRule::CounterStyle(..) | CssRule::Supports(..) | CssRule::Keyframes(..) | diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 0b749fbd1438..28f9a083cff0 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -91,7 +91,7 @@ use style::gecko_bindings::structs::{ RawServoLayerStatementRule, RawServoMediaList, RawServoMediaRule, RawServoMozDocumentRule, RawServoNamespaceRule, RawServoPageRule, RawServoScrollTimelineRule, RawServoSharedMemoryBuilder, RawServoStyleSet, RawServoStyleSheetContents, - RawServoSupportsRule, ServoCssRules, + RawServoSupportsRule, RawServoContainerRule, ServoCssRules, }; use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasFFI}; use style::gecko_bindings::sugar::ownership::{ @@ -127,7 +127,7 @@ use style::stylesheets::{ DocumentRule, FontFaceRule, FontFeatureValuesRule, ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule, MediaRule, NamespaceRule, Origin, OriginSet, PageRule, SanitizationData, SanitizationKind, ScrollTimelineRule, StyleRule, StylesheetContents, - StylesheetLoader as StyleStylesheetLoader, SupportsRule, UrlExtraData, + StylesheetLoader as StyleStylesheetLoader, SupportsRule, UrlExtraData, ContainerRule, }; use style::stylist::{add_size_of_ua_cache, AuthorStylesEnabled, RuleInclusion, Stylist}; use style::thread_state; @@ -2334,6 +2334,14 @@ impl_group_rule_funcs! { (Supports, SupportsRule, RawServoSupportsRule), changed: Servo_StyleSet_SupportsRuleChanged, } +impl_group_rule_funcs! { (Container, ContainerRule, RawServoContainerRule), + get_rules: Servo_ContainerRule_GetRules, + getter: Servo_CssRules_GetContainerRuleAt, + debug: Servo_ContainerRule_Debug, + to_css: Servo_ContainerRule_GetCssText, + changed: Servo_StyleSet_ContainerRuleChanged, +} + impl_group_rule_funcs! { (LayerBlock, LayerBlockRule, RawServoLayerBlockRule), get_rules: Servo_LayerBlockRule_GetRules, getter: Servo_CssRules_GetLayerBlockRuleAt, @@ -2951,6 +2959,16 @@ pub extern "C" fn Servo_SupportsRule_GetConditionText( }) } +#[no_mangle] +pub extern "C" fn Servo_ContainerRule_GetConditionText( + rule: &RawServoContainerRule, + result: &mut nsACString, +) { + read_locked_arc(rule, |rule: &ContainerRule| { + rule.condition.to_css(&mut CssWriter::new(result)).unwrap(); + }) +} + #[no_mangle] pub extern "C" fn Servo_MozDocumentRule_GetConditionText( rule: &RawServoMozDocumentRule, diff --git a/testing/web-platform/meta/css/css-contain/container-queries/aspect-ratio-feature-evaluation.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/aspect-ratio-feature-evaluation.html.ini index 97bfa5fb7c70..69d4f6a56469 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/aspect-ratio-feature-evaluation.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/aspect-ratio-feature-evaluation.html.ini @@ -1,6 +1,3 @@ [aspect-ratio-feature-evaluation.html] [@container queries with aspect-ratio and size containment] expected: FAIL - - [@container query with aspect-ratio change after resize] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/at-container-parsing.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/at-container-parsing.html.ini index 8f58546452f7..05dd92812294 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/at-container-parsing.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/at-container-parsing.html.ini @@ -1,34 +1,4 @@ [at-container-parsing.html] - [(width)] - expected: FAIL - - [(min-width: 0px)] - expected: FAIL - - [(max-width: 0px)] - expected: FAIL - - [(height)] - expected: FAIL - - [(min-height: 0px)] - expected: FAIL - - [(max-height: 0px)] - expected: FAIL - - [(aspect-ratio)] - expected: FAIL - - [(min-aspect-ratio: 1/2)] - expected: FAIL - - [(max-aspect-ratio: 1/2)] - expected: FAIL - - [(orientation: portrait)] - expected: FAIL - [(inline-size)] expected: FAIL @@ -47,24 +17,9 @@ [(max-block-size: 0px)] expected: FAIL - [(width: 100px)] - expected: FAIL - - [((width: 100px))] - expected: FAIL - - [(not (width: 100px))] - expected: FAIL - - [((width: 100px) and (height: 100px))] - expected: FAIL - [((width: 50px) or (height: 100px))] expected: FAIL - [(width < 100px)] - expected: FAIL - [(100px < width)] expected: FAIL @@ -101,42 +56,9 @@ [(grid)] expected: FAIL - [Container selector: foo] - expected: FAIL - - [Container selector: foo] - expected: FAIL - - [Container selector: foo ] - expected: FAIL - - [(((width: 40px) or (width: 50px)) and (height: 100px))] - expected: FAIL - - [((width: 100px) and ((height: 40px) or (height: 50px)))] - expected: FAIL - [(((width: 40x) and (height: 50px)) or (height: 100px))] expected: FAIL - [((width: 50px) or ((width: 40px) and (height: 50px)))] - expected: FAIL - - [((width: 100px) and (not (height: 100px)))] - expected: FAIL - - [(width <= 100px)] - expected: FAIL - - [(width = 100px)] - expected: FAIL - - [(width > 100px)] - expected: FAIL - - [(width >= 100px)] - expected: FAIL - [(100px <= width)] expected: FAIL @@ -187,3 +109,36 @@ [(100px : width : 200px)] expected: FAIL + + [screen and (width: 100px)] + expected: FAIL + + [screen or (width: 100px)] + expected: FAIL + + [not screen and (width: 100px)] + expected: FAIL + + [not screen or (width: 100px)] + expected: FAIL + + [(width: 100px) and (height: 100px)] + expected: FAIL + + [(width: 100px) or (height: 100px)] + expected: FAIL + + [not (width: 100px)] + expected: FAIL + + [foo (width: 100px)] + expected: FAIL + + [Container selector: foo foo] + expected: FAIL + + [Container selector: none] + expected: FAIL + + [Container selector: None] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/at-container-serialization.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/at-container-serialization.html.ini index 6c7334742e6e..589dfb309e8b 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/at-container-serialization.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/at-container-serialization.html.ini @@ -8,11 +8,5 @@ [Serialization of nested @container rule] expected: FAIL - [Serialization of boolean condition syntax] - expected: FAIL - - [Serialization of colon condition syntax] - expected: FAIL - [Serialization of range condition syntax] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-003.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-003.html.ini deleted file mode 100644 index e6ff9db8dd58..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-003.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[canvas-as-container-003.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-004.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-004.html.ini deleted file mode 100644 index e745dc1dbaba..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-004.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[canvas-as-container-004.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-005.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-005.html.ini index 69ec819abd95..a25595e70d43 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-005.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-005.html.ini @@ -1,3 +1,3 @@ [canvas-as-container-005.html] - [Focusable after container size change] + [Initially display:none, not focusable] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-006.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-006.html.ini index 0aaa7995a130..2bec1da93aeb 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-006.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-006.html.ini @@ -1,3 +1,3 @@ [canvas-as-container-006.html] - [Focusable after container size change] + [Initially display:none, not focusable] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/change-display-in-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/change-display-in-container.html.ini deleted file mode 100644 index 1a14360fad1d..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/change-display-in-container.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[change-display-in-container.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/conditional-container-status.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/conditional-container-status.html.ini deleted file mode 100644 index ed8d459baace..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/conditional-container-status.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[conditional-container-status.html] - [Conditionally applying container-type:initial] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/container-for-shadow-dom.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/container-for-shadow-dom.html.ini index 7ebe0e51a570..c2dfb40ce6ff 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/container-for-shadow-dom.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/container-for-shadow-dom.html.ini @@ -2,9 +2,6 @@ [Match container in outer tree] expected: FAIL - [Match container in same tree, not walking flat tree ancestors] - expected: FAIL - [Match container in ::slotted selector's originating element tree] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/container-inner-at-rules.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/container-inner-at-rules.html.ini index 68010d992c1f..118e6d61c702 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/container-inner-at-rules.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/container-inner-at-rules.html.ini @@ -5,12 +5,6 @@ [@property is defined regardless of evaluation] expected: FAIL - [@layer order respected regardless of evaluation] - expected: FAIL - - [@font-face is defined regardless of evaluation] - expected: FAIL - [@media works inside @container] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/container-nested.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/container-nested.html.ini index af458226e9e2..2e4337dc1504 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/container-nested.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/container-nested.html.ini @@ -1,27 +1,21 @@ [container-nested.html] - [Implicit] - expected: FAIL - - [Outer named, inner named] - expected: FAIL - - [Outer named, inner named (reverse)] - expected: FAIL - - [Outer named, inner implicit] - expected: FAIL - - [Inner named, outer implicit] - expected: FAIL - - [Inner named, outer implicit (reverse)] - expected: FAIL - - [Three levels] - expected: FAIL - [Named inner invalidation] expected: FAIL [Implicit outer invalidation] expected: FAIL + + [Implicit, outer failing] + expected: FAIL + + [Implicit, inner failing] + expected: FAIL + + [Failing outer name] + expected: FAIL + + [Failing inner name] + expected: FAIL + + [Three levels, middle fail] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/container-selection.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/container-selection.html.ini index 41697cff7ad1..1168f8ae23a2 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/container-selection.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/container-selection.html.ini @@ -1,43 +1,4 @@ [container-selection.html] - [(width: 16px) for .size > .inline > span] - expected: FAIL - - [(height: 16px) for .inline > .size > span] - expected: FAIL - - [(width: 16px) for .inline > .size > span] - expected: FAIL - - [(height: 32px) for .size > .inline > span] - expected: FAIL - - [a (width: 32px) for .a-size > .b-size > span] - expected: FAIL - - [b (width: 16px) for .a-size > .b-size > span] - expected: FAIL - - [a (width: 16px) for .a-size > .a-size > span] - expected: FAIL - - [a (width: 32px) for .a-size > .a > span] - expected: FAIL - - [a (width: 32px) for .ab-size > .size > span] - expected: FAIL - - [b (width: 32px) for .ab-size > .size > span] - expected: FAIL - - [a (width: 8px) for .a-size > .b-size > .a-inline > span] - expected: FAIL - - [b (width: 16px) for .a-size > .b-size > .a-inline > span] - expected: FAIL - - [a (height: 32px) for .a-size > .b-size > .a-inline > span] - expected: FAIL - [a (inline-size: 8px) for .a-size > .b-size > .a-inline > span] expected: FAIL @@ -46,3 +7,12 @@ [a (block-size: 32px) for .a-size > .b-size > .a-inline > span] expected: FAIL + + [(height: 16px) for .size > .inline > span] + expected: FAIL + + [c (width) for .a-size > .b-size > span] + expected: FAIL + + [c (width) for .ab-size > .size > span] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container-dynamic.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container-dynamic.html.ini deleted file mode 100644 index 7cd3bd77b75d..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container-dynamic.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[counters-in-container-dynamic.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container.html.ini deleted file mode 100644 index 4bf610e9b835..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[counters-in-container.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/deep-nested-inline-size-containers.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/deep-nested-inline-size-containers.html.ini index 49ed002ee861..e04cf1e12084 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/deep-nested-inline-size-containers.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/deep-nested-inline-size-containers.html.ini @@ -1,2 +1,3 @@ [deep-nested-inline-size-containers.html] - expected: ERROR + [Test that all container widths match] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/display-contents.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/display-contents.html.ini index 3b16182c1827..6e621b35be30 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/display-contents.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/display-contents.html.ini @@ -4,3 +4,6 @@ [getComputedStyle when intermediate container becomes display:contents] expected: FAIL + + [getComputedStyle when container is display:contents] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/display-none.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/display-none.html.ini index 5c2a480abeca..170b460379a2 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/display-none.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/display-none.html.ini @@ -37,3 +37,18 @@ [getComputedStyle when in display:none with layout dirty outer element] expected: FAIL + + [getComputedStyle when container is display:none] + expected: FAIL + + [getComputedStyle when inner container is display:none] + expected: FAIL + + [getComputedStyle when intermediate ancestor is display:none] + expected: FAIL + + [getComputedStyle when outer container is display:none] + expected: FAIL + + [getComputedStyle on ::before when container is display:none] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/fieldset-legend-change.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/fieldset-legend-change.html.ini deleted file mode 100644 index 9d5d377cd9c5..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/fieldset-legend-change.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[fieldset-legend-change.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units-dynamic.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units-dynamic.html.ini index 318c812c6550..3a8ce7450987 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units-dynamic.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units-dynamic.html.ini @@ -1,12 +1,12 @@ [font-relative-units-dynamic.html] - [em relative after change] + [em relative before change] expected: FAIL - [rem relative after change] + [rem relative before change] expected: FAIL - [ex relative after change] + [ex relative before change] expected: FAIL - [ch relative after change] + [ch relative before change] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units.html.ini deleted file mode 100644 index 3e8e01654403..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[font-relative-units.html] - [em relative inline-size] - expected: FAIL - - [rem relative inline-size] - expected: FAIL - - [ex relative inline-size] - expected: FAIL - - [ch relative inline-size] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/fragmented-container-001.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/fragmented-container-001.html.ini deleted file mode 100644 index 06a25a08df23..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/fragmented-container-001.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[fragmented-container-001.html] - [Children of fragmented inline-size container should match inline-size of first fragment] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/idlharness.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/idlharness.html.ini index b5746c6e3a8c..b5a2c43946d9 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/idlharness.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/idlharness.html.ini @@ -1,30 +1,6 @@ [idlharness.html] - [CSSContainerRule interface object length] - expected: FAIL - - [CSSContainerRule interface: existence and properties of interface object] - expected: FAIL - - [CSSContainerRule interface: existence and properties of interface prototype object] - expected: FAIL - [Stringification of sheet.cssRules[0\].cssRules[0\]] expected: FAIL [CSSContainerRule must be primary interface of sheet.cssRules[0\].cssRules[0\]] expected: FAIL - - [CSSContainerRule must be primary interface of sheet.cssRules[0\]] - expected: FAIL - - [CSSContainerRule interface: existence and properties of interface prototype object's @@unscopables property] - expected: FAIL - - [Stringification of sheet.cssRules[0\]] - expected: FAIL - - [CSSContainerRule interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - - [CSSContainerRule interface object name] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/ineligible-containment.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/ineligible-containment.html.ini index 1a6d08f1f00c..a18c90ee2a2b 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/ineligible-containment.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/ineligible-containment.html.ini @@ -1,3 +1,6 @@ [ineligible-containment.html] [Changing containment eligibility invalidates style] expected: FAIL + + [Container ineligible for containment] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/inline-size-and-min-width.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/inline-size-and-min-width.html.ini deleted file mode 100644 index be23d2784966..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/inline-size-and-min-width.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[inline-size-and-min-width.html] - [min-width of inline-size container affects container size] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/multicol-container-001.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/multicol-container-001.html.ini deleted file mode 100644 index f74fceae162d..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/multicol-container-001.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[multicol-container-001.html] - [Children of multicol inline-size container should match inline-size of the container] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/multicol-inside-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/multicol-inside-container.html.ini deleted file mode 100644 index 0e9d4ebfc9da..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/multicol-inside-container.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[multicol-inside-container.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/never-match-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/never-match-container.html.ini new file mode 100644 index 000000000000..5d7e33d4b325 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/never-match-container.html.ini @@ -0,0 +1,6 @@ +[never-match-container.html] + [Size @container query against inline box never matches] + expected: FAIL + + [Size @container query against svg element never matches] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/orthogonal-wm-container-query.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/orthogonal-wm-container-query.html.ini index d49b0b0b1f62..9ceeb1bc0685 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/orthogonal-wm-container-query.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/orthogonal-wm-container-query.html.ini @@ -1,3 +1,3 @@ [orthogonal-wm-container-query.html] - [Orthogonal width] + [Initial non-orthogonal width] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/percentage-padding-orthogonal.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/percentage-padding-orthogonal.html.ini index 56c3b6e727b0..9e409dfe836b 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/percentage-padding-orthogonal.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/percentage-padding-orthogonal.html.ini @@ -5,11 +5,5 @@ [#container width 400px after padding is applied.] expected: FAIL - [#container width 400px after padding is applied. #second is removed from the rendering] - expected: FAIL - [#container height measured with 499px width. Both container children visible] expected: FAIL - - [#container width 399x after padding is applied. #second is removed from the rendering] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/pseudo-elements-003.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/pseudo-elements-003.html.ini index 9a1dce292489..38287f613b1d 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/pseudo-elements-003.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/pseudo-elements-003.html.ini @@ -1,24 +1,3 @@ [pseudo-elements-003.html] - [Originating element container for ::before] - expected: FAIL - - [Originating element container for ::after] - expected: FAIL - - [Originating element container for ::marker] - expected: FAIL - - [Originating element container for ::first-line] - expected: FAIL - - [Originating element container for ::first-letter] - expected: FAIL - - [Originating element container for outer ::first-line] - expected: FAIL - - [Originating element container for outer ::first-letter] - expected: FAIL - [Originating element container for ::backdrop] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/query-content-box.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/query-content-box.html.ini deleted file mode 100644 index f21577ea55e9..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/query-content-box.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[query-content-box.html] - [Size queries with content-box sizing] - expected: FAIL - - [Size queries with border-box sizing] - expected: FAIL - - [Size queries with content-box sizing and overflow:scroll] - expected: FAIL - - [Size queries with border-box sizing and overflow:scroll] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/query-evaluation.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/query-evaluation.html.ini index 59c63da41f00..6582d211b48a 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/query-evaluation.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/query-evaluation.html.ini @@ -1,37 +1,4 @@ [query-evaluation.html] - [(width)] - expected: FAIL - - [((width))] - expected: FAIL - - [((((width))))] - expected: FAIL - - [(not (height))] - expected: FAIL - - [((width) and (width))] - expected: FAIL - - [((width) and (width) and (width))] - expected: FAIL - - [((width) or (width))] - expected: FAIL - - [((width) or (width) or (width))] - expected: FAIL - - [((height) or (width) or (width))] - expected: FAIL - - [((width) or (height) or (width))] - expected: FAIL - - [((width) or (width) or (height))] - expected: FAIL - [((unknown) or (width) or (width))] expected: FAIL @@ -44,12 +11,6 @@ [((unknown) or (height) or (width))] expected: FAIL - [(not ((width) and (height)))] - expected: FAIL - - [((height) or (not ((height) and (width))))] - expected: FAIL - [style((width: 1px))] expected: FAIL @@ -94,3 +55,39 @@ [style((height: 2px) or (not ((height: 2px) and (width: 1px))))] expected: FAIL + + [(height)] + expected: FAIL + + [((height))] + expected: FAIL + + [((((height))))] + expected: FAIL + + [(not (width))] + expected: FAIL + + [((height) and (height))] + expected: FAIL + + [((height) and (width) and (width))] + expected: FAIL + + [((width) and (height) and (width))] + expected: FAIL + + [((width) and (width) and (height))] + expected: FAIL + + [((height) or (height))] + expected: FAIL + + [(not ((width) and (width)))] + expected: FAIL + + [((width) and (not ((height) or (width))))] + expected: FAIL + + [((height) or ((height) and (width)))] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/reattach-container-with-dirty-child.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/reattach-container-with-dirty-child.html.ini index 2543bb66f8b5..bd34f008bb72 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/reattach-container-with-dirty-child.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/reattach-container-with-dirty-child.html.ini @@ -1,6 +1,3 @@ [reattach-container-with-dirty-child.html] [Initially wider than 200px] expected: FAIL - - [Container query changed and inner.style applied] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/resize-while-content-visibility-hidden.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/resize-while-content-visibility-hidden.html.ini deleted file mode 100644 index 9a43f8e35d16..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/resize-while-content-visibility-hidden.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[resize-while-content-visibility-hidden.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/size-container-no-principal-box.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/size-container-no-principal-box.html.ini index 5724c5803493..8ca33c7ead53 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/size-container-no-principal-box.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/size-container-no-principal-box.html.ini @@ -1,3 +1,6 @@ [size-container-no-principal-box.html] - [Check that container queries is supported] + [(min-width: 0) does not match a container without a principal box (display:none)] + expected: FAIL + + [(min-width: 0) does not match a container without a principal box (display:contents)] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/size-feature-evaluation.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/size-feature-evaluation.html.ini index 8ada0b1eb739..072fc16f2c1f 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/size-feature-evaluation.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/size-feature-evaluation.html.ini @@ -1,22 +1,4 @@ [size-feature-evaluation.html] - [(width >= 100px) (.horizontal)] - expected: FAIL - - [(min-width: 100px) (.horizontal)] - expected: FAIL - - [(max-width: 100px) (.horizontal)] - expected: FAIL - - [(height >= 200px) (.horizontal)] - expected: FAIL - - [(min-height: 200px) (.horizontal)] - expected: FAIL - - [(max-height: 200px) (.horizontal)] - expected: FAIL - [(inline-size >= 100px) (.horizontal)] expected: FAIL @@ -35,30 +17,6 @@ [(max-block-size: 200px) (.horizontal)] expected: FAIL - [(orientation: portrait) (.horizontal)] - expected: FAIL - - [(aspect-ratio: 1/2) (.horizontal)] - expected: FAIL - - [(width >= 100px) (.vertical)] - expected: FAIL - - [(min-width: 100px) (.vertical)] - expected: FAIL - - [(max-width: 100px) (.vertical)] - expected: FAIL - - [(height >= 200px) (.vertical)] - expected: FAIL - - [(min-height: 200px) (.vertical)] - expected: FAIL - - [(max-height: 200px) (.vertical)] - expected: FAIL - [(block-size >= 100px) (.vertical)] expected: FAIL @@ -77,8 +35,50 @@ [(max-inline-size: 200px) (.vertical)] expected: FAIL - [(orientation: portrait) (.vertical)] + [(width < 100px) (.horizontal)] expected: FAIL - [(aspect-ratio: 1/2) (.vertical)] + [(min-width: 101px) (.horizontal)] + expected: FAIL + + [(max-width: 99px) (.horizontal)] + expected: FAIL + + [(height < 200px) (.horizontal)] + expected: FAIL + + [(min-height: 201px) (.horizontal)] + expected: FAIL + + [(max-height: 199px) (.horizontal)] + expected: FAIL + + [(orientation: landscape) (.horizontal)] + expected: FAIL + + [(aspect-ratio: 2/1) (.horizontal)] + expected: FAIL + + [(width < 100px) (.vertical)] + expected: FAIL + + [(min-width: 101px) (.vertical)] + expected: FAIL + + [(max-width: 99px) (.vertical)] + expected: FAIL + + [(height < 200px) (.vertical)] + expected: FAIL + + [(min-height: 201px) (.vertical)] + expected: FAIL + + [(max-height: 199px) (.vertical)] + expected: FAIL + + [(orientation: landscape) (.vertical)] + expected: FAIL + + [(aspect-ratio: 2/1) (.vertical)] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/style-change-in-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/style-change-in-container.html.ini deleted file mode 100644 index a394a8ae697b..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/style-change-in-container.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[style-change-in-container.html] - [Basic test for container query evaluation stability] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/svg-foreignobject-no-size-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/svg-foreignobject-no-size-container.html.ini new file mode 100644 index 000000000000..ecfd70444c22 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/svg-foreignobject-no-size-container.html.ini @@ -0,0 +1,2 @@ +[svg-foreignobject-no-size-container.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/svg-g-no-size-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/svg-g-no-size-container.html.ini new file mode 100644 index 000000000000..4213a08a8113 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/svg-g-no-size-container.html.ini @@ -0,0 +1,2 @@ +[svg-g-no-size-container.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/svg-root-size-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/svg-root-size-container.html.ini deleted file mode 100644 index f9b04ee16b71..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/svg-root-size-container.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[svg-root-size-container.html] - [SVG text querying SVG root size container] - expected: FAIL - - [div in foreignObject querying SVG root size container] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-backdrop.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-backdrop.html.ini index 1df51f918508..c2c634ac1e1b 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-backdrop.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-backdrop.html.ini @@ -1,3 +1,2 @@ [top-layer-dialog-backdrop.html] prefs: [dom.dialog_element.enabled:true] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-container.html.ini index 8acade9d67c0..a2f7493fc77b 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-container.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-container.html.ini @@ -1,3 +1,3 @@ [top-layer-dialog-container.html] - [#dialog sized by viewport] + [#dialog initially sized by #containing-block] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog.html.ini index 35f0120c587a..bc7562b953c9 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog.html.ini @@ -5,5 +5,5 @@ [Modal dialog still has parent as query container while in top layer] expected: FAIL - [Container changes width while dialog is in top layer] + [#container initially wider than 200px] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-nested-dialog.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-nested-dialog.html.ini index af9391443a7c..e9196d801c12 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-nested-dialog.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-nested-dialog.html.ini @@ -1,3 +1,6 @@ [top-layer-nested-dialog.html] - [@container queries start matching] + [Dialogs initially not matching for container queries] + expected: FAIL + + [Dialogs still not matching after showModal] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/transition-style-change-event.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/transition-style-change-event.html.ini deleted file mode 100644 index 805e5ca57d58..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/transition-style-change-event.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[transition-style-change-event.html] - [Container Queries - Style Change Event for transitions] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/unsupported-axis.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/unsupported-axis.html.ini index 1658c29088e5..dcd6d0d79368 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/unsupported-axis.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/unsupported-axis.html.ini @@ -1,6 +1,24 @@ [unsupported-axis.html] - [(width > 0px)] - expected: FAIL - [(inline-size > 0px)] expected: FAIL + + [(height > 0px)] + expected: FAIL + + [((height > 0px) or (width > 0px))] + expected: FAIL + + [((width > 0px) or (height > 0px))] + expected: FAIL + + [((orientation: landscape) or (width > 0px))] + expected: FAIL + + [((width > 0px) or (orientation: landscape))] + expected: FAIL + + [((height > 0px) or (orientation: landscape))] + expected: FAIL + + [((height > 0px) or (orientation: landscape)), with contain:size] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/whitespace-update-after-removal.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/whitespace-update-after-removal.html.ini new file mode 100644 index 000000000000..4d3034d71f7d --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/whitespace-update-after-removal.html.ini @@ -0,0 +1,2 @@ +[whitespace-update-after-removal.html] + expected: FAIL From 03d33c13bf72ea4790e13613456f9f038a0de4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 8 Apr 2022 04:24:18 +0000 Subject: [PATCH 02/11] Bug 1762474 - Make CSSConditionRule.conditionText readonly. r=layout-reviewers,firefox-style-system-reviewers,boris Differential Revision: https://phabricator.services.mozilla.com/D143193 --- dom/webidl/CSSConditionRule.webidl | 3 +- layout/style/CSSContainerRule.cpp | 6 -- layout/style/CSSContainerRule.h | 1 - layout/style/CSSMediaRule.cpp | 8 --- layout/style/CSSMediaRule.h | 2 - layout/style/CSSMozDocumentRule.cpp | 9 --- layout/style/CSSMozDocumentRule.h | 2 - layout/style/CSSSupportsRule.cpp | 9 --- layout/style/CSSSupportsRule.h | 2 - layout/style/GroupRule.h | 2 - layout/style/test/mochitest.ini | 1 - .../test/test_condition_text_assignment.html | 59 ------------------- .../cssom/CSSConditionRule-conditionText.html | 23 ++++++++ .../tests/interfaces/css-conditional.idl | 2 +- 14 files changed, 25 insertions(+), 104 deletions(-) delete mode 100644 layout/style/test/test_condition_text_assignment.html create mode 100644 testing/web-platform/tests/css/cssom/CSSConditionRule-conditionText.html diff --git a/dom/webidl/CSSConditionRule.webidl b/dom/webidl/CSSConditionRule.webidl index 5ab3ae1dcda3..a799498494df 100644 --- a/dom/webidl/CSSConditionRule.webidl +++ b/dom/webidl/CSSConditionRule.webidl @@ -10,6 +10,5 @@ // https://drafts.csswg.org/css-conditional/#the-cssconditionrule-interface [Exposed=Window] interface CSSConditionRule : CSSGroupingRule { - [SetterThrows] - attribute UTF8String conditionText; + readonly attribute UTF8String conditionText; }; diff --git a/layout/style/CSSContainerRule.cpp b/layout/style/CSSContainerRule.cpp index bfe900c5ebe3..2797a56b93d3 100644 --- a/layout/style/CSSContainerRule.cpp +++ b/layout/style/CSSContainerRule.cpp @@ -50,12 +50,6 @@ void CSSContainerRule::GetConditionText(nsACString& aConditionText) { Servo_ContainerRule_GetConditionText(mRawRule, &aConditionText); } -void CSSContainerRule::SetConditionText(const nsACString& aConditionText, ErrorResult&) { - // FIXME: This shouldn't be here, CSSConditionRule.conditionText should be - // readonly as per: - // https://github.com/w3c/csswg-drafts/issues/6819#issuecomment-1016695585 -} - /* virtual */ void CSSContainerRule::GetCssText(nsACString& aCssText) const { Servo_ContainerRule_GetCssText(mRawRule, &aCssText); diff --git a/layout/style/CSSContainerRule.h b/layout/style/CSSContainerRule.h index c5ddc19c450f..21e02c318f1c 100644 --- a/layout/style/CSSContainerRule.h +++ b/layout/style/CSSContainerRule.h @@ -31,7 +31,6 @@ class CSSContainerRule final : public css::ConditionRule { // WebIDL interface void GetCssText(nsACString& aCssText) const final; void GetConditionText(nsACString& aConditionText) final; - void SetConditionText(const nsACString& aConditionText, ErrorResult&) final; size_t SizeOfIncludingThis(MallocSizeOf) const override; diff --git a/layout/style/CSSMediaRule.cpp b/layout/style/CSSMediaRule.cpp index 042a145dbd86..650b2d56de03 100644 --- a/layout/style/CSSMediaRule.cpp +++ b/layout/style/CSSMediaRule.cpp @@ -84,14 +84,6 @@ void CSSMediaRule::GetConditionText(nsACString& aConditionText) { Media()->GetMediaText(aConditionText); } -void CSSMediaRule::SetConditionText(const nsACString& aConditionText, - ErrorResult& aRv) { - if (IsReadOnly()) { - return; - } - Media()->SetMediaText(aConditionText); -} - /* virtual */ void CSSMediaRule::GetCssText(nsACString& aCssText) const { Servo_MediaRule_GetCssText(mRawRule, &aCssText); diff --git a/layout/style/CSSMediaRule.h b/layout/style/CSSMediaRule.h index b16e84f6e825..12bf9dec2fd6 100644 --- a/layout/style/CSSMediaRule.h +++ b/layout/style/CSSMediaRule.h @@ -34,8 +34,6 @@ class CSSMediaRule final : public css::ConditionRule { // WebIDL interface void GetCssText(nsACString& aCssText) const final; void GetConditionText(nsACString& aConditionText) final; - void SetConditionText(const nsACString& aConditionText, - ErrorResult& aRv) final; dom::MediaList* Media(); size_t SizeOfIncludingThis(MallocSizeOf) const override; diff --git a/layout/style/CSSMozDocumentRule.cpp b/layout/style/CSSMozDocumentRule.cpp index 73ca12aba959..13609dc5dffa 100644 --- a/layout/style/CSSMozDocumentRule.cpp +++ b/layout/style/CSSMozDocumentRule.cpp @@ -122,15 +122,6 @@ void CSSMozDocumentRule::GetConditionText(nsACString& aConditionText) { Servo_MozDocumentRule_GetConditionText(mRawRule, &aConditionText); } -void CSSMozDocumentRule::SetConditionText(const nsACString& aConditionText, - ErrorResult& aRv) { - if (IsReadOnly()) { - return; - } - - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); -} - /* virtual */ void CSSMozDocumentRule::GetCssText(nsACString& aCssText) const { Servo_MozDocumentRule_GetCssText(mRawRule, &aCssText); diff --git a/layout/style/CSSMozDocumentRule.h b/layout/style/CSSMozDocumentRule.h index a437070f6337..6cc69212cdc9 100644 --- a/layout/style/CSSMozDocumentRule.h +++ b/layout/style/CSSMozDocumentRule.h @@ -37,8 +37,6 @@ class CSSMozDocumentRule final : public css::ConditionRule { StyleCssRuleType Type() const final; void GetCssText(nsACString& aCssText) const final; void GetConditionText(nsACString& aConditionText) final; - void SetConditionText(const nsACString& aConditionText, - ErrorResult& aRv) final; size_t SizeOfIncludingThis(MallocSizeOf) const override; diff --git a/layout/style/CSSSupportsRule.cpp b/layout/style/CSSSupportsRule.cpp index 1a4f9a406a65..3859e6201edc 100644 --- a/layout/style/CSSSupportsRule.cpp +++ b/layout/style/CSSSupportsRule.cpp @@ -48,15 +48,6 @@ void CSSSupportsRule::GetConditionText(nsACString& aConditionText) { Servo_SupportsRule_GetConditionText(mRawRule, &aConditionText); } -void CSSSupportsRule::SetConditionText(const nsACString& aConditionText, - ErrorResult& aRv) { - if (IsReadOnly()) { - return; - } - - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); -} - /* virtual */ void CSSSupportsRule::GetCssText(nsACString& aCssText) const { Servo_SupportsRule_GetCssText(mRawRule, &aCssText); diff --git a/layout/style/CSSSupportsRule.h b/layout/style/CSSSupportsRule.h index 9a11ff190c01..e8a9976cb4e0 100644 --- a/layout/style/CSSSupportsRule.h +++ b/layout/style/CSSSupportsRule.h @@ -31,8 +31,6 @@ class CSSSupportsRule : public css::ConditionRule { StyleCssRuleType Type() const final; void GetCssText(nsACString& aCssText) const final; void GetConditionText(nsACString& aConditionText) final; - void SetConditionText(const nsACString& aConditionText, - ErrorResult& aRv) final; size_t SizeOfIncludingThis(MallocSizeOf) const override; JSObject* WrapObject(JSContext* aCx, diff --git a/layout/style/GroupRule.h b/layout/style/GroupRule.h index 6e8b785fd576..367ab48ae54b 100644 --- a/layout/style/GroupRule.h +++ b/layout/style/GroupRule.h @@ -95,8 +95,6 @@ class ConditionRule : public GroupRule { public: virtual void GetConditionText(nsACString& aConditionText) = 0; - virtual void SetConditionText(const nsACString& aConditionText, - ErrorResult& aRv) = 0; }; } // namespace css diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 4f719696cd90..14b21a641887 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -208,7 +208,6 @@ skip-if = toolkit == 'android' [test_computed_style_no_pseudo.html] [test_computed_style_prefs.html] [test_condition_text.html] -[test_condition_text_assignment.html] [test_counter_descriptor_storage.html] [test_counter_style.html] [test_crash_with_content_policy.html] diff --git a/layout/style/test/test_condition_text_assignment.html b/layout/style/test/test_condition_text_assignment.html deleted file mode 100644 index 9f060a0b6e10..000000000000 --- a/layout/style/test/test_condition_text_assignment.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Test for Bug 815021 - - - - - -Mozilla Bug 815021 -

- -
-
-
- - diff --git a/testing/web-platform/tests/css/cssom/CSSConditionRule-conditionText.html b/testing/web-platform/tests/css/cssom/CSSConditionRule-conditionText.html new file mode 100644 index 000000000000..bccfc3135a4c --- /dev/null +++ b/testing/web-platform/tests/css/cssom/CSSConditionRule-conditionText.html @@ -0,0 +1,23 @@ + +CSSConditionRule.conditionText + + + + + + diff --git a/testing/web-platform/tests/interfaces/css-conditional.idl b/testing/web-platform/tests/interfaces/css-conditional.idl index 16f25583be97..d87f305fddf9 100644 --- a/testing/web-platform/tests/interfaces/css-conditional.idl +++ b/testing/web-platform/tests/interfaces/css-conditional.idl @@ -9,7 +9,7 @@ partial interface CSSRule { [Exposed=Window] interface CSSConditionRule : CSSGroupingRule { - attribute CSSOMString conditionText; + readonly attribute CSSOMString conditionText; }; [Exposed=Window] From 28844e8f8020502c899e56eded8de0f7a84072d4 Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Fri, 8 Apr 2022 05:11:48 +0000 Subject: [PATCH 03/11] Bug 1639087 - Add dragcaret event by accessible caret. r=TYLin,smaug To support magnifying glass on GeckoView, I would like to add `dragcaret` event and, clientX and clientX in CaretStateChangedEvent chrome event. Actually, accessible caret fires `presscaret` and `releasecaret` when accessbile caret is pressed or released. But when dragging this caret, no chrome event is fired. Since magnifying glass listens to moving this caret, I would like `dargcaret` for GeckoView. Also, Users' dragging point is necessary to set better position of magnifying glass windows. So I also want client point of dragging point on `presscaret` and `dragcaret` event. This event and properties are on layout.accessiblecaret.magnifier.enabled=true, So this can be only for GeckoView. Differential Revision: https://phabricator.services.mozilla.com/D137965 --- dom/webidl/CaretStateChangedEvent.webidl | 9 +- layout/base/AccessibleCaretManager.cpp | 16 +- layout/base/AccessibleCaretManager.h | 5 +- .../base/gtest/TestAccessibleCaretManager.cpp | 140 +++++++++--------- .../base/tests/accessiblecaret_magnifier.html | 91 ++++++++++++ layout/base/tests/mochitest.ini | 2 + .../tests/test_accessiblecaret_magnifier.html | 33 +++++ modules/libpref/init/StaticPrefList.yaml | 7 + 8 files changed, 228 insertions(+), 75 deletions(-) create mode 100644 layout/base/tests/accessiblecaret_magnifier.html create mode 100644 layout/base/tests/test_accessiblecaret_magnifier.html diff --git a/dom/webidl/CaretStateChangedEvent.webidl b/dom/webidl/CaretStateChangedEvent.webidl index 5fdb9f34b3cb..0a661fe73733 100644 --- a/dom/webidl/CaretStateChangedEvent.webidl +++ b/dom/webidl/CaretStateChangedEvent.webidl @@ -11,7 +11,8 @@ enum CaretChangedReason { "taponcaret", "presscaret", "releasecaret", - "scroll" + "scroll", + "dragcaret" }; dictionary CaretStateChangedEventInit : EventInit { @@ -23,6 +24,8 @@ dictionary CaretStateChangedEventInit : EventInit { boolean selectionVisible = false; boolean selectionEditable = false; DOMString selectedTextContent = ""; + long clientX = 0; + long clientY = 0; }; [ChromeOnly, @@ -40,4 +43,8 @@ interface CaretStateChangedEvent : Event { readonly attribute boolean selectionVisible; readonly attribute boolean selectionEditable; readonly attribute DOMString selectedTextContent; + [Pref="layout.accessiblecaret.magnifier.enabled"] + readonly attribute long clientX; + [Pref="layout.accessiblecaret.magnifier.enabled"] + readonly attribute long clientY; }; diff --git a/layout/base/AccessibleCaretManager.cpp b/layout/base/AccessibleCaretManager.cpp index 918ee8e518c3..0d1875333a44 100644 --- a/layout/base/AccessibleCaretManager.cpp +++ b/layout/base/AccessibleCaretManager.cpp @@ -497,7 +497,7 @@ nsresult AccessibleCaretManager::PressCaret(const nsPoint& aPoint, mOffsetYToCaretLogicalPosition = mActiveCaret->LogicalPosition().y - aPoint.y; SetSelectionDragState(true); - DispatchCaretStateChangedEvent(CaretChangedReason::Presscaret); + DispatchCaretStateChangedEvent(CaretChangedReason::Presscaret, &aPoint); rv = NS_OK; } @@ -518,6 +518,10 @@ nsresult AccessibleCaretManager::DragCaret(const nsPoint& aPoint) { // We want to scroll the page even if we failed to drag the caret. StartSelectionAutoScrollTimer(aPoint); UpdateCarets(); + + if (StaticPrefs::layout_accessiblecaret_magnifier_enabled()) { + DispatchCaretStateChangedEvent(CaretChangedReason::Dragcaret, &aPoint); + } return NS_OK; } @@ -537,7 +541,7 @@ nsresult AccessibleCaretManager::TapCaret(const nsPoint& aPoint) { nsresult rv = NS_ERROR_FAILURE; if (GetCaretMode() == CaretMode::Cursor) { - DispatchCaretStateChangedEvent(CaretChangedReason::Taponcaret); + DispatchCaretStateChangedEvent(CaretChangedReason::Taponcaret, &aPoint); rv = NS_OK; } @@ -1427,7 +1431,7 @@ void AccessibleCaretManager::StopSelectionAutoScrollTimer() const { } void AccessibleCaretManager::DispatchCaretStateChangedEvent( - CaretChangedReason aReason) { + CaretChangedReason aReason, const nsPoint* aPoint) { if (MaybeFlushLayout() == Terminated::Yes) { return; } @@ -1488,6 +1492,12 @@ void AccessibleCaretManager::DispatchCaretStateChangedEvent( init.mCaretVisuallyVisible = mCarets.HasVisuallyVisibleCaret(); init.mSelectedTextContent = StringifiedSelection(); + if (aPoint) { + CSSIntPoint pt = CSSPixel::FromAppUnitsRounded(*aPoint); + init.mClientX = pt.x; + init.mClientY = pt.y; + } + RefPtr event = CaretStateChangedEvent::Constructor( doc, u"mozcaretstatechanged"_ns, init); diff --git a/layout/base/AccessibleCaretManager.h b/layout/base/AccessibleCaretManager.h index 049c4a44be63..909aeb883895 100644 --- a/layout/base/AccessibleCaretManager.h +++ b/layout/base/AccessibleCaretManager.h @@ -304,8 +304,11 @@ class AccessibleCaretManager { // This function will flush layout, so caller must ensure the PresShell is // still valid after calling this method. + // @param aPoint The event point when the user is pressing or dragging a + // caret, which is relative to the root frame. MOZ_CAN_RUN_SCRIPT - virtual void DispatchCaretStateChangedEvent(dom::CaretChangedReason aReason); + virtual void DispatchCaretStateChangedEvent(dom::CaretChangedReason aReason, + const nsPoint* aPoint = nullptr); // --------------------------------------------------------------------------- // Member variables diff --git a/layout/base/gtest/TestAccessibleCaretManager.cpp b/layout/base/gtest/TestAccessibleCaretManager.cpp index d23558a18294..464ad68fb043 100644 --- a/layout/base/gtest/TestAccessibleCaretManager.cpp +++ b/layout/base/gtest/TestAccessibleCaretManager.cpp @@ -105,8 +105,8 @@ class AccessibleCaretManagerTester : public ::testing::Test { Terminated MaybeFlushLayout() override { return Terminated::No; } MOCK_CONST_METHOD0(GetCaretMode, CaretMode()); - MOCK_METHOD1(DispatchCaretStateChangedEvent, - void(CaretChangedReason aReason)); + MOCK_METHOD2(DispatchCaretStateChangedEvent, + void(CaretChangedReason aReason, const nsPoint* aPoint)); MOCK_CONST_METHOD1(HasNonEmptyTextContent, bool(nsINode* aNode)); }; // class MockAccessibleCaretManager @@ -148,7 +148,7 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { .WillRepeatedly(Return(CaretMode::Selection)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(3); mManager.UpdateCarets(); @@ -176,33 +176,33 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { InSequence dummy; EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("update")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Visibilitychange)) + CaretChangedReason::Visibilitychange, nullptr)) .Times(1); EXPECT_CALL(check, Call("mouse down")); - EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_)).Times(0); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0); EXPECT_CALL(check, Call("reflow")); - EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_)).Times(0); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0); EXPECT_CALL(check, Call("blur")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("mouse up")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("reflow2")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); } @@ -256,33 +256,33 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { InSequence dummy; EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("update")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Visibilitychange)) + CaretChangedReason::Visibilitychange, nullptr)) .Times(1); EXPECT_CALL(check, Call("mouse down")); - EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_)).Times(0); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0); EXPECT_CALL(check, Call("reflow")); - EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_)).Times(0); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0); EXPECT_CALL(check, Call("blur")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("mouse up")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("reflow2")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); } @@ -330,18 +330,18 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { InSequence dummy; EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("update")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Visibilitychange)) + CaretChangedReason::Visibilitychange, nullptr)) .Times(1); EXPECT_CALL(check, Call("keyboard")); // No CaretStateChanged events should be dispatched since the caret has // being hidden in cursor mode. - EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_)).Times(0); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0); } // Simulate typing the end of the input. @@ -378,15 +378,15 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { .WillOnce(Return(PositionChangedResult::Invisible)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("updatecarets")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("scrollstart1")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("reflow1")); // After scroll ended, first caret is visible and second caret is out of @@ -395,20 +395,20 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { .WillOnce(Return(PositionChangedResult::Invisible)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("scrollend1")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("scrollstart2")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("reflow2")); // After the scroll ended, both carets are visible. EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("scrollend2")); } @@ -466,18 +466,18 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { .WillOnce(Return(PositionChangedResult::Invisible)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("updatecarets")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("scrollstart1")); - EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_)).Times(0); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0); EXPECT_CALL(check, Call("scrollPositionChanged1")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("reflow1")); // After scroll ended, first caret is visible and second caret is out of @@ -486,23 +486,23 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { .WillOnce(Return(PositionChangedResult::Invisible)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("scrollend1")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("scrollstart2")); - EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_)).Times(0); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0); EXPECT_CALL(check, Call("scrollPositionChanged2")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("reflow2")); // After the scroll ended, both carets are visible. EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("scrollend2")); } @@ -564,12 +564,12 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { InSequence dummy; EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("updatecarets")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)) + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)) .Times(1); EXPECT_CALL(check, Call("scrollstart1")); @@ -577,12 +577,12 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _)) .WillRepeatedly(Return(PositionChangedResult::Invisible)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("scrollend1")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)) + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)) .Times(1); EXPECT_CALL(check, Call("scrollstart2")); @@ -590,7 +590,7 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _)) .WillRepeatedly(Return(PositionChangedResult::Position)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("scrollend2")); } @@ -628,12 +628,12 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { InSequence dummy; EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)) + CaretChangedReason::Updateposition, nullptr)) .Times(1); EXPECT_CALL(check, Call("updatecarets")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Visibilitychange)) + CaretChangedReason::Visibilitychange, nullptr)) .Times(1); EXPECT_CALL(check, Call("hidecarets")); @@ -689,33 +689,33 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { InSequence dummy; EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("updatecarets")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("scrollstart1")); EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _)) .WillOnce(Return(PositionChangedResult::Invisible)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("scrollend1")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("scrollstart2")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("scrollend2")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("scrollstart3")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("scrollend3")); } @@ -770,37 +770,37 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { InSequence dummy; EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("singletap updatecarets")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("longtap updatecarets")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("longtap scrollstart1")); EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _)) .WillOnce(Return(PositionChangedResult::Invisible)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("longtap scrollend1")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("longtap scrollstart2")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("longtap scrollend2")); - EXPECT_CALL(mManager, - DispatchCaretStateChangedEvent(CaretChangedReason::Scroll)); + EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( + CaretChangedReason::Scroll, nullptr)); EXPECT_CALL(check, Call("longtap scrollstart3")); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( - CaretChangedReason::Updateposition)); + CaretChangedReason::Updateposition, nullptr)); EXPECT_CALL(check, Call("longtap scrollend3")); } diff --git a/layout/base/tests/accessiblecaret_magnifier.html b/layout/base/tests/accessiblecaret_magnifier.html new file mode 100644 index 000000000000..855a027725a6 --- /dev/null +++ b/layout/base/tests/accessiblecaret_magnifier.html @@ -0,0 +1,91 @@ + + + + + + +

+

foobarbaz
+

+ + + diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini index 6845928bc1c2..4e9c4882bcf3 100644 --- a/layout/base/tests/mochitest.ini +++ b/layout/base/tests/mochitest.ini @@ -8,6 +8,8 @@ support-files = selection-utils.js !/gfx/layers/apz/test/mochitest/apz_test_utils.js +[test_accessiblecaret_magnifier.html] +support-files = accessiblecaret_magnifier.html [test_after_paint_pref.html] [test_border_radius_hit_testing.html] support-files = border_radius_hit_testing_iframe.html diff --git a/layout/base/tests/test_accessiblecaret_magnifier.html b/layout/base/tests/test_accessiblecaret_magnifier.html new file mode 100644 index 000000000000..2ac97cccc504 --- /dev/null +++ b/layout/base/tests/test_accessiblecaret_magnifier.html @@ -0,0 +1,33 @@ + + + + + Test for magnifier event + + + + + +Mozilla Bug 1639087 +

+

+

+ + + diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index ae1e683a32e8..4ba1bda0dff8 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -7221,6 +7221,13 @@ value: false mirror: always +# To support magnify glass, whether we dispatch additional chrome event such as +# dragcaret. +- name: layout.accessiblecaret.magnifier.enabled + type: bool + value: @IS_ANDROID@ + mirror: always + # One of several prefs affecting the maximum area to pre-render when animating # a large element on the compositor. # This pref enables transform (and transform like properties) animations on a From 8abdcc7d3eea41e5ef7ab53a295bb52e8713566b Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Fri, 8 Apr 2022 05:11:49 +0000 Subject: [PATCH 04/11] Bug 1639087 - Add Magnifying glass support in GeckoView. r=geckoview-reviewers,agi,owlish Android P+ supports magnify glass and Chrome already supports it. When accessible caret events are fired for pressing or dragging it, we show Android's magnifying glass. Differential Revision: https://phabricator.services.mozilla.com/D137966 --- .../actors/SelectionActionDelegateChild.jsm | 81 ++++++++++- .../org/mozilla/geckoview/GeckoSession.java | 131 +++++++++++++++++- .../java/org/mozilla/geckoview/GeckoView.java | 12 ++ 3 files changed, 216 insertions(+), 8 deletions(-) diff --git a/mobile/android/actors/SelectionActionDelegateChild.jsm b/mobile/android/actors/SelectionActionDelegateChild.jsm index e5ecea1e175a..35b67a58bd28 100644 --- a/mobile/android/actors/SelectionActionDelegateChild.jsm +++ b/mobile/android/actors/SelectionActionDelegateChild.jsm @@ -11,6 +11,10 @@ const { XPCOMUtils } = ChromeUtils.import( const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); const EXPORTED_SYMBOLS = ["SelectionActionDelegateChild"]; +const MAGNIFIER_PREF = "layout.accessiblecaret.magnifier.enabled"; +const ACCESSIBLECARET_HEIGHT_PREF = "layout.accessiblecaret.height"; +const PREFS = [MAGNIFIER_PREF, ACCESSIBLECARET_HEIGHT_PREF]; + // Dispatches GeckoView:ShowSelectionAction and GeckoView:HideSelectionAction to // the GeckoSession on accessible caret changes. class SelectionActionDelegateChild extends GeckoViewActorChild { @@ -20,6 +24,27 @@ class SelectionActionDelegateChild extends GeckoViewActorChild { this._seqNo = 0; this._isActive = false; this._previousMessage = ""; + + // Bug 1570744 - JSWindowActorChild's cannot be used as nsIObserver's + // directly, so we create a new function here instead to act as our + // nsIObserver, which forwards the notification to the observe method. + this._observerFunction = (subject, topic, data) => { + this.observe(subject, topic, data); + }; + for (const pref of PREFS) { + Services.prefs.addObserver(pref, this._observerFunction); + } + + this._magnifierEnabled = Services.prefs.getBoolPref(MAGNIFIER_PREF); + this._accessiblecaretHeight = parseFloat( + Services.prefs.getCharPref(ACCESSIBLECARET_HEIGHT_PREF, "0") + ); + } + + didDestroy() { + for (const pref of PREFS) { + Services.prefs.removeObserver(pref, this._observerFunction); + } } _actions = [ @@ -201,6 +226,25 @@ class SelectionActionDelegateChild extends GeckoViewActorChild { return offset; } + _handleMagnifier(aEvent, aReason) { + if (["presscaret", "dragcaret"].includes(aReason)) { + debug`_handleMagnifier: ${aReason}`; + const offset = this._getFrameOffset(aEvent); + this.eventDispatcher.sendRequest({ + type: "GeckoView:ShowMagnifier", + clientPoint: { + x: aEvent.clientX + offset.left, + y: aEvent.clientY + offset.top - this._accessiblecaretHeight, + }, + }); + } else if (aReason == "releasecaret") { + debug`_handleMagnifier: ${aReason}`; + this.eventDispatcher.sendRequest({ + type: "GeckoView:HideMagnifier", + }); + } + } + /** * Receive and act on AccessibleCarets caret state-change * (mozcaretstatechanged and pagehide) events. @@ -243,6 +287,10 @@ class SelectionActionDelegateChild extends GeckoViewActorChild { debug`handleEvent: ${reason}`; + if (this._magnifierEnabled) { + this._handleMagnifier(aEvent, reason); + } + if ( [ "longpressonemptycontent", @@ -276,13 +324,9 @@ class SelectionActionDelegateChild extends GeckoViewActorChild { actions: actions.map(action => action.id), }; - try { - if (msg.clientRect) { - msg.clientRect.bottom += parseFloat( - Services.prefs.getCharPref("layout.accessiblecaret.height", "0") - ); - } - } catch (e) {} + if (msg.clientRect) { + msg.clientRect.bottom += this._accessiblecaretHeight; + } if (this._isActive && JSON.stringify(msg) === this._previousMessage) { // Don't call again if we're already active and things haven't changed. @@ -337,10 +381,33 @@ class SelectionActionDelegateChild extends GeckoViewActorChild { type: "GeckoView:HideSelectionAction", reason, }); + } else if (reason == "dragcaret") { + // nothing for selection action } else { warn`Unknown reason: ${reason}`; } } + + observe(aSubject, aTopic, aData) { + if (aTopic != "nsPref:changed") { + return; + } + + switch (aData) { + case ACCESSIBLECARET_HEIGHT_PREF: + this._accessiblecaretHeight = parseFloat( + Services.prefs.getCharPref(ACCESSIBLECARET_HEIGHT_PREF, "0") + ); + break; + case MAGNIFIER_PREF: + this._magnifierEnabled = Services.prefs.getBoolPref(MAGNIFIER_PREF); + break; + } + // Reset magnifier + this.eventDispatcher.sendRequest({ + type: "GeckoView:HideMagnifier", + }); + } } const { debug, warn } = SelectionActionDelegateChild.initLogging( diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java index 7f4b3b97db76..ee425b31f827 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java @@ -13,6 +13,7 @@ import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Matrix; +import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.net.Uri; @@ -33,6 +34,7 @@ import android.view.ViewStructure; import android.view.inputmethod.CursorAnchorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; +import android.widget.Magnifier; import androidx.annotation.AnyThread; import androidx.annotation.IntDef; import androidx.annotation.LongDef; @@ -133,6 +135,95 @@ public class GeckoSession { private SessionAccessibility mAccessibility; private SessionFinder mFinder; + /** {@code SessionMagnifier} handles magnifying glass. */ + /* package */ interface SessionMagnifier { + /** + * Get the current {@link android.view.View} for magnifying glass. + * + * @return Current View for magnifying glass or null if not set. + */ + @UiThread + default @Nullable View getView() { + return null; + } + + /** + * Set the current {@link android.view.View} for magnifying glass. + * + * @param view View for magnifying glass or null to clear current View. + */ + @UiThread + default void setView(final @NonNull View view) {} + + /** + * Show magnifying glass. + * + * @param sourceCenter The source center of view that magnifying glass is attached + */ + @UiThread + default void show(final @NonNull PointF sourceCenter) {} + + /** Dismiss magnifying glass. */ + @UiThread + default void dismiss() {} + } + + @TargetApi(Build.VERSION_CODES.P) + private static class SessionMagnifierP implements GeckoSession.SessionMagnifier { + private @Nullable View mView; + private @Nullable Magnifier mMagnifier; + + @Override + @UiThread + public @Nullable View getView() { + ThreadUtils.assertOnUiThread(); + + return mView; + } + + @Override + @UiThread + public void setView(final @NonNull View view) { + ThreadUtils.assertOnUiThread(); + + if (mMagnifier != null) { + mMagnifier.dismiss(); + mMagnifier = null; + } + mView = view; + } + + @Override + @UiThread + public void show(final @NonNull PointF sourceCenter) { + ThreadUtils.assertOnUiThread(); + + if (mView == null) { + return; + } + if (mMagnifier == null) { + mMagnifier = new Magnifier(mView); + } + + mMagnifier.show(sourceCenter.x, sourceCenter.y); + } + + @Override + @UiThread + public void dismiss() { + ThreadUtils.assertOnUiThread(); + + if (mMagnifier == null) { + return; + } + + mMagnifier.dismiss(); + mMagnifier = null; + } + } + + private SessionMagnifier mMagnifier; + private String mId; /* package */ String getId() { return mId; @@ -795,7 +886,10 @@ public class GeckoSession { "GeckoViewSelectionAction", this, new String[] { - "GeckoView:HideSelectionAction", "GeckoView:ShowSelectionAction", + "GeckoView:HideSelectionAction", + "GeckoView:ShowSelectionAction", + "GeckoView:HideMagnifier", + "GeckoView:ShowMagnifier", }) { @Override public void handleMessage( @@ -827,6 +921,21 @@ public class GeckoSession { } delegate.onHideAction(GeckoSession.this, reason); + } else if ("GeckoView:ShowMagnifier".equals(event)) { + final GeckoBundle ptBundle = message.getBundle("clientPoint"); + if (ptBundle == null) { + throw new IllegalArgumentException("Invalid argument"); + } + + final Matrix matrix = new Matrix(); + GeckoSession.this.getClientToSurfaceMatrix(matrix); + final float[] origin = + new float[] {(float) ptBundle.getDouble("x"), (float) ptBundle.getDouble("y")}; + matrix.mapPoints(origin); + + GeckoSession.this.getMagnifier().show(new PointF(origin[0], origin[1])); + } else if ("GeckoView:HideMagnifier".equals(event)) { + GeckoSession.this.getMagnifier().dismiss(); } } }; @@ -1452,6 +1561,26 @@ public class GeckoSession { return mAccessibility; } + /** + * Get the SessionMagnifier instance for this session. + * + * @return SessionMagnifier instance. + */ + @UiThread + /* package */ @NonNull + SessionMagnifier getMagnifier() { + ThreadUtils.assertOnUiThread(); + if (mMagnifier == null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + mMagnifier = new SessionMagnifierP(); + } else { + mMagnifier = new SessionMagnifier() {}; + } + } + + return mMagnifier; + } + @Retention(RetentionPolicy.SOURCE) @IntDef( flag = true, diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java index adbcf6ea6abe..e0f8807fe3ec 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java @@ -323,6 +323,10 @@ public class GeckoView extends FrameLayout { } addView(mSurfaceWrapper.getView()); + + if (mSession != null) { + mSession.getMagnifier().setView(mSurfaceWrapper.getView()); + } } /** @@ -428,6 +432,10 @@ public class GeckoView extends FrameLayout { mSession.setAutofillDelegate(null); } + if (mSession.getMagnifier().getView() == mSurfaceWrapper.getView()) { + session.getMagnifier().setView(null); + } + if (isFocused()) { mSession.setFocused(false); } @@ -525,6 +533,10 @@ public class GeckoView extends FrameLayout { session.setAutofillDelegate(mAutofillDelegate); } + if (session.getMagnifier().getView() == null) { + session.getMagnifier().setView(mSurfaceWrapper.getView()); + } + if (isFocused()) { session.setFocused(true); } From 3c0087116298d277965ba4b4cf44b8385069cc02 Mon Sep 17 00:00:00 2001 From: Jens Stutte Date: Fri, 8 Apr 2022 06:20:19 +0000 Subject: [PATCH 05/11] Bug 1696771: Always null check the ContentProcessManager singleton before use. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D143180 --- docshell/base/CanonicalBrowsingContext.cpp | 3 + dom/base/nsFrameLoader.cpp | 3 + dom/ipc/BrowserBridgeParent.cpp | 3 + dom/ipc/BrowserParent.cpp | 5 +- dom/ipc/ContentParent.cpp | 127 +++++++++++------- .../webrtc/transport/ipc/WebrtcTCPSocket.cpp | 6 +- gfx/ipc/CrossProcessPaint.cpp | 9 +- 7 files changed, 104 insertions(+), 52 deletions(-) diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp index 5cd83a13645f..6048a2c0e8eb 100644 --- a/docshell/base/CanonicalBrowsingContext.cpp +++ b/docshell/base/CanonicalBrowsingContext.cpp @@ -184,6 +184,9 @@ ContentParent* CanonicalBrowsingContext::GetContentParent() const { } ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); + if (!cpm) { + return nullptr; + } return cpm->GetContentProcessById(ContentParentId(mProcessId)); } diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index c558a14c97c4..0ebd25360dbb 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -2750,6 +2750,9 @@ bool nsFrameLoader::TryRemoteBrowserInternal() { RefPtr contentParent; if (mChildID != 0) { ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); + if (cpm) { + return false; + } contentParent = cpm->GetContentProcessById(ContentParentId(mChildID)); } mRemoteBrowser = diff --git a/dom/ipc/BrowserBridgeParent.cpp b/dom/ipc/BrowserBridgeParent.cpp index 1039f6e24720..e856864748ce 100644 --- a/dom/ipc/BrowserBridgeParent.cpp +++ b/dom/ipc/BrowserBridgeParent.cpp @@ -83,6 +83,9 @@ nsresult BrowserBridgeParent::InitWithProcess( } ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); + if (!cpm) { + return NS_ERROR_UNEXPECTED; + } cpm->RegisterRemoteFrame(browserParent); RefPtr windowParent = diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 57cd0a5f64e4..45eb3de92a23 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -675,7 +675,10 @@ mozilla::ipc::IPCResult BrowserParent::RecvEnsureLayersConnected( void BrowserParent::ActorDestroy(ActorDestroyReason why) { Manager()->NotifyTabDestroyed(mTabId, mMarkedDestroying); - ContentProcessManager::GetSingleton()->UnregisterRemoteFrame(mTabId); + ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); + if (cpm) { + cpm->UnregisterRemoteFrame(mTabId); + } if (mRemoteLayerTreeOwner.IsInitialized()) { auto layersId = mRemoteLayerTreeOwner.GetLayersId(); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index e694f441ee36..87fbc45ef51d 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1530,6 +1530,9 @@ already_AddRefed ContentParent::CreateBrowser( } ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); + if (NS_WARN_IF(!cpm)) { + return nullptr; + } cpm->RegisterRemoteFrame(browserParent); nsCOMPtr initialPrincipal = @@ -2090,7 +2093,9 @@ void ContentParent::ActorDestroy(ActorDestroyReason why) { mSubprocess = nullptr; ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - cpm->RemoveContentProcess(this->ChildID()); + if (cpm) { + cpm->RemoveContentProcess(this->ChildID()); + } if (mDriverCrashGuard) { mDriverCrashGuard->NotifyCrashed(); @@ -2481,6 +2486,8 @@ void ContentParent::AppendSandboxParams(std::vector& aArgs) { bool ContentParent::BeginSubprocessLaunch(ProcessPriority aPriority) { AUTO_PROFILER_LABEL("ContentParent::LaunchSubprocess", OTHER); + // XXX: This check works only late, as GetSingleton will return nullptr + // only after ClearOnShutdown happened. See bug 1632740. if (!ContentProcessManager::GetSingleton()) { NS_WARNING( "Shutdown has begun, we shouldn't spawn any more child processes"); @@ -2613,7 +2620,13 @@ bool ContentParent::LaunchSubprocessResolve(bool aIsSync, base::GetProcId(mSubprocess->GetChildProcessHandle()); Open(mSubprocess->TakeInitialPort(), procId); - ContentProcessManager::GetSingleton()->AddContentProcess(this); + ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); + if (!cpm) { + NS_WARNING("immediately shutting-down caused by our shutdown"); + ShutDownProcess(SEND_SHUTDOWN_MESSAGE); + return false; + } + cpm->AddContentProcess(this); #ifdef MOZ_CODE_COVERAGE Unused << SendShareCodeCoverageMutex( @@ -4026,7 +4039,7 @@ mozilla::ipc::IPCResult ContentParent::RecvConstructPopupBrowser( // window.open(). // We need to register remote frame with the child generated tab id. auto* cpm = ContentProcessManager::GetSingleton(); - if (!cpm->RegisterRemoteFrame(parent)) { + if (!cpm || !cpm->RegisterRemoteFrame(parent)) { return IPC_FAIL(this, "RegisterRemoteFrame Failed"); } } @@ -5156,9 +5169,12 @@ ContentParent::AllocPContentPermissionRequestParent( const IPC::Principal& aPrincipal, const IPC::Principal& aTopLevelPrincipal, const bool& aIsHandlingUserInput, const bool& aMaybeUnsafePermissionDelegate, const TabId& aTabId) { + RefPtr tp; ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - RefPtr tp = - cpm->GetTopLevelBrowserParentByProcessAndTabId(this->ChildID(), aTabId); + if (cpm) { + tp = + cpm->GetTopLevelBrowserParentByProcessAndTabId(this->ChildID(), aTabId); + } if (!tp) { return nullptr; } @@ -6812,9 +6828,11 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowClose( // browsing contexts of bc. ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendWindowClose(context, aTrustedCaller); + if (cpm) { + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendWindowClose(context, aTrustedCaller); + } return IPC_OK(); } @@ -6831,9 +6849,11 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowFocus( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendWindowFocus(context, aCallerType, aActionId); + if (cpm) { + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendWindowFocus(context, aCallerType, aActionId); + } return IPC_OK(); } @@ -6848,9 +6868,11 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowBlur( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendWindowBlur(context, aCallerType); + if (cpm) { + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendWindowBlur(context, aCallerType); + } return IPC_OK(); } @@ -6868,9 +6890,11 @@ mozilla::ipc::IPCResult ContentParent::RecvRaiseWindow( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendRaiseWindow(context, aCallerType, aActionId); + if (cpm) { + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendRaiseWindow(context, aCallerType, aActionId); + } return IPC_OK(); } @@ -6891,21 +6915,23 @@ mozilla::ipc::IPCResult ContentParent::RecvAdjustWindowFocus( processes.InsertOrUpdate(this, true); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - CanonicalBrowsingContext* context = aContext.get_canonical(); - while (context) { - BrowsingContext* parent = context->GetParent(); - if (!parent) { - break; - } + if (cpm) { + CanonicalBrowsingContext* context = aContext.get_canonical(); + while (context) { + BrowsingContext* parent = context->GetParent(); + if (!parent) { + break; + } - CanonicalBrowsingContext* canonicalParent = parent->Canonical(); - ContentParent* cp = cpm->GetContentProcessById( - ContentParentId(canonicalParent->OwnerProcessId())); - if (cp && !processes.Get(cp)) { - Unused << cp->SendAdjustWindowFocus(context, aIsVisible, aActionId); - processes.InsertOrUpdate(cp, true); + CanonicalBrowsingContext* canonicalParent = parent->Canonical(); + ContentParent* cp = cpm->GetContentProcessById( + ContentParentId(canonicalParent->OwnerProcessId())); + if (cp && !processes.Get(cp)) { + Unused << cp->SendAdjustWindowFocus(context, aIsVisible, aActionId); + processes.InsertOrUpdate(cp, true); + } + context = canonicalParent; } - context = canonicalParent; } return IPC_OK(); } @@ -6921,9 +6947,11 @@ mozilla::ipc::IPCResult ContentParent::RecvClearFocus( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendClearFocus(context); + if (cpm) { + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendClearFocus(context); + } return IPC_OK(); } @@ -7046,11 +7074,11 @@ mozilla::ipc::IPCResult ContentParent::RecvSetFocusedElement( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendSetFocusedElement(context, aNeedsFocus); - + if (cpm) { + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendSetFocusedElement(context, aNeedsFocus); + } return IPC_OK(); } @@ -7066,11 +7094,12 @@ mozilla::ipc::IPCResult ContentParent::RecvFinalizeFocusOuter( LOGFOCUS(("ContentParent::RecvFinalizeFocusOuter")); CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->EmbedderProcessId())); - if (cp) { - Unused << cp->SendFinalizeFocusOuter(context, aCanFocus, aCallerType); + if (cpm) { + ContentParent* cp = cpm->GetContentProcessById( + ContentParentId(context->EmbedderProcessId())); + if (cp) { + Unused << cp->SendFinalizeFocusOuter(context, aCanFocus, aCallerType); + } } return IPC_OK(); } @@ -7111,6 +7140,9 @@ mozilla::ipc::IPCResult ContentParent::RecvBlurToParent( aFocusedBrowsingContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); + if (!cpm) { + return IPC_OK(); + } // If aBrowsingContextToClear and aAncestorBrowsingContextToFocusHandled // didn't get handled in the process that sent this IPC message and they @@ -7158,10 +7190,11 @@ mozilla::ipc::IPCResult ContentParent::RecvMaybeExitFullscreen( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendMaybeExitFullscreen(context); + if (cpm) { + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendMaybeExitFullscreen(context); + } return IPC_OK(); } diff --git a/dom/media/webrtc/transport/ipc/WebrtcTCPSocket.cpp b/dom/media/webrtc/transport/ipc/WebrtcTCPSocket.cpp index 26a883cece75..d33c9a1dd865 100644 --- a/dom/media/webrtc/transport/ipc/WebrtcTCPSocket.cpp +++ b/dom/media/webrtc/transport/ipc/WebrtcTCPSocket.cpp @@ -73,8 +73,10 @@ WebrtcTCPSocket::~WebrtcTCPSocket() { void WebrtcTCPSocket::SetTabId(dom::TabId aTabId) { MOZ_ASSERT(NS_IsMainThread()); dom::ContentProcessManager* cpm = dom::ContentProcessManager::GetSingleton(); - dom::ContentParentId cpId = cpm->GetTabProcessId(aTabId); - mAuthProvider = cpm->GetBrowserParentByProcessAndTabId(cpId, aTabId); + if (cpm) { + dom::ContentParentId cpId = cpm->GetTabProcessId(aTabId); + mAuthProvider = cpm->GetBrowserParentByProcessAndTabId(cpId, aTabId); + } } nsresult WebrtcTCPSocket::Write(nsTArray&& aWriteData) { diff --git a/gfx/ipc/CrossProcessPaint.cpp b/gfx/ipc/CrossProcessPaint.cpp index 608fb30af425..23eafc408f03 100644 --- a/gfx/ipc/CrossProcessPaint.cpp +++ b/gfx/ipc/CrossProcessPaint.cpp @@ -367,13 +367,18 @@ void CrossProcessPaint::LostFragment(dom::WindowGlobalParent* aWGP) { void CrossProcessPaint::QueueDependencies( const nsTHashSet& aDependencies) { + dom::ContentProcessManager* cpm = dom::ContentProcessManager::GetSingleton(); + if (!cpm) { + CPP_LOG( + "Skipping QueueDependencies with no" + " current ContentProcessManager.\n"); + return; + } for (const auto& key : aDependencies) { auto dependency = dom::TabId(key); // Get the current BrowserParent of the remote browser that was marked // as a dependency - dom::ContentProcessManager* cpm = - dom::ContentProcessManager::GetSingleton(); dom::ContentParentId cpId = cpm->GetTabProcessId(dependency); RefPtr browser = cpm->GetBrowserParentByProcessAndTabId(cpId, dependency); From 0d0ad9c7f36adc5f4e7500f46ad79cb484e19154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 8 Apr 2022 06:51:15 +0000 Subject: [PATCH 06/11] Bug 1763746 - Stop preferring dark background for SelectedItem/SelectedItemText. r=stransky This was added because ElementaryOS themes have bright selected backgrounds and dark text (for light themes), but we use the accent colors for some places where that is not appropriate and a darker color is, like checkbox backgrounds or form control borders. Bug 1741293 split the selected item text / background colors from the accent colors, so now we can use the real selected item colors and only do this on the accent color. I wanted to split this out from bug 1741293 to minimize behavior changes in there. Also while at it, blend opaque foreground with the appropriate background on EnsureColorPairIsOpaque. Differential Revision: https://phabricator.services.mozilla.com/D143255 --- widget/gtk/nsLookAndFeel.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp index fd251bfb13d5..243314a3198a 100644 --- a/widget/gtk/nsLookAndFeel.cpp +++ b/widget/gtk/nsLookAndFeel.cpp @@ -1620,7 +1620,7 @@ static void EnsureColorPairIsOpaque(nscolor& aBg, nscolor& aFg) { // Blend with white, ensuring the color is opaque, so that the UI doesn't have // to care about alpha. aBg = NS_ComposeColors(NS_RGB(0xff, 0xff, 0xff), aBg); - aFg = NS_ComposeColors(NS_RGB(0xff, 0xff, 0xff), aFg); + aFg = NS_ComposeColors(aBg, aFg); } static void PreferDarkerBackground(nscolor& aBg, nscolor& aFg) { @@ -1903,7 +1903,6 @@ void nsLookAndFeel::PerThemeData::Init() { mSelectedItemText = mTextSelectedText; } - PreferDarkerBackground(mSelectedItem, mSelectedItemText); EnsureColorPairIsOpaque(mSelectedItem, mSelectedItemText); // In a similar fashion, default accent color is the selected item/text @@ -1919,8 +1918,8 @@ void nsLookAndFeel::PerThemeData::Init() { mAccentColorForeground = mSelectedItemText; } - PreferDarkerBackground(mAccentColor, mAccentColorForeground); EnsureColorPairIsOpaque(mAccentColor, mAccentColorForeground); + PreferDarkerBackground(mAccentColor, mAccentColorForeground); } // Button text color From c463ca58c7227e9611037a86921adf21e7a9ec5b Mon Sep 17 00:00:00 2001 From: Norisz Fay Date: Fri, 8 Apr 2022 10:44:55 +0300 Subject: [PATCH 07/11] Backed out changeset 2531ddbeeffa (bug 1696771) for causing multiple failures CLOSED TREE --- docshell/base/CanonicalBrowsingContext.cpp | 3 - dom/base/nsFrameLoader.cpp | 3 - dom/ipc/BrowserBridgeParent.cpp | 3 - dom/ipc/BrowserParent.cpp | 5 +- dom/ipc/ContentParent.cpp | 129 +++++++----------- .../webrtc/transport/ipc/WebrtcTCPSocket.cpp | 6 +- gfx/ipc/CrossProcessPaint.cpp | 9 +- 7 files changed, 53 insertions(+), 105 deletions(-) diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp index 6048a2c0e8eb..5cd83a13645f 100644 --- a/docshell/base/CanonicalBrowsingContext.cpp +++ b/docshell/base/CanonicalBrowsingContext.cpp @@ -184,9 +184,6 @@ ContentParent* CanonicalBrowsingContext::GetContentParent() const { } ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (!cpm) { - return nullptr; - } return cpm->GetContentProcessById(ContentParentId(mProcessId)); } diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index 0ebd25360dbb..c558a14c97c4 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -2750,9 +2750,6 @@ bool nsFrameLoader::TryRemoteBrowserInternal() { RefPtr contentParent; if (mChildID != 0) { ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - return false; - } contentParent = cpm->GetContentProcessById(ContentParentId(mChildID)); } mRemoteBrowser = diff --git a/dom/ipc/BrowserBridgeParent.cpp b/dom/ipc/BrowserBridgeParent.cpp index e856864748ce..1039f6e24720 100644 --- a/dom/ipc/BrowserBridgeParent.cpp +++ b/dom/ipc/BrowserBridgeParent.cpp @@ -83,9 +83,6 @@ nsresult BrowserBridgeParent::InitWithProcess( } ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (!cpm) { - return NS_ERROR_UNEXPECTED; - } cpm->RegisterRemoteFrame(browserParent); RefPtr windowParent = diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 45eb3de92a23..57cd0a5f64e4 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -675,10 +675,7 @@ mozilla::ipc::IPCResult BrowserParent::RecvEnsureLayersConnected( void BrowserParent::ActorDestroy(ActorDestroyReason why) { Manager()->NotifyTabDestroyed(mTabId, mMarkedDestroying); - ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - cpm->UnregisterRemoteFrame(mTabId); - } + ContentProcessManager::GetSingleton()->UnregisterRemoteFrame(mTabId); if (mRemoteLayerTreeOwner.IsInitialized()) { auto layersId = mRemoteLayerTreeOwner.GetLayersId(); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 87fbc45ef51d..e694f441ee36 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1530,9 +1530,6 @@ already_AddRefed ContentParent::CreateBrowser( } ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (NS_WARN_IF(!cpm)) { - return nullptr; - } cpm->RegisterRemoteFrame(browserParent); nsCOMPtr initialPrincipal = @@ -2093,9 +2090,7 @@ void ContentParent::ActorDestroy(ActorDestroyReason why) { mSubprocess = nullptr; ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - cpm->RemoveContentProcess(this->ChildID()); - } + cpm->RemoveContentProcess(this->ChildID()); if (mDriverCrashGuard) { mDriverCrashGuard->NotifyCrashed(); @@ -2486,8 +2481,6 @@ void ContentParent::AppendSandboxParams(std::vector& aArgs) { bool ContentParent::BeginSubprocessLaunch(ProcessPriority aPriority) { AUTO_PROFILER_LABEL("ContentParent::LaunchSubprocess", OTHER); - // XXX: This check works only late, as GetSingleton will return nullptr - // only after ClearOnShutdown happened. See bug 1632740. if (!ContentProcessManager::GetSingleton()) { NS_WARNING( "Shutdown has begun, we shouldn't spawn any more child processes"); @@ -2620,13 +2613,7 @@ bool ContentParent::LaunchSubprocessResolve(bool aIsSync, base::GetProcId(mSubprocess->GetChildProcessHandle()); Open(mSubprocess->TakeInitialPort(), procId); - ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (!cpm) { - NS_WARNING("immediately shutting-down caused by our shutdown"); - ShutDownProcess(SEND_SHUTDOWN_MESSAGE); - return false; - } - cpm->AddContentProcess(this); + ContentProcessManager::GetSingleton()->AddContentProcess(this); #ifdef MOZ_CODE_COVERAGE Unused << SendShareCodeCoverageMutex( @@ -4039,7 +4026,7 @@ mozilla::ipc::IPCResult ContentParent::RecvConstructPopupBrowser( // window.open(). // We need to register remote frame with the child generated tab id. auto* cpm = ContentProcessManager::GetSingleton(); - if (!cpm || !cpm->RegisterRemoteFrame(parent)) { + if (!cpm->RegisterRemoteFrame(parent)) { return IPC_FAIL(this, "RegisterRemoteFrame Failed"); } } @@ -5169,12 +5156,9 @@ ContentParent::AllocPContentPermissionRequestParent( const IPC::Principal& aPrincipal, const IPC::Principal& aTopLevelPrincipal, const bool& aIsHandlingUserInput, const bool& aMaybeUnsafePermissionDelegate, const TabId& aTabId) { - RefPtr tp; ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - tp = - cpm->GetTopLevelBrowserParentByProcessAndTabId(this->ChildID(), aTabId); - } + RefPtr tp = + cpm->GetTopLevelBrowserParentByProcessAndTabId(this->ChildID(), aTabId); if (!tp) { return nullptr; } @@ -6828,11 +6812,9 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowClose( // browsing contexts of bc. ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendWindowClose(context, aTrustedCaller); - } + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendWindowClose(context, aTrustedCaller); return IPC_OK(); } @@ -6849,11 +6831,9 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowFocus( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendWindowFocus(context, aCallerType, aActionId); - } + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendWindowFocus(context, aCallerType, aActionId); return IPC_OK(); } @@ -6868,11 +6848,9 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowBlur( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendWindowBlur(context, aCallerType); - } + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendWindowBlur(context, aCallerType); return IPC_OK(); } @@ -6890,11 +6868,9 @@ mozilla::ipc::IPCResult ContentParent::RecvRaiseWindow( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendRaiseWindow(context, aCallerType, aActionId); - } + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendRaiseWindow(context, aCallerType, aActionId); return IPC_OK(); } @@ -6915,23 +6891,21 @@ mozilla::ipc::IPCResult ContentParent::RecvAdjustWindowFocus( processes.InsertOrUpdate(this, true); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - CanonicalBrowsingContext* context = aContext.get_canonical(); - while (context) { - BrowsingContext* parent = context->GetParent(); - if (!parent) { - break; - } - - CanonicalBrowsingContext* canonicalParent = parent->Canonical(); - ContentParent* cp = cpm->GetContentProcessById( - ContentParentId(canonicalParent->OwnerProcessId())); - if (cp && !processes.Get(cp)) { - Unused << cp->SendAdjustWindowFocus(context, aIsVisible, aActionId); - processes.InsertOrUpdate(cp, true); - } - context = canonicalParent; + CanonicalBrowsingContext* context = aContext.get_canonical(); + while (context) { + BrowsingContext* parent = context->GetParent(); + if (!parent) { + break; } + + CanonicalBrowsingContext* canonicalParent = parent->Canonical(); + ContentParent* cp = cpm->GetContentProcessById( + ContentParentId(canonicalParent->OwnerProcessId())); + if (cp && !processes.Get(cp)) { + Unused << cp->SendAdjustWindowFocus(context, aIsVisible, aActionId); + processes.InsertOrUpdate(cp, true); + } + context = canonicalParent; } return IPC_OK(); } @@ -6947,11 +6921,9 @@ mozilla::ipc::IPCResult ContentParent::RecvClearFocus( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendClearFocus(context); - } + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendClearFocus(context); return IPC_OK(); } @@ -7074,11 +7046,11 @@ mozilla::ipc::IPCResult ContentParent::RecvSetFocusedElement( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendSetFocusedElement(context, aNeedsFocus); - } + + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendSetFocusedElement(context, aNeedsFocus); + return IPC_OK(); } @@ -7094,12 +7066,11 @@ mozilla::ipc::IPCResult ContentParent::RecvFinalizeFocusOuter( LOGFOCUS(("ContentParent::RecvFinalizeFocusOuter")); CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - ContentParent* cp = cpm->GetContentProcessById( - ContentParentId(context->EmbedderProcessId())); - if (cp) { - Unused << cp->SendFinalizeFocusOuter(context, aCanFocus, aCallerType); - } + + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->EmbedderProcessId())); + if (cp) { + Unused << cp->SendFinalizeFocusOuter(context, aCanFocus, aCallerType); } return IPC_OK(); } @@ -7140,9 +7111,6 @@ mozilla::ipc::IPCResult ContentParent::RecvBlurToParent( aFocusedBrowsingContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (!cpm) { - return IPC_OK(); - } // If aBrowsingContextToClear and aAncestorBrowsingContextToFocusHandled // didn't get handled in the process that sent this IPC message and they @@ -7190,11 +7158,10 @@ mozilla::ipc::IPCResult ContentParent::RecvMaybeExitFullscreen( CanonicalBrowsingContext* context = aContext.get_canonical(); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - if (cpm) { - ContentParent* cp = - cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); - Unused << cp->SendMaybeExitFullscreen(context); - } + + ContentParent* cp = + cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId())); + Unused << cp->SendMaybeExitFullscreen(context); return IPC_OK(); } diff --git a/dom/media/webrtc/transport/ipc/WebrtcTCPSocket.cpp b/dom/media/webrtc/transport/ipc/WebrtcTCPSocket.cpp index d33c9a1dd865..26a883cece75 100644 --- a/dom/media/webrtc/transport/ipc/WebrtcTCPSocket.cpp +++ b/dom/media/webrtc/transport/ipc/WebrtcTCPSocket.cpp @@ -73,10 +73,8 @@ WebrtcTCPSocket::~WebrtcTCPSocket() { void WebrtcTCPSocket::SetTabId(dom::TabId aTabId) { MOZ_ASSERT(NS_IsMainThread()); dom::ContentProcessManager* cpm = dom::ContentProcessManager::GetSingleton(); - if (cpm) { - dom::ContentParentId cpId = cpm->GetTabProcessId(aTabId); - mAuthProvider = cpm->GetBrowserParentByProcessAndTabId(cpId, aTabId); - } + dom::ContentParentId cpId = cpm->GetTabProcessId(aTabId); + mAuthProvider = cpm->GetBrowserParentByProcessAndTabId(cpId, aTabId); } nsresult WebrtcTCPSocket::Write(nsTArray&& aWriteData) { diff --git a/gfx/ipc/CrossProcessPaint.cpp b/gfx/ipc/CrossProcessPaint.cpp index 23eafc408f03..608fb30af425 100644 --- a/gfx/ipc/CrossProcessPaint.cpp +++ b/gfx/ipc/CrossProcessPaint.cpp @@ -367,18 +367,13 @@ void CrossProcessPaint::LostFragment(dom::WindowGlobalParent* aWGP) { void CrossProcessPaint::QueueDependencies( const nsTHashSet& aDependencies) { - dom::ContentProcessManager* cpm = dom::ContentProcessManager::GetSingleton(); - if (!cpm) { - CPP_LOG( - "Skipping QueueDependencies with no" - " current ContentProcessManager.\n"); - return; - } for (const auto& key : aDependencies) { auto dependency = dom::TabId(key); // Get the current BrowserParent of the remote browser that was marked // as a dependency + dom::ContentProcessManager* cpm = + dom::ContentProcessManager::GetSingleton(); dom::ContentParentId cpId = cpm->GetTabProcessId(dependency); RefPtr browser = cpm->GetBrowserParentByProcessAndTabId(cpId, dependency); From ae4e1b024641dc9a6423be8cb2cb4c52513b695f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Fri, 8 Apr 2022 08:43:02 +0000 Subject: [PATCH 08/11] Bug 1763609 - Part 1: Update list of unsupported features. r=mgaudet Differential Revision: https://phabricator.services.mozilla.com/D143163 --- js/src/tests/test262-update.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/js/src/tests/test262-update.py b/js/src/tests/test262-update.py index 513d7a6286df..6f4e7e1d7558 100755 --- a/js/src/tests/test262-update.py +++ b/js/src/tests/test262-update.py @@ -25,13 +25,16 @@ UNSUPPORTED_FEATURES = set( "Intl.DateTimeFormat-quarter", "Intl.Segmenter", "Intl.Locale-info", + "Intl.DurationFormat", "Atomics.waitAsync", "legacy-regexp", "json-modules", "resizable-arraybuffer", "Temporal", - "callable-boundary-realms", + "ShadowRealm", "array-find-from-last", + "array-grouping", + "regexp-v-flag", ] ) FEATURE_CHECK_NEEDED = { @@ -40,7 +43,11 @@ FEATURE_CHECK_NEEDED = { "SharedArrayBuffer": "!this.hasOwnProperty('SharedArrayBuffer')", "WeakRef": "!this.hasOwnProperty('WeakRef')", } -RELEASE_OR_BETA = set([]) +RELEASE_OR_BETA = set( + [ + "Intl.NumberFormat-v3", + ] +) SHELL_OPTIONS = { "import-assertions": "--enable-import-assertions", } From f9ec3301f19e938ef00c768aa4ccdae2a39afc5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Fri, 8 Apr 2022 08:43:02 +0000 Subject: [PATCH 09/11] Bug 1763609 - Part 2: Update Github URL. r=mgaudet "git://" protocol is no longer supported. Depends on D143163 Differential Revision: https://phabricator.services.mozilla.com/D143164 --- js/src/tests/test262-update.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/tests/test262-update.py b/js/src/tests/test262-update.py index 6f4e7e1d7558..d011bb7e8ef1 100755 --- a/js/src/tests/test262-update.py +++ b/js/src/tests/test262-update.py @@ -859,7 +859,7 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description="Update the test262 test suite.") parser.add_argument( "--url", - default="git://github.com/tc39/test262.git", + default="https://github.com/tc39/test262.git", help="URL to git repository (default: %(default)s)", ) parser.add_argument( From e24361a3a208a488376fa8dbdd8eb0937717c3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Fri, 8 Apr 2022 08:43:02 +0000 Subject: [PATCH 10/11] Bug 1763609 - Part 3: Update test262 April 2022. r=mgaudet Depends on D143164 Differential Revision: https://phabricator.services.mozilla.com/D143165 --- js/src/tests/test262/GIT-INFO | 13 +- .../compile/this-cross-realm-instance.js | 2 +- .../built-ins/Array/S15.4.1_A1.1_T1.js | 1 - .../built-ins/Array/S15.4.1_A1.1_T2.js | 2 - .../built-ins/Array/S15.4.1_A1.2_T1.js | 2 - .../built-ins/Array/S15.4.1_A2.2_T1.js | 1 - .../built-ins/Array/S15.4.2.1_A1.1_T1.js | 1 - .../built-ins/Array/S15.4.2.1_A1.1_T2.js | 2 - .../built-ins/Array/S15.4.2.1_A1.2_T1.js | 2 - .../built-ins/Array/S15.4.2.1_A2.2_T1.js | 1 - .../built-ins/Array/S15.4.3_A1.1_T2.js | 1 - .../built-ins/Array/S15.4.5.1_A1.2_T2.js | 2 - .../built-ins/Array/S15.4.5.1_A2.1_T1.js | 3 - .../built-ins/Array/S15.4.5.1_A2.2_T1.js | 3 - .../built-ins/Array/S15.4.5.1_A2.3_T1.js | 2 - .../built-ins/Array/S15.4.5.2_A1_T1.js | 5 - .../built-ins/Array/S15.4.5.2_A1_T2.js | 2 - .../built-ins/Array/S15.4.5.2_A2_T1.js | 4 - .../built-ins/Array/S15.4.5.2_A3_T1.js | 2 - .../built-ins/Array/S15.4.5.2_A3_T2.js | 4 - .../built-ins/Array/S15.4.5.2_A3_T3.js | 2 - .../test262/built-ins/Array/S15.4_A1.1_T10.js | 1 - .../test262/built-ins/Array/S15.4_A1.1_T4.js | 2 - .../test262/built-ins/Array/S15.4_A1.1_T5.js | 2 - .../test262/built-ins/Array/S15.4_A1.1_T6.js | 2 - .../test262/built-ins/Array/S15.4_A1.1_T7.js | 3 - .../test262/built-ins/Array/S15.4_A1.1_T8.js | 3 - .../test262/built-ins/Array/S15.4_A1.1_T9.js | 8 - .../Array/from/Array.from-descriptor.js | 3 +- ...e-has-length-but-no-indexes-with-values.js | 41 + .../built-ins/Array/isArray/descriptor.js | 3 +- .../Array/length/S15.4.2.2_A1.1_T1.js | 1 - .../Array/length/S15.4.2.2_A1.1_T2.js | 1 - .../Array/length/S15.4.2.2_A1.2_T1.js | 1 - .../Array/length/S15.4.2.2_A2.1_T1.js | 3 - .../Array/length/S15.4.2.2_A2.2_T1.js | 3 - .../Array/length/S15.4.2.2_A2.2_T2.js | 3 - .../Array/length/S15.4.2.2_A2.2_T3.js | 3 - .../Array/length/S15.4.5.1_A1.1_T1.js | 3 - .../Array/length/S15.4.5.1_A1.1_T2.js | 4 - .../Array/length/S15.4.5.1_A1.2_T1.js | 2 - .../Array/length/S15.4.5.1_A1.2_T3.js | 2 - .../Array/length/S15.4.5.1_A1.3_T1.js | 6 - .../Array/length/S15.4.5.1_A1.3_T2.js | 8 - .../built-ins/Array/length/S15.4.5.2_A3_T4.js | 1 - .../array-find-from-last.js | 34 + .../Symbol.unscopables/array-grouping.js | 34 + .../prototype/Symbol.unscopables/value.js | 31 +- ...rray.prototype.concat_large-typed-array.js | 19 +- ...rray.prototype.concat_small-typed-array.js | 19 +- .../Array/prototype/concat/S15.4.4.4_A1_T1.js | 1 - .../Array/prototype/concat/S15.4.4.4_A1_T2.js | 1 - .../Array/prototype/concat/S15.4.4.4_A1_T3.js | 1 - .../Array/prototype/concat/S15.4.4.4_A1_T4.js | 1 - .../Array/prototype/concat/S15.4.4.4_A2_T1.js | 1 - .../Array/prototype/concat/S15.4.4.4_A2_T2.js | 1 - .../copyWithin/coerced-values-target.js | 5 + .../non-negative-target-and-start.js | 28 +- .../every/callbackfn-resize-arraybuffer.js | 74 + .../built-ins/Array/prototype/every/shell.js | 124 + .../filter/callbackfn-resize-arraybuffer.js | 74 + .../built-ins/Array/prototype/filter/shell.js | 124 + .../find/callbackfn-resize-arraybuffer.js | 76 + .../built-ins/Array/prototype/find/shell.js | 124 + .../callbackfn-resize-arraybuffer.js | 76 + .../Array/prototype/findIndex/shell.js | 124 + .../findLast/callbackfn-resize-arraybuffer.js | 76 + .../Array/prototype/findLast/shell.js | 124 + .../callbackfn-resize-arraybuffer.js | 76 + .../Array/prototype/findLastIndex/shell.js | 124 + .../forEach/callbackfn-resize-arraybuffer.js | 72 + .../Array/prototype/forEach/shell.js | 124 + .../Array/prototype/join/S15.4.4.5_A1.1_T1.js | 2 - .../Array/prototype/join/S15.4.4.5_A1.2_T1.js | 3 - .../Array/prototype/join/S15.4.4.5_A1.2_T2.js | 3 - .../Array/prototype/join/S15.4.4.5_A1.3_T1.js | 3 - .../Array/prototype/join/S15.4.4.5_A2_T1.js | 6 - .../Array/prototype/join/S15.4.4.5_A2_T2.js | 10 - .../Array/prototype/join/S15.4.4.5_A2_T3.js | 6 - .../Array/prototype/join/S15.4.4.5_A2_T4.js | 105 +- .../Array/prototype/join/S15.4.4.5_A3.1_T1.js | 8 - .../Array/prototype/join/S15.4.4.5_A3.1_T2.js | 116 +- .../Array/prototype/join/S15.4.4.5_A3.2_T1.js | 8 - .../Array/prototype/join/S15.4.4.5_A3.2_T2.js | 50 +- .../Array/prototype/join/S15.4.4.5_A4_T3.js | 2 - .../Array/prototype/join/S15.4.4.5_A5_T1.js | 2 - .../Array/prototype/join/S15.4.4.5_A6.6.js | 1 - .../Array/prototype/join/S15.4.4.5_A6.7.js | 23 - .../map/callbackfn-resize-arraybuffer.js | 78 + .../built-ins/Array/prototype/map/shell.js | 124 + .../Array/prototype/pop/S15.4.4.6_A1.1_T1.js | 4 - .../Array/prototype/pop/S15.4.4.6_A1.2_T1.js | 10 - .../Array/prototype/pop/S15.4.4.6_A2_T1.js | 6 - .../Array/prototype/pop/S15.4.4.6_A2_T2.js | 12 - .../Array/prototype/pop/S15.4.4.6_A2_T3.js | 4 - .../Array/prototype/pop/S15.4.4.6_A2_T4.js | 82 +- .../Array/prototype/pop/S15.4.4.6_A3_T1.js | 4 - .../Array/prototype/pop/S15.4.4.6_A3_T2.js | 4 - .../Array/prototype/pop/S15.4.4.6_A3_T3.js | 3 - .../Array/prototype/pop/S15.4.4.6_A4_T1.js | 6 - .../Array/prototype/pop/S15.4.4.6_A4_T2.js | 6 - .../Array/prototype/pop/S15.4.4.6_A5.7.js | 23 - .../pop/set-length-array-is-frozen.js | 49 + ...set-length-array-length-is-non-writable.js | 49 + .../pop/set-length-zero-array-is-frozen.js | 34 + ...ength-zero-array-length-is-non-writable.js | 34 + .../Array/prototype/push/S15.4.4.7_A1_T1.js | 7 - .../Array/prototype/push/S15.4.4.7_A1_T2.js | 9 - .../Array/prototype/push/S15.4.4.7_A2_T1.js | 9 - .../Array/prototype/push/S15.4.4.7_A2_T2.js | 18 - .../Array/prototype/push/S15.4.4.7_A2_T3.js | 83 +- .../Array/prototype/push/S15.4.4.7_A3.js | 25 +- .../Array/prototype/push/S15.4.4.7_A4_T1.js | 10 - .../Array/prototype/push/S15.4.4.7_A4_T2.js | 5 - .../Array/prototype/push/S15.4.4.7_A4_T3.js | 8 - .../Array/prototype/push/S15.4.4.7_A5_T1.js | 5 - .../Array/prototype/push/S15.4.4.7_A6.7.js | 23 - .../push/set-length-array-is-frozen.js | 47 + ...set-length-array-length-is-non-writable.js | 47 + .../push/set-length-zero-array-is-frozen.js | 38 + ...ength-zero-array-length-is-non-writable.js | 38 + .../Array/prototype/reduce/15.4.4.21-9-8.js | 2 +- .../reduce/callbackfn-resize-arraybuffer.js | 76 + .../built-ins/Array/prototype/reduce/shell.js | 124 + .../prototype/reduceRight/15.4.4.22-9-8.js | 6 +- .../callbackfn-resize-arraybuffer.js | 81 + .../Array/prototype/reduceRight/shell.js | 124 + .../prototype/reverse/S15.4.4.8_A1_T1.js | 6 - .../prototype/reverse/S15.4.4.8_A1_T2.js | 20 - .../prototype/reverse/S15.4.4.8_A2_T1.js | 20 - .../prototype/reverse/S15.4.4.8_A2_T2.js | 20 - .../prototype/reverse/S15.4.4.8_A2_T3.js | 20 - .../prototype/reverse/S15.4.4.8_A3_T3.js | 5 - .../prototype/reverse/S15.4.4.8_A4_T1.js | 8 - .../prototype/reverse/S15.4.4.8_A4_T2.js | 8 - .../Array/prototype/reverse/S15.4.4.8_A5.7.js | 23 - .../prototype/shift/S15.4.4.9_A1.1_T1.js | 4 - .../prototype/shift/S15.4.4.9_A1.2_T1.js | 10 - .../Array/prototype/shift/S15.4.4.9_A2_T1.js | 6 - .../Array/prototype/shift/S15.4.4.9_A2_T2.js | 10 - .../Array/prototype/shift/S15.4.4.9_A2_T3.js | 4 - .../Array/prototype/shift/S15.4.4.9_A2_T4.js | 6 - .../Array/prototype/shift/S15.4.4.9_A2_T5.js | 82 +- .../Array/prototype/shift/S15.4.4.9_A3_T3.js | 4 - .../Array/prototype/shift/S15.4.4.9_A4_T1.js | 8 - .../Array/prototype/shift/S15.4.4.9_A4_T2.js | 8 - .../Array/prototype/shift/S15.4.4.9_A5.7.js | 23 - .../shift/set-length-array-is-frozen.js | 45 + ...set-length-array-length-is-non-writable.js | 45 + .../shift/set-length-zero-array-is-frozen.js | 34 + ...ength-zero-array-length-is-non-writable.js | 34 + .../prototype/slice/S15.4.4.10_A1.1_T1.js | 6 - .../prototype/slice/S15.4.4.10_A1.1_T2.js | 3 - .../prototype/slice/S15.4.4.10_A1.1_T3.js | 3 - .../prototype/slice/S15.4.4.10_A1.1_T4.js | 3 - .../prototype/slice/S15.4.4.10_A1.1_T5.js | 5 - .../prototype/slice/S15.4.4.10_A1.1_T6.js | 5 - .../prototype/slice/S15.4.4.10_A1.1_T7.js | 5 - .../prototype/slice/S15.4.4.10_A1.2_T1.js | 4 - .../prototype/slice/S15.4.4.10_A1.2_T2.js | 4 - .../prototype/slice/S15.4.4.10_A1.2_T3.js | 4 - .../prototype/slice/S15.4.4.10_A1.2_T4.js | 8 - .../prototype/slice/S15.4.4.10_A1.3_T1.js | 6 - .../prototype/slice/S15.4.4.10_A1.3_T2.js | 3 - .../prototype/slice/S15.4.4.10_A1.3_T3.js | 3 - .../prototype/slice/S15.4.4.10_A1.3_T4.js | 3 - .../prototype/slice/S15.4.4.10_A1.4_T1.js | 6 - .../prototype/slice/S15.4.4.10_A1.4_T2.js | 5 - .../prototype/slice/S15.4.4.10_A1.4_T3.js | 7 - .../prototype/slice/S15.4.4.10_A1.4_T4.js | 3 - .../prototype/slice/S15.4.4.10_A1.5_T1.js | 5 - .../prototype/slice/S15.4.4.10_A1.5_T2.js | 5 - .../prototype/slice/S15.4.4.10_A2.1_T1.js | 5 - .../prototype/slice/S15.4.4.10_A2.1_T2.js | 6 - .../prototype/slice/S15.4.4.10_A2.1_T3.js | 3 - .../prototype/slice/S15.4.4.10_A2.1_T4.js | 6 - .../prototype/slice/S15.4.4.10_A2.1_T5.js | 6 - .../prototype/slice/S15.4.4.10_A2.2_T1.js | 5 - .../prototype/slice/S15.4.4.10_A2.2_T2.js | 3 - .../prototype/slice/S15.4.4.10_A2.2_T3.js | 8 - .../prototype/slice/S15.4.4.10_A2.2_T4.js | 3 - .../prototype/slice/S15.4.4.10_A2.2_T5.js | 6 - .../Array/prototype/slice/S15.4.4.10_A2_T1.js | 6 - .../Array/prototype/slice/S15.4.4.10_A2_T2.js | 6 - .../Array/prototype/slice/S15.4.4.10_A2_T3.js | 6 - .../Array/prototype/slice/S15.4.4.10_A2_T4.js | 6 - .../Array/prototype/slice/S15.4.4.10_A2_T5.js | 6 - .../Array/prototype/slice/S15.4.4.10_A2_T6.js | 6 - .../Array/prototype/slice/S15.4.4.10_A3_T1.js | 22 +- .../Array/prototype/slice/S15.4.4.10_A3_T2.js | 22 +- .../Array/prototype/slice/S15.4.4.10_A3_T3.js | 2 - .../Array/prototype/slice/S15.4.4.10_A4_T1.js | 3 - .../Array/prototype/slice/S15.4.4.10_A5.7.js | 23 - .../some/callbackfn-resize-arraybuffer.js | 74 + .../built-ins/Array/prototype/some/shell.js | 124 + .../prototype/sort/S15.4.4.11_A1.1_T1.js | 3 - .../prototype/sort/S15.4.4.11_A1.2_T1.js | 6 - .../prototype/sort/S15.4.4.11_A1.2_T2.js | 6 - .../prototype/sort/S15.4.4.11_A1.3_T1.js | 3 - .../prototype/sort/S15.4.4.11_A1.4_T1.js | 6 - .../prototype/sort/S15.4.4.11_A1.4_T2.js | 6 - .../prototype/sort/S15.4.4.11_A1.5_T1.js | 6 - .../prototype/sort/S15.4.4.11_A2.1_T1.js | 1 - .../prototype/sort/S15.4.4.11_A2.1_T2.js | 1 - .../prototype/sort/S15.4.4.11_A2.1_T3.js | 1 - .../prototype/sort/S15.4.4.11_A2.2_T1.js | 1 - .../prototype/sort/S15.4.4.11_A2.2_T2.js | 1 - .../prototype/sort/S15.4.4.11_A2.2_T3.js | 1 - .../Array/prototype/sort/S15.4.4.11_A3_T1.js | 2 - .../Array/prototype/sort/S15.4.4.11_A3_T2.js | 2 - .../Array/prototype/sort/S15.4.4.11_A4_T3.js | 5 - .../Array/prototype/sort/S15.4.4.11_A5_T1.js | 18 +- .../Array/prototype/sort/S15.4.4.11_A6_T2.js | 8 - .../Array/prototype/sort/S15.4.4.11_A7.7.js | 23 - .../prototype/splice/S15.4.4.12_A1.1_T1.js | 7 - .../prototype/splice/S15.4.4.12_A1.1_T2.js | 9 - .../prototype/splice/S15.4.4.12_A1.1_T3.js | 7 - .../prototype/splice/S15.4.4.12_A1.1_T4.js | 9 - .../prototype/splice/S15.4.4.12_A1.1_T5.js | 7 - .../prototype/splice/S15.4.4.12_A1.1_T6.js | 9 - .../prototype/splice/S15.4.4.12_A1.2_T1.js | 5 - .../prototype/splice/S15.4.4.12_A1.2_T2.js | 5 - .../prototype/splice/S15.4.4.12_A1.2_T3.js | 7 - .../prototype/splice/S15.4.4.12_A1.2_T4.js | 7 - .../prototype/splice/S15.4.4.12_A1.2_T5.js | 7 - .../prototype/splice/S15.4.4.12_A1.3_T1.js | 5 - .../prototype/splice/S15.4.4.12_A1.3_T2.js | 5 - .../prototype/splice/S15.4.4.12_A1.3_T3.js | 7 - .../prototype/splice/S15.4.4.12_A1.3_T4.js | 7 - .../prototype/splice/S15.4.4.12_A1.3_T5.js | 7 - .../prototype/splice/S15.4.4.12_A1.4_T1.js | 7 - .../prototype/splice/S15.4.4.12_A1.4_T2.js | 9 - .../prototype/splice/S15.4.4.12_A1.4_T3.js | 7 - .../prototype/splice/S15.4.4.12_A1.4_T4.js | 9 - .../prototype/splice/S15.4.4.12_A1.4_T5.js | 7 - .../prototype/splice/S15.4.4.12_A1.4_T6.js | 9 - .../prototype/splice/S15.4.4.12_A1.5_T1.js | 7 - .../prototype/splice/S15.4.4.12_A1.5_T2.js | 7 - .../prototype/splice/S15.4.4.12_A2.1_T1.js | 7 - .../prototype/splice/S15.4.4.12_A2.1_T2.js | 7 - .../prototype/splice/S15.4.4.12_A2.1_T3.js | 6 - .../prototype/splice/S15.4.4.12_A2.1_T4.js | 7 - .../prototype/splice/S15.4.4.12_A2.1_T5.js | 7 - .../prototype/splice/S15.4.4.12_A2.2_T1.js | 7 - .../prototype/splice/S15.4.4.12_A2.2_T2.js | 5 - .../prototype/splice/S15.4.4.12_A2.2_T3.js | 7 - .../prototype/splice/S15.4.4.12_A2.2_T4.js | 5 - .../prototype/splice/S15.4.4.12_A2.2_T5.js | 7 - .../prototype/splice/S15.4.4.12_A2_T1.js | 10 - .../prototype/splice/S15.4.4.12_A2_T2.js | 8 - .../prototype/splice/S15.4.4.12_A2_T3.js | 8 - .../prototype/splice/S15.4.4.12_A2_T4.js | 10 - .../prototype/splice/S15.4.4.12_A3_T1.js | 5 - .../prototype/splice/S15.4.4.12_A3_T3.js | 4 - .../prototype/splice/S15.4.4.12_A4_T1.js | 12 - .../prototype/splice/S15.4.4.12_A4_T2.js | 12 - .../prototype/splice/S15.4.4.12_A4_T3.js | 10 - .../Array/prototype/splice/S15.4.4.12_A5.7.js | 23 - .../toLocaleString/S15.4.4.3_A1_T1.js | 1 - .../toLocaleString/S15.4.4.3_A3_T1.js | 1 - .../toLocaleString/S15.4.4.3_A4.7.js | 24 - .../prototype/toString/S15.4.4.2_A1_T1.js | 2 - .../prototype/toString/S15.4.4.2_A1_T2.js | 4 - .../prototype/toString/S15.4.4.2_A1_T3.js | 8 - .../prototype/toString/S15.4.4.2_A1_T4.js | 132 +- .../prototype/toString/S15.4.4.2_A3_T1.js | 1 - .../prototype/toString/S15.4.4.2_A4.7.js | 24 - .../prototype/unshift/S15.4.4.13_A1_T1.js | 8 - .../prototype/unshift/S15.4.4.13_A1_T2.js | 9 - .../prototype/unshift/S15.4.4.13_A2_T1.js | 15 +- .../prototype/unshift/S15.4.4.13_A2_T2.js | 15 - .../prototype/unshift/S15.4.4.13_A2_T3.js | 82 +- .../prototype/unshift/S15.4.4.13_A3_T2.js | 6 - .../prototype/unshift/S15.4.4.13_A4_T1.js | 10 - .../prototype/unshift/S15.4.4.13_A4_T2.js | 10 - .../prototype/unshift/S15.4.4.13_A5.7.js | 23 - .../unshift/set-length-array-is-frozen.js | 50 + ...set-length-array-length-is-non-writable.js | 50 + .../set-length-zero-array-is-frozen.js | 38 + ...ength-zero-array-length-is-non-writable.js | 38 + .../built-ins/Boolean/S15.6.1.1_A1_T1.js | 30 +- .../built-ins/Boolean/S15.6.1.1_A1_T2.js | 42 +- .../built-ins/Boolean/S15.6.1.1_A1_T3.js | 54 +- .../built-ins/Boolean/S15.6.1.1_A1_T4.js | 58 +- .../built-ins/Boolean/S15.6.1.1_A1_T5.js | 59 +- .../test262/built-ins/Boolean/S15.6.1.1_A2.js | 12 +- .../test262/built-ins/Boolean/S15.6.2.1_A1.js | 43 +- .../test262/built-ins/Boolean/S15.6.2.1_A2.js | 24 +- .../test262/built-ins/Boolean/S15.6.2.1_A3.js | 19 +- .../test262/built-ins/Boolean/S15.6.2.1_A4.js | 5 +- .../test262/built-ins/Boolean/S15.6.3_A1.js | 5 +- .../test262/built-ins/Boolean/S15.6.3_A2.js | 9 +- .../test262/built-ins/Boolean/S15.6.3_A3.js | 12 +- .../test262/built-ins/Boolean/S9.2_A1_T1.js | 23 +- .../test262/built-ins/Boolean/S9.2_A2_T1.js | 6 +- .../test262/built-ins/Boolean/S9.2_A3_T1.js | 12 +- .../test262/built-ins/Boolean/S9.2_A4_T1.js | 18 +- .../test262/built-ins/Boolean/S9.2_A4_T3.js | 48 +- .../test262/built-ins/Boolean/S9.2_A5_T1.js | 6 +- .../test262/built-ins/Boolean/S9.2_A5_T3.js | 12 +- .../test262/built-ins/Boolean/S9.2_A6_T1.js | 118 +- .../Boolean/prototype/S15.6.3.1_A1.js | 22 +- .../Boolean/prototype/S15.6.3.1_A2.js | 4 +- ...S15.6.3.1_A3.js => S15.6.3.1_A3-strict.js} | 13 +- .../Boolean/prototype/S15.6.3.1_A4.js | 12 +- .../built-ins/Boolean/prototype/S15.6.4_A1.js | 28 - .../built-ins/Boolean/prototype/S15.6.4_A2.js | 8 +- .../prototype/constructor/S15.6.4.1_A1.js | 10 +- .../prototype/toString/S15.6.4.2_A1_T1.js | 45 +- .../prototype/toString/S15.6.4.2_A1_T2.js | 50 +- .../prototype/toString/S15.6.4.2_A2_T1.js | 22 +- .../prototype/toString/S15.6.4.2_A2_T2.js | 26 +- .../prototype/toString/S15.6.4.2_A2_T3.js | 26 +- .../prototype/toString/S15.6.4.2_A2_T4.js | 27 +- .../prototype/toString/S15.6.4.2_A2_T5.js | 26 +- .../prototype/valueOf/S15.6.4.3_A1_T1.js | 39 +- .../prototype/valueOf/S15.6.4.3_A1_T2.js | 39 +- .../prototype/valueOf/S15.6.4.3_A2_T1.js | 28 +- .../prototype/valueOf/S15.6.4.3_A2_T2.js | 28 +- .../prototype/valueOf/S15.6.4.3_A2_T3.js | 28 +- .../prototype/valueOf/S15.6.4.3_A2_T4.js | 28 +- .../prototype/valueOf/S15.6.4.3_A2_T5.js | 28 +- ...access-resizes-buffer-invalid-by-length.js | 43 + ...access-resizes-buffer-invalid-by-offset.js | 42 + ...o-access-resizes-buffer-valid-by-length.js | 35 + ...o-access-resizes-buffer-valid-by-offset.js | 38 + .../DataView/prototype/Symbol.toStringTag.js | 6 +- .../byteLength/resizable-array-buffer-auto.js | 7 + .../byteOffset/resizable-array-buffer-auto.js | 8 +- .../test262/built-ins/Date/S15.9.2.1_A1.js | 110 +- .../test262/built-ins/Date/S15.9.2.1_A2.js | 112 +- .../test262/built-ins/Date/S15.9.3.1_A1_T1.js | 240 +- .../test262/built-ins/Date/S15.9.3.1_A1_T2.js | 240 +- .../test262/built-ins/Date/S15.9.3.1_A1_T3.js | 273 +- .../test262/built-ins/Date/S15.9.3.1_A1_T4.js | 289 +- .../test262/built-ins/Date/S15.9.3.1_A1_T5.js | 289 +- .../test262/built-ins/Date/S15.9.3.1_A1_T6.js | 289 +- .../test262/built-ins/Date/S15.9.3.1_A2_T1.js | 264 +- .../test262/built-ins/Date/S15.9.3.1_A2_T2.js | 264 +- .../test262/built-ins/Date/S15.9.3.1_A2_T3.js | 264 +- .../test262/built-ins/Date/S15.9.3.1_A2_T4.js | 264 +- .../test262/built-ins/Date/S15.9.3.1_A2_T5.js | 264 +- .../test262/built-ins/Date/S15.9.3.1_A2_T6.js | 264 +- .../built-ins/Date/S15.9.3.1_A3_T1.1.js | 108 +- .../built-ins/Date/S15.9.3.1_A3_T1.2.js | 48 +- .../built-ins/Date/S15.9.3.1_A3_T2.1.js | 108 +- .../built-ins/Date/S15.9.3.1_A3_T2.2.js | 48 +- .../built-ins/Date/S15.9.3.1_A3_T3.1.js | 108 +- .../built-ins/Date/S15.9.3.1_A3_T3.2.js | 48 +- .../built-ins/Date/S15.9.3.1_A3_T4.1.js | 108 +- .../built-ins/Date/S15.9.3.1_A3_T4.2.js | 48 +- .../built-ins/Date/S15.9.3.1_A3_T5.1.js | 108 +- .../built-ins/Date/S15.9.3.1_A3_T5.2.js | 48 +- .../built-ins/Date/S15.9.3.1_A3_T6.1.js | 108 +- .../built-ins/Date/S15.9.3.1_A3_T6.2.js | 48 +- .../test262/built-ins/Date/S15.9.3.1_A4_T0.js | 31 + .../test262/built-ins/Date/S15.9.3.1_A4_T1.js | 36 +- .../test262/built-ins/Date/S15.9.3.1_A4_T2.js | 49 +- .../test262/built-ins/Date/S15.9.3.1_A4_T3.js | 62 +- .../test262/built-ins/Date/S15.9.3.1_A4_T4.js | 75 +- .../test262/built-ins/Date/S15.9.3.1_A4_T5.js | 88 +- .../test262/built-ins/Date/S15.9.3.1_A4_T6.js | 101 +- .../test262/built-ins/Date/S15.9.3.1_A6_T1.js | 24 +- .../test262/built-ins/Date/S15.9.3.1_A6_T2.js | 24 +- .../test262/built-ins/Date/S15.9.3.1_A6_T3.js | 24 +- .../test262/built-ins/Date/S15.9.3.1_A6_T4.js | 24 +- .../test262/built-ins/Date/S15.9.3.1_A6_T5.js | 24 +- .../test262/built-ins/Date/S15.9.3.2_A1_T1.js | 177 +- .../test262/built-ins/Date/S15.9.3.2_A2_T1.js | 176 +- .../built-ins/Date/S15.9.3.2_A3_T1.1.js | 72 +- .../built-ins/Date/S15.9.3.2_A3_T1.2.js | 32 +- .../test262/built-ins/Date/S15.9.4_A1.js | 5 +- .../test262/built-ins/Date/S15.9.4_A2.js | 5 +- .../test262/built-ins/Date/S15.9.4_A3.js | 5 +- .../test262/built-ins/Date/S15.9.4_A4.js | 6 +- .../test262/built-ins/Date/S15.9.4_A5.js | 12 +- .../built-ins/Date/UTC/S15.9.4.3_A1_T1.js | 9 +- .../built-ins/Date/UTC/S15.9.4.3_A1_T2.js | 10 +- .../built-ins/Date/UTC/S15.9.4.3_A1_T3.js | 14 +- .../built-ins/Date/UTC/S15.9.4.3_A2_T1.js | 10 +- .../built-ins/Date/UTC/S15.9.4.3_A3_T1.js | 6 +- .../built-ins/Date/UTC/S15.9.4.3_A3_T2.js | 13 +- .../built-ins/Date/UTC/S15.9.4.3_A3_T3.js | 14 +- .../built-ins/Date/parse/S15.9.4.2_A1_T1.js | 9 +- .../built-ins/Date/parse/S15.9.4.2_A1_T2.js | 10 +- .../built-ins/Date/parse/S15.9.4.2_A1_T3.js | 14 +- .../built-ins/Date/parse/S15.9.4.2_A2_T1.js | 10 +- .../built-ins/Date/parse/S15.9.4.2_A3_T1.js | 6 +- .../built-ins/Date/parse/S15.9.4.2_A3_T2.js | 12 +- .../built-ins/Date/parse/S15.9.4.2_A3_T3.js | 14 +- .../Date/prototype/S15.9.4.1_A1_T1.js | 6 +- .../Date/prototype/S15.9.4.1_A1_T2.js | 10 +- .../Date/prototype/S15.9.4.1_A1_T3.js | 14 +- .../Date/prototype/S15.9.5_A01_T1.js | 9 +- .../Date/prototype/S15.9.5_A02_T1.js | 9 +- .../Date/prototype/S15.9.5_A03_T1.js | 9 +- .../Date/prototype/S15.9.5_A04_T1.js | 9 +- .../Date/prototype/S15.9.5_A05_T1.js | 9 +- .../Date/prototype/S15.9.5_A06_T1.js | 9 +- .../Date/prototype/S15.9.5_A07_T1.js | 9 +- .../Date/prototype/S15.9.5_A08_T1.js | 9 +- .../Date/prototype/S15.9.5_A09_T1.js | 9 +- .../Date/prototype/S15.9.5_A10_T1.js | 9 +- .../Date/prototype/S15.9.5_A11_T1.js | 9 +- .../Date/prototype/S15.9.5_A12_T1.js | 9 +- .../Date/prototype/S15.9.5_A13_T1.js | 9 +- .../Date/prototype/S15.9.5_A14_T1.js | 9 +- .../Date/prototype/S15.9.5_A15_T1.js | 9 +- .../Date/prototype/S15.9.5_A16_T1.js | 9 +- .../Date/prototype/S15.9.5_A17_T1.js | 9 +- .../Date/prototype/S15.9.5_A18_T1.js | 9 +- .../Date/prototype/S15.9.5_A19_T1.js | 9 +- .../Date/prototype/S15.9.5_A20_T1.js | 9 +- .../Date/prototype/S15.9.5_A21_T1.js | 9 +- .../Date/prototype/S15.9.5_A22_T1.js | 9 +- .../Date/prototype/S15.9.5_A23_T1.js | 9 +- .../Date/prototype/S15.9.5_A24_T1.js | 9 +- .../Date/prototype/S15.9.5_A25_T1.js | 9 +- .../Date/prototype/S15.9.5_A26_T1.js | 9 +- .../Date/prototype/S15.9.5_A27_T1.js | 9 +- .../Date/prototype/S15.9.5_A28_T1.js | 9 +- .../Date/prototype/S15.9.5_A29_T1.js | 9 +- .../Date/prototype/S15.9.5_A30_T1.js | 9 +- .../Date/prototype/S15.9.5_A31_T1.js | 9 +- .../Date/prototype/S15.9.5_A32_T1.js | 9 +- .../Date/prototype/S15.9.5_A33_T1.js | 9 +- .../Date/prototype/S15.9.5_A34_T1.js | 9 +- .../Date/prototype/S15.9.5_A35_T1.js | 9 +- .../Date/prototype/S15.9.5_A36_T1.js | 9 +- .../Date/prototype/S15.9.5_A37_T1.js | 9 +- .../Date/prototype/S15.9.5_A38_T1.js | 9 +- .../Date/prototype/S15.9.5_A39_T1.js | 9 +- .../Date/prototype/S15.9.5_A40_T1.js | 9 +- .../Date/prototype/S15.9.5_A41_T1.js | 9 +- .../Date/prototype/S15.9.5_A42_T1.js | 9 +- .../prototype/constructor/S15.9.5.1_A1_T1.js | 14 +- .../prototype/constructor/S15.9.5.1_A1_T2.js | 16 +- .../prototype/constructor/S15.9.5.1_A1_T3.js | 14 +- .../prototype/constructor/S15.9.5.1_A2_T1.js | 17 +- .../prototype/constructor/S15.9.5.1_A3_T1.js | 11 +- .../prototype/constructor/S15.9.5.1_A3_T2.js | 16 +- .../prototype/constructor/S15.9.5.1_A3_T3.js | 14 +- .../prototype/getDate/S15.9.5.14_A1_T1.js | 14 +- .../prototype/getDate/S15.9.5.14_A1_T2.js | 12 +- .../prototype/getDate/S15.9.5.14_A1_T3.js | 14 +- .../prototype/getDate/S15.9.5.14_A2_T1.js | 13 +- .../prototype/getDate/S15.9.5.14_A3_T1.js | 11 +- .../prototype/getDate/S15.9.5.14_A3_T2.js | 16 +- .../prototype/getDate/S15.9.5.14_A3_T3.js | 14 +- .../Date/prototype/getDay/S15.9.5.16_A1_T1.js | 14 +- .../Date/prototype/getDay/S15.9.5.16_A1_T2.js | 12 +- .../Date/prototype/getDay/S15.9.5.16_A1_T3.js | 14 +- .../Date/prototype/getDay/S15.9.5.16_A2_T1.js | 13 +- .../Date/prototype/getDay/S15.9.5.16_A3_T1.js | 11 +- .../Date/prototype/getDay/S15.9.5.16_A3_T2.js | 16 +- .../Date/prototype/getDay/S15.9.5.16_A3_T3.js | 14 +- .../prototype/getFullYear/S15.9.5.10_A1_T1.js | 14 +- .../prototype/getFullYear/S15.9.5.10_A1_T2.js | 16 +- .../prototype/getFullYear/S15.9.5.10_A1_T3.js | 14 +- .../prototype/getFullYear/S15.9.5.10_A2_T1.js | 17 +- .../prototype/getFullYear/S15.9.5.10_A3_T1.js | 11 +- .../prototype/getFullYear/S15.9.5.10_A3_T2.js | 16 +- .../prototype/getFullYear/S15.9.5.10_A3_T3.js | 14 +- .../prototype/getHours/S15.9.5.18_A1_T1.js | 14 +- .../prototype/getHours/S15.9.5.18_A1_T2.js | 12 +- .../prototype/getHours/S15.9.5.18_A1_T3.js | 14 +- .../prototype/getHours/S15.9.5.18_A2_T1.js | 13 +- .../prototype/getHours/S15.9.5.18_A3_T1.js | 11 +- .../prototype/getHours/S15.9.5.18_A3_T2.js | 16 +- .../prototype/getHours/S15.9.5.18_A3_T3.js | 14 +- .../getMilliseconds/S15.9.5.24_A1_T1.js | 14 +- .../getMilliseconds/S15.9.5.24_A1_T2.js | 16 +- .../getMilliseconds/S15.9.5.24_A1_T3.js | 14 +- .../getMilliseconds/S15.9.5.24_A2_T1.js | 17 +- .../getMilliseconds/S15.9.5.24_A3_T1.js | 11 +- .../getMilliseconds/S15.9.5.24_A3_T2.js | 16 +- .../getMilliseconds/S15.9.5.24_A3_T3.js | 14 +- .../prototype/getMinutes/S15.9.5.20_A1_T1.js | 14 +- .../prototype/getMinutes/S15.9.5.20_A1_T2.js | 16 +- .../prototype/getMinutes/S15.9.5.20_A1_T3.js | 14 +- .../prototype/getMinutes/S15.9.5.20_A2_T1.js | 17 +- .../prototype/getMinutes/S15.9.5.20_A3_T1.js | 11 +- .../prototype/getMinutes/S15.9.5.20_A3_T2.js | 16 +- .../prototype/getMinutes/S15.9.5.20_A3_T3.js | 14 +- .../prototype/getMonth/S15.9.5.12_A1_T1.js | 14 +- .../prototype/getMonth/S15.9.5.12_A1_T2.js | 12 +- .../prototype/getMonth/S15.9.5.12_A1_T3.js | 14 +- .../prototype/getMonth/S15.9.5.12_A2_T1.js | 13 +- .../prototype/getMonth/S15.9.5.12_A3_T1.js | 11 +- .../prototype/getMonth/S15.9.5.12_A3_T2.js | 16 +- .../prototype/getMonth/S15.9.5.12_A3_T3.js | 14 +- .../prototype/getSeconds/S15.9.5.22_A1_T1.js | 14 +- .../prototype/getSeconds/S15.9.5.22_A1_T2.js | 16 +- .../prototype/getSeconds/S15.9.5.22_A1_T3.js | 14 +- .../prototype/getSeconds/S15.9.5.22_A2_T1.js | 17 +- .../prototype/getSeconds/S15.9.5.22_A3_T1.js | 11 +- .../prototype/getSeconds/S15.9.5.22_A3_T2.js | 16 +- .../prototype/getSeconds/S15.9.5.22_A3_T3.js | 14 +- .../Date/prototype/getTime/S15.9.5.9_A1_T1.js | 14 +- .../Date/prototype/getTime/S15.9.5.9_A1_T2.js | 12 +- .../Date/prototype/getTime/S15.9.5.9_A1_T3.js | 14 +- .../Date/prototype/getTime/S15.9.5.9_A2_T1.js | 13 +- .../Date/prototype/getTime/S15.9.5.9_A3_T1.js | 11 +- .../Date/prototype/getTime/S15.9.5.9_A3_T2.js | 16 +- .../Date/prototype/getTime/S15.9.5.9_A3_T3.js | 14 +- .../getTimezoneOffset/S15.9.5.26_A1_T1.js | 14 +- .../getTimezoneOffset/S15.9.5.26_A1_T2.js | 16 +- .../getTimezoneOffset/S15.9.5.26_A1_T3.js | 14 +- .../getTimezoneOffset/S15.9.5.26_A2_T1.js | 17 +- .../getTimezoneOffset/S15.9.5.26_A3_T1.js | 11 +- .../getTimezoneOffset/S15.9.5.26_A3_T2.js | 16 +- .../getTimezoneOffset/S15.9.5.26_A3_T3.js | 14 +- .../prototype/getUTCDate/S15.9.5.15_A1_T1.js | 14 +- .../prototype/getUTCDate/S15.9.5.15_A1_T2.js | 16 +- .../prototype/getUTCDate/S15.9.5.15_A1_T3.js | 14 +- .../prototype/getUTCDate/S15.9.5.15_A2_T1.js | 17 +- .../prototype/getUTCDate/S15.9.5.15_A3_T1.js | 11 +- .../prototype/getUTCDate/S15.9.5.15_A3_T2.js | 16 +- .../prototype/getUTCDate/S15.9.5.15_A3_T3.js | 14 +- .../prototype/getUTCDay/S15.9.5.17_A1_T1.js | 14 +- .../prototype/getUTCDay/S15.9.5.17_A1_T2.js | 12 +- .../prototype/getUTCDay/S15.9.5.17_A1_T3.js | 14 +- .../prototype/getUTCDay/S15.9.5.17_A2_T1.js | 17 +- .../prototype/getUTCDay/S15.9.5.17_A3_T1.js | 11 +- .../prototype/getUTCDay/S15.9.5.17_A3_T2.js | 16 +- .../prototype/getUTCDay/S15.9.5.17_A3_T3.js | 14 +- .../getUTCFullYear/S15.9.5.11_A1_T1.js | 14 +- .../getUTCFullYear/S15.9.5.11_A1_T2.js | 16 +- .../getUTCFullYear/S15.9.5.11_A1_T3.js | 14 +- .../getUTCFullYear/S15.9.5.11_A2_T1.js | 17 +- .../getUTCFullYear/S15.9.5.11_A3_T1.js | 11 +- .../getUTCFullYear/S15.9.5.11_A3_T2.js | 16 +- .../getUTCFullYear/S15.9.5.11_A3_T3.js | 14 +- .../prototype/getUTCHours/S15.9.5.19_A1_T1.js | 14 +- .../prototype/getUTCHours/S15.9.5.19_A1_T2.js | 16 +- .../prototype/getUTCHours/S15.9.5.19_A1_T3.js | 14 +- .../prototype/getUTCHours/S15.9.5.19_A2_T1.js | 17 +- .../prototype/getUTCHours/S15.9.5.19_A3_T1.js | 11 +- .../prototype/getUTCHours/S15.9.5.19_A3_T2.js | 16 +- .../prototype/getUTCHours/S15.9.5.19_A3_T3.js | 14 +- .../getUTCMilliseconds/S15.9.5.25_A1_T1.js | 14 +- .../getUTCMilliseconds/S15.9.5.25_A1_T2.js | 16 +- .../getUTCMilliseconds/S15.9.5.25_A1_T3.js | 14 +- .../getUTCMilliseconds/S15.9.5.25_A2_T1.js | 17 +- .../getUTCMilliseconds/S15.9.5.25_A3_T1.js | 11 +- .../getUTCMilliseconds/S15.9.5.25_A3_T2.js | 16 +- .../getUTCMilliseconds/S15.9.5.25_A3_T3.js | 14 +- .../getUTCMinutes/S15.9.5.21_A1_T1.js | 14 +- .../getUTCMinutes/S15.9.5.21_A1_T2.js | 16 +- .../getUTCMinutes/S15.9.5.21_A1_T3.js | 14 +- .../getUTCMinutes/S15.9.5.21_A2_T1.js | 17 +- .../getUTCMinutes/S15.9.5.21_A3_T1.js | 11 +- .../getUTCMinutes/S15.9.5.21_A3_T2.js | 16 +- .../getUTCMinutes/S15.9.5.21_A3_T3.js | 14 +- .../prototype/getUTCMonth/S15.9.5.13_A1_T1.js | 14 +- .../prototype/getUTCMonth/S15.9.5.13_A1_T2.js | 16 +- .../prototype/getUTCMonth/S15.9.5.13_A1_T3.js | 14 +- .../prototype/getUTCMonth/S15.9.5.13_A2_T1.js | 17 +- .../prototype/getUTCMonth/S15.9.5.13_A3_T1.js | 11 +- .../prototype/getUTCMonth/S15.9.5.13_A3_T2.js | 16 +- .../prototype/getUTCMonth/S15.9.5.13_A3_T3.js | 14 +- .../getUTCSeconds/S15.9.5.23_A1_T1.js | 14 +- .../getUTCSeconds/S15.9.5.23_A1_T2.js | 16 +- .../getUTCSeconds/S15.9.5.23_A1_T3.js | 14 +- .../getUTCSeconds/S15.9.5.23_A2_T1.js | 17 +- .../getUTCSeconds/S15.9.5.23_A3_T1.js | 11 +- .../getUTCSeconds/S15.9.5.23_A3_T2.js | 16 +- .../getUTCSeconds/S15.9.5.23_A3_T3.js | 14 +- .../prototype/setDate/S15.9.5.36_A1_T1.js | 14 +- .../prototype/setDate/S15.9.5.36_A1_T2.js | 12 +- .../prototype/setDate/S15.9.5.36_A1_T3.js | 14 +- .../prototype/setDate/S15.9.5.36_A2_T1.js | 13 +- .../prototype/setDate/S15.9.5.36_A3_T1.js | 11 +- .../prototype/setDate/S15.9.5.36_A3_T2.js | 16 +- .../prototype/setDate/S15.9.5.36_A3_T3.js | 14 +- .../prototype/setDate/arg-coercion-order.js | 32 + .../prototype/setFullYear/S15.9.5.40_A1_T1.js | 14 +- .../prototype/setFullYear/S15.9.5.40_A1_T2.js | 16 +- .../prototype/setFullYear/S15.9.5.40_A1_T3.js | 14 +- .../prototype/setFullYear/S15.9.5.40_A2_T1.js | 17 +- .../prototype/setFullYear/S15.9.5.40_A3_T1.js | 11 +- .../prototype/setFullYear/S15.9.5.40_A3_T2.js | 16 +- .../prototype/setFullYear/S15.9.5.40_A3_T3.js | 14 +- .../prototype/setHours/S15.9.5.34_A1_T1.js | 14 +- .../prototype/setHours/S15.9.5.34_A1_T2.js | 12 +- .../prototype/setHours/S15.9.5.34_A1_T3.js | 14 +- .../prototype/setHours/S15.9.5.34_A2_T1.js | 13 +- .../prototype/setHours/S15.9.5.34_A3_T1.js | 11 +- .../prototype/setHours/S15.9.5.34_A3_T2.js | 16 +- .../prototype/setHours/S15.9.5.34_A3_T3.js | 14 +- .../prototype/setHours/arg-coercion-order.js | 59 + .../setMilliseconds/S15.9.5.28_A1_T1.js | 14 +- .../setMilliseconds/S15.9.5.28_A1_T2.js | 16 +- .../setMilliseconds/S15.9.5.28_A1_T3.js | 14 +- .../setMilliseconds/S15.9.5.28_A2_T1.js | 17 +- .../setMilliseconds/S15.9.5.28_A3_T1.js | 11 +- .../setMilliseconds/S15.9.5.28_A3_T2.js | 16 +- .../setMilliseconds/S15.9.5.28_A3_T3.js | 14 +- .../setMilliseconds/arg-coercion-order.js | 32 + .../prototype/setMinutes/S15.9.5.32_A1_T1.js | 14 +- .../prototype/setMinutes/S15.9.5.32_A1_T2.js | 16 +- .../prototype/setMinutes/S15.9.5.32_A1_T3.js | 14 +- .../prototype/setMinutes/S15.9.5.32_A2_T1.js | 17 +- .../prototype/setMinutes/S15.9.5.32_A3_T1.js | 11 +- .../prototype/setMinutes/S15.9.5.32_A3_T2.js | 16 +- .../prototype/setMinutes/S15.9.5.32_A3_T3.js | 14 +- .../setMinutes/arg-coercion-order.js | 51 + .../prototype/setMonth/S15.9.5.38_A1_T1.js | 14 +- .../prototype/setMonth/S15.9.5.38_A1_T2.js | 12 +- .../prototype/setMonth/S15.9.5.38_A1_T3.js | 14 +- .../prototype/setMonth/S15.9.5.38_A2_T1.js | 13 +- .../prototype/setMonth/S15.9.5.38_A3_T1.js | 11 +- .../prototype/setMonth/S15.9.5.38_A3_T2.js | 16 +- .../prototype/setMonth/S15.9.5.38_A3_T3.js | 14 +- .../prototype/setMonth/arg-coercion-order.js | 43 + .../prototype/setSeconds/S15.9.5.30_A1_T1.js | 14 +- .../prototype/setSeconds/S15.9.5.30_A1_T2.js | 16 +- .../prototype/setSeconds/S15.9.5.30_A1_T3.js | 14 +- .../prototype/setSeconds/S15.9.5.30_A2_T1.js | 17 +- .../prototype/setSeconds/S15.9.5.30_A3_T1.js | 11 +- .../prototype/setSeconds/S15.9.5.30_A3_T2.js | 16 +- .../prototype/setSeconds/S15.9.5.30_A3_T3.js | 14 +- .../setSeconds/arg-coercion-order.js | 43 + .../prototype/setTime/S15.9.5.27_A1_T1.js | 14 +- .../prototype/setTime/S15.9.5.27_A1_T2.js | 12 +- .../prototype/setTime/S15.9.5.27_A1_T3.js | 14 +- .../prototype/setTime/S15.9.5.27_A2_T1.js | 13 +- .../prototype/setTime/S15.9.5.27_A3_T1.js | 11 +- .../prototype/setTime/S15.9.5.27_A3_T2.js | 16 +- .../prototype/setTime/S15.9.5.27_A3_T3.js | 14 +- .../prototype/setUTCDate/S15.9.5.37_A1_T1.js | 14 +- .../prototype/setUTCDate/S15.9.5.37_A1_T2.js | 16 +- .../prototype/setUTCDate/S15.9.5.37_A1_T3.js | 14 +- .../prototype/setUTCDate/S15.9.5.37_A2_T1.js | 17 +- .../prototype/setUTCDate/S15.9.5.37_A3_T1.js | 11 +- .../prototype/setUTCDate/S15.9.5.37_A3_T2.js | 16 +- .../prototype/setUTCDate/S15.9.5.37_A3_T3.js | 14 +- .../setUTCDate/arg-coercion-order.js | 31 + .../setUTCFullYear/S15.9.5.41_A1_T1.js | 14 +- .../setUTCFullYear/S15.9.5.41_A1_T2.js | 16 +- .../setUTCFullYear/S15.9.5.41_A1_T3.js | 14 +- .../setUTCFullYear/S15.9.5.41_A2_T1.js | 17 +- .../setUTCFullYear/S15.9.5.41_A3_T1.js | 11 +- .../setUTCFullYear/S15.9.5.41_A3_T2.js | 16 +- .../setUTCFullYear/S15.9.5.41_A3_T3.js | 14 +- .../prototype/setUTCHours/S15.9.5.35_A1_T1.js | 14 +- .../prototype/setUTCHours/S15.9.5.35_A1_T2.js | 16 +- .../prototype/setUTCHours/S15.9.5.35_A1_T3.js | 14 +- .../prototype/setUTCHours/S15.9.5.35_A2_T1.js | 17 +- .../prototype/setUTCHours/S15.9.5.35_A3_T1.js | 11 +- .../prototype/setUTCHours/S15.9.5.35_A3_T2.js | 16 +- .../prototype/setUTCHours/S15.9.5.35_A3_T3.js | 14 +- .../setUTCHours/arg-coercion-order.js | 58 + .../setUTCMilliseconds/S15.9.5.29_A1_T1.js | 14 +- .../setUTCMilliseconds/S15.9.5.29_A1_T2.js | 16 +- .../setUTCMilliseconds/S15.9.5.29_A1_T3.js | 14 +- .../setUTCMilliseconds/S15.9.5.29_A2_T1.js | 17 +- .../setUTCMilliseconds/S15.9.5.29_A3_T1.js | 11 +- .../setUTCMilliseconds/S15.9.5.29_A3_T2.js | 16 +- .../setUTCMilliseconds/S15.9.5.29_A3_T3.js | 14 +- .../setUTCMilliseconds/arg-coercion-order.js | 32 + .../setUTCMinutes/S15.9.5.33_A1_T1.js | 14 +- .../setUTCMinutes/S15.9.5.33_A1_T2.js | 16 +- .../setUTCMinutes/S15.9.5.33_A1_T3.js | 14 +- .../setUTCMinutes/S15.9.5.33_A2_T1.js | 17 +- .../setUTCMinutes/S15.9.5.33_A3_T1.js | 11 +- .../setUTCMinutes/S15.9.5.33_A3_T2.js | 16 +- .../setUTCMinutes/S15.9.5.33_A3_T3.js | 14 +- .../setUTCMinutes/arg-coercion-order.js | 50 + .../prototype/setUTCMonth/S15.9.5.39_A1_T1.js | 14 +- .../prototype/setUTCMonth/S15.9.5.39_A1_T2.js | 16 +- .../prototype/setUTCMonth/S15.9.5.39_A1_T3.js | 14 +- .../prototype/setUTCMonth/S15.9.5.39_A2_T1.js | 17 +- .../prototype/setUTCMonth/S15.9.5.39_A3_T1.js | 11 +- .../prototype/setUTCMonth/S15.9.5.39_A3_T2.js | 16 +- .../prototype/setUTCMonth/S15.9.5.39_A3_T3.js | 14 +- .../setUTCMonth/arg-coercion-order.js | 42 + .../setUTCSeconds/S15.9.5.31_A1_T1.js | 14 +- .../setUTCSeconds/S15.9.5.31_A1_T2.js | 16 +- .../setUTCSeconds/S15.9.5.31_A1_T3.js | 14 +- .../setUTCSeconds/S15.9.5.31_A2_T1.js | 17 +- .../setUTCSeconds/S15.9.5.31_A3_T1.js | 11 +- .../setUTCSeconds/S15.9.5.31_A3_T2.js | 16 +- .../setUTCSeconds/S15.9.5.31_A3_T3.js | 14 +- .../setUTCSeconds/arg-coercion-order.js | 42 + .../prototype/toDateString/S15.9.5.3_A1_T1.js | 14 +- .../prototype/toDateString/S15.9.5.3_A1_T2.js | 16 +- .../prototype/toDateString/S15.9.5.3_A1_T3.js | 14 +- .../prototype/toDateString/S15.9.5.3_A2_T1.js | 17 +- .../prototype/toDateString/S15.9.5.3_A3_T1.js | 11 +- .../prototype/toDateString/S15.9.5.3_A3_T2.js | 16 +- .../prototype/toDateString/S15.9.5.3_A3_T3.js | 14 +- .../toLocaleDateString/S15.9.5.6_A1_T1.js | 14 +- .../toLocaleDateString/S15.9.5.6_A1_T2.js | 16 +- .../toLocaleDateString/S15.9.5.6_A1_T3.js | 14 +- .../toLocaleDateString/S15.9.5.6_A2_T1.js | 17 +- .../toLocaleDateString/S15.9.5.6_A3_T1.js | 11 +- .../toLocaleDateString/S15.9.5.6_A3_T2.js | 16 +- .../toLocaleDateString/S15.9.5.6_A3_T3.js | 14 +- .../toLocaleString/S15.9.5.5_A1_T1.js | 14 +- .../toLocaleString/S15.9.5.5_A1_T2.js | 17 +- .../toLocaleString/S15.9.5.5_A1_T3.js | 14 +- .../toLocaleString/S15.9.5.5_A2_T1.js | 16 +- .../toLocaleString/S15.9.5.5_A3_T1.js | 11 +- .../toLocaleString/S15.9.5.5_A3_T2.js | 17 +- .../toLocaleString/S15.9.5.5_A3_T3.js | 14 +- .../toLocaleTimeString/S15.9.5.7_A1_T1.js | 14 +- .../toLocaleTimeString/S15.9.5.7_A1_T2.js | 17 +- .../toLocaleTimeString/S15.9.5.7_A1_T3.js | 14 +- .../toLocaleTimeString/S15.9.5.7_A2_T1.js | 16 +- .../toLocaleTimeString/S15.9.5.7_A3_T1.js | 11 +- .../toLocaleTimeString/S15.9.5.7_A3_T2.js | 17 +- .../toLocaleTimeString/S15.9.5.7_A3_T3.js | 14 +- .../prototype/toString/S15.9.5.2_A1_T1.js | 14 +- .../prototype/toString/S15.9.5.2_A1_T2.js | 12 +- .../prototype/toString/S15.9.5.2_A1_T3.js | 14 +- .../prototype/toString/S15.9.5.2_A2_T1.js | 12 +- .../prototype/toString/S15.9.5.2_A3_T1.js | 11 +- .../prototype/toString/S15.9.5.2_A3_T2.js | 17 +- .../prototype/toString/S15.9.5.2_A3_T3.js | 14 +- .../prototype/toTimeString/S15.9.5.4_A1_T1.js | 14 +- .../prototype/toTimeString/S15.9.5.4_A1_T2.js | 17 +- .../prototype/toTimeString/S15.9.5.4_A1_T3.js | 14 +- .../prototype/toTimeString/S15.9.5.4_A2_T1.js | 18 +- .../prototype/toTimeString/S15.9.5.4_A3_T1.js | 11 +- .../prototype/toTimeString/S15.9.5.4_A3_T2.js | 16 +- .../prototype/toTimeString/S15.9.5.4_A3_T3.js | 14 +- .../prototype/toUTCString/S15.9.5.42_A1_T1.js | 14 +- .../prototype/toUTCString/S15.9.5.42_A1_T2.js | 17 +- .../prototype/toUTCString/S15.9.5.42_A1_T3.js | 14 +- .../prototype/toUTCString/S15.9.5.42_A2_T1.js | 16 +- .../prototype/toUTCString/S15.9.5.42_A3_T1.js | 11 +- .../prototype/toUTCString/S15.9.5.42_A3_T2.js | 17 +- .../prototype/toUTCString/S15.9.5.42_A3_T3.js | 14 +- .../Date/prototype/valueOf/S15.9.5.8_A1_T1.js | 14 +- .../Date/prototype/valueOf/S15.9.5.8_A1_T2.js | 13 +- .../Date/prototype/valueOf/S15.9.5.8_A1_T3.js | 14 +- .../Date/prototype/valueOf/S15.9.5.8_A2_T1.js | 12 +- .../Date/prototype/valueOf/S15.9.5.8_A3_T1.js | 11 +- .../Date/prototype/valueOf/S15.9.5.8_A3_T2.js | 17 +- .../Date/prototype/valueOf/S15.9.5.8_A3_T3.js | 14 +- .../Date/prototype/valueOf/S9.4_A3_T1.js | 48 +- .../Date/prototype/valueOf/S9.4_A3_T2.js | 14 +- .../Error/prototype/S15.11.3.1_A1_T1.js | 10 +- .../Error/prototype/S15.11.3.1_A2_T1.js | 30 +- .../Error/prototype/S15.11.3.1_A3_T1.js | 29 +- .../Error/prototype/S15.11.3.1_A4_T1.js | 9 +- .../built-ins/Error/prototype/S15.11.4_A1.js | 12 +- .../built-ins/Error/prototype/S15.11.4_A2.js | 8 +- .../built-ins/Error/prototype/S15.11.4_A3.js | 12 +- .../built-ins/Error/prototype/S15.11.4_A4.js | 14 +- .../prototype/constructor/S15.11.4.1_A1_T2.js | 40 +- .../Error/prototype/toString/S15.11.4.4_A2.js | 17 +- ...-has-one-chance-to-call-cleanupCallback.js | 2 +- .../callback-not-callable-throws.js | 2 +- .../cleanup-prevented-with-reference.js | 2 +- .../cleanup-prevented-with-unregister.js | 2 +- .../prototype/cleanupSome/custom-this.js | 2 +- .../cleanupSome/holdings-multiple-values.js | 2 +- .../prototype/cleanupSome/length.js | 2 +- .../prototype/cleanupSome/name.js | 2 +- .../prototype/cleanupSome/prop-desc.js | 2 +- .../prototype/cleanupSome/reentrancy.js | 2 +- .../cleanupSome/return-undefined-with-gc.js | 2 +- .../prototype/cleanupSome/return-undefined.js | 2 +- ...his-does-not-have-internal-cells-throws.js | 2 +- .../cleanupSome/this-not-object-throws.js | 2 +- .../unregister/unregister-cleaned-up-cell.js | 2 +- .../built-ins/FinalizationRegistry/shell.js | 2 +- .../built-ins/Function/S10.1.1_A1_T3.js | 9 +- .../built-ins/Function/S15.3.1_A1_T1.js | 28 +- .../built-ins/Function/S15.3.2.1_A1_T1.js | 5 +- .../built-ins/Function/S15.3.2.1_A1_T10.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T11.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T12.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T13.js | 8 +- .../built-ins/Function/S15.3.2.1_A1_T2.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T3.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T4.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T5.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T6.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T7.js | 12 +- .../built-ins/Function/S15.3.2.1_A1_T8.js | 8 +- .../built-ins/Function/S15.3.2.1_A1_T9.js | 11 +- .../built-ins/Function/S15.3.2.1_A2_T1.js | 12 +- .../built-ins/Function/S15.3.2.1_A2_T2.js | 12 +- .../built-ins/Function/S15.3.2.1_A2_T3.js | 12 +- .../built-ins/Function/S15.3.2.1_A2_T4.js | 12 +- .../built-ins/Function/S15.3.2.1_A2_T5.js | 12 +- .../built-ins/Function/S15.3.2.1_A2_T6.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T1.js | 5 +- .../built-ins/Function/S15.3.2.1_A3_T10.js | 8 +- .../built-ins/Function/S15.3.2.1_A3_T11.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T12.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T13.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T14.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T15.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T2.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T3.js | 10 +- .../built-ins/Function/S15.3.2.1_A3_T4.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T5.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T6.js | 8 +- .../built-ins/Function/S15.3.2.1_A3_T7.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T8.js | 12 +- .../built-ins/Function/S15.3.2.1_A3_T9.js | 8 +- .../test262/built-ins/Function/S15.3.2_A1.js | 11 +- .../test262/built-ins/Function/S15.3.3_A1.js | 5 +- .../built-ins/Function/S15.3.3_A2_T1.js | 9 +- .../built-ins/Function/S15.3.3_A2_T2.js | 5 +- .../test262/built-ins/Function/S15.3.3_A3.js | 12 +- .../built-ins/Function/S15.3.5_A1_T1.js | 8 +- .../built-ins/Function/S15.3.5_A1_T2.js | 8 +- .../built-ins/Function/S15.3.5_A2_T1.js | 21 +- .../built-ins/Function/S15.3.5_A2_T2.js | 21 +- .../built-ins/Function/S15.3.5_A3_T1.js | 17 +- .../built-ins/Function/S15.3.5_A3_T2.js | 17 +- .../test262/built-ins/Function/S15.3_A1.js | 4 +- .../test262/built-ins/Function/S15.3_A2_T1.js | 8 +- .../test262/built-ins/Function/S15.3_A2_T2.js | 8 +- .../test262/built-ins/Function/S15.3_A3_T1.js | 7 +- .../test262/built-ins/Function/S15.3_A3_T2.js | 10 +- .../test262/built-ins/Function/S15.3_A3_T3.js | 22 +- .../test262/built-ins/Function/S15.3_A3_T4.js | 10 +- .../test262/built-ins/Function/S15.3_A3_T5.js | 21 +- .../test262/built-ins/Function/S15.3_A3_T6.js | 10 +- .../StrictFunction_reservedwords_with.js | 4 +- ...ctFunction_restricted-properties-strict.js | 20 +- .../internals/Call/class-ctor-realm.js | 2 +- .../Function/length/S15.3.5.1_A1_T1.js | 11 +- .../Function/length/S15.3.5.1_A1_T2.js | 11 +- .../Function/length/S15.3.5.1_A1_T3.js | 11 +- .../Function/length/S15.3.5.1_A2_T1.js | 23 +- .../Function/length/S15.3.5.1_A2_T2.js | 16 +- .../Function/length/S15.3.5.1_A2_T3.js | 16 +- .../Function/length/S15.3.5.1_A3_T1.js | 18 +- .../Function/length/S15.3.5.1_A3_T2.js | 18 +- .../Function/length/S15.3.5.1_A3_T3.js | 18 +- .../Function/length/S15.3.5.1_A4_T1.js | 12 +- .../Function/length/S15.3.5.1_A4_T2.js | 12 +- .../Function/length/S15.3.5.1_A4_T3.js | 12 +- .../Function/prototype/S15.3.3.1_A1.js | 12 +- .../Function/prototype/S15.3.3.1_A2.js | 19 +- .../Function/prototype/S15.3.3.1_A3.js | 12 +- .../Function/prototype/S15.3.3.1_A4.js | 10 +- .../Function/prototype/S15.3.4_A1.js | 10 +- .../Function/prototype/S15.3.4_A2_T1.js | 5 +- .../Function/prototype/S15.3.4_A2_T2.js | 5 +- .../Function/prototype/S15.3.4_A2_T3.js | 11 +- .../Function/prototype/S15.3.4_A3_T1.js | 11 +- .../Function/prototype/S15.3.4_A3_T2.js | 5 +- .../Function/prototype/S15.3.4_A4.js | 28 +- .../Function/prototype/S15.3.4_A5.js | 2 +- .../Function/prototype/S15.3.5.2_A1_T1.js | 17 +- .../Function/prototype/S15.3.5.2_A1_T2.js | 17 +- .../Function/prototype/apply/S15.3.4.3_A12.js | 10 +- .../prototype/apply/S15.3.4.3_A1_T1.js | 12 +- .../prototype/apply/S15.3.4.3_A1_T2.js | 12 +- .../prototype/apply/S15.3.4.3_A3_T1.js | 5 +- .../prototype/apply/S15.3.4.3_A3_T10.js | 5 +- .../prototype/apply/S15.3.4.3_A3_T2.js | 5 +- .../prototype/apply/S15.3.4.3_A3_T3.js | 5 +- .../prototype/apply/S15.3.4.3_A3_T4.js | 5 +- .../prototype/apply/S15.3.4.3_A3_T5.js | 13 +- .../prototype/apply/S15.3.4.3_A3_T6.js | 13 +- .../prototype/apply/S15.3.4.3_A3_T7.js | 5 +- .../prototype/apply/S15.3.4.3_A3_T8.js | 5 +- .../prototype/apply/S15.3.4.3_A3_T9.js | 5 +- .../prototype/apply/S15.3.4.3_A5_T1.js | 11 +- .../prototype/apply/S15.3.4.3_A5_T2.js | 11 +- .../prototype/apply/S15.3.4.3_A5_T3.js | 11 +- .../prototype/apply/S15.3.4.3_A5_T4.js | 11 +- .../prototype/apply/S15.3.4.3_A5_T5.js | 5 +- .../prototype/apply/S15.3.4.3_A5_T6.js | 5 +- .../prototype/apply/S15.3.4.3_A5_T7.js | 5 +- .../prototype/apply/S15.3.4.3_A5_T8.js | 5 +- .../prototype/apply/S15.3.4.3_A7_T1.js | 5 +- .../prototype/apply/S15.3.4.3_A7_T10.js | 14 +- .../prototype/apply/S15.3.4.3_A7_T2.js | 5 +- .../prototype/apply/S15.3.4.3_A7_T3.js | 14 +- .../prototype/apply/S15.3.4.3_A7_T4.js | 14 +- .../prototype/apply/S15.3.4.3_A7_T5.js | 11 +- .../prototype/apply/S15.3.4.3_A7_T6.js | 14 +- .../prototype/apply/S15.3.4.3_A7_T7.js | 5 +- .../prototype/apply/S15.3.4.3_A7_T8.js | 5 +- .../prototype/apply/S15.3.4.3_A7_T9.js | 14 +- .../prototype/apply/S15.3.4.3_A8_T1.js | 19 - .../prototype/apply/S15.3.4.3_A8_T2.js | 19 - .../prototype/apply/S15.3.4.3_A8_T3.js | 4 +- .../prototype/apply/S15.3.4.3_A8_T4.js | 4 +- .../prototype/apply/S15.3.4.3_A8_T5.js | 4 +- .../prototype/apply/S15.3.4.3_A8_T6.js | 6 +- .../prototype/apply/not-a-constructor.js | 5 +- .../Function/prototype/bind/S15.3.4.5_A1.js | 2 +- .../Function/prototype/bind/S15.3.4.5_A13.js | 2 +- .../Function/prototype/bind/S15.3.4.5_A14.js | 2 +- .../Function/prototype/bind/S15.3.4.5_A15.js | 2 +- .../Function/prototype/bind/S15.3.4.5_A16.js | 4 +- .../Function/prototype/bind/S15.3.4.5_A2.js | 2 +- .../Function/prototype/bind/S15.3.4.5_A3.js | 8 +- .../Function/prototype/bind/S15.3.4.5_A5.js | 9 +- .../Function/prototype/call/S15.3.4.4_A10.js | 20 +- .../Function/prototype/call/S15.3.4.4_A11.js | 23 +- .../Function/prototype/call/S15.3.4.4_A12.js | 10 +- .../Function/prototype/call/S15.3.4.4_A13.js | 2 +- .../Function/prototype/call/S15.3.4.4_A14.js | 2 +- .../Function/prototype/call/S15.3.4.4_A15.js | 2 +- .../Function/prototype/call/S15.3.4.4_A16.js | 4 +- .../prototype/call/S15.3.4.4_A1_T1.js | 12 +- .../prototype/call/S15.3.4.4_A1_T2.js | 12 +- .../prototype/call/S15.3.4.4_A2_T1.js | 24 +- .../prototype/call/S15.3.4.4_A2_T2.js | 17 +- .../prototype/call/S15.3.4.4_A3_T1.js | 5 +- .../prototype/call/S15.3.4.4_A3_T10.js | 5 +- .../prototype/call/S15.3.4.4_A3_T2.js | 5 +- .../prototype/call/S15.3.4.4_A3_T3.js | 5 +- .../prototype/call/S15.3.4.4_A3_T4.js | 5 +- .../prototype/call/S15.3.4.4_A3_T5.js | 13 +- .../prototype/call/S15.3.4.4_A3_T6.js | 13 +- .../prototype/call/S15.3.4.4_A3_T7.js | 5 +- .../prototype/call/S15.3.4.4_A3_T8.js | 5 +- .../prototype/call/S15.3.4.4_A3_T9.js | 5 +- .../prototype/call/S15.3.4.4_A5_T1.js | 11 +- .../prototype/call/S15.3.4.4_A5_T2.js | 11 +- .../prototype/call/S15.3.4.4_A5_T3.js | 11 +- .../prototype/call/S15.3.4.4_A5_T4.js | 11 +- .../prototype/call/S15.3.4.4_A5_T5.js | 5 +- .../prototype/call/S15.3.4.4_A5_T6.js | 5 +- .../prototype/call/S15.3.4.4_A5_T7.js | 5 +- .../prototype/call/S15.3.4.4_A5_T8.js | 5 +- .../prototype/call/S15.3.4.4_A6_T1.js | 20 +- .../prototype/call/S15.3.4.4_A6_T10.js | 14 +- .../prototype/call/S15.3.4.4_A6_T2.js | 6 +- .../prototype/call/S15.3.4.4_A6_T3.js | 7 +- .../prototype/call/S15.3.4.4_A6_T4.js | 14 +- .../prototype/call/S15.3.4.4_A6_T5.js | 11 +- .../prototype/call/S15.3.4.4_A6_T6.js | 14 +- .../prototype/call/S15.3.4.4_A6_T7.js | 5 +- .../prototype/call/S15.3.4.4_A6_T8.js | 5 +- .../prototype/call/S15.3.4.4_A6_T9.js | 14 +- .../prototype/call/S15.3.4.4_A7_T1.js | 19 - .../prototype/call/S15.3.4.4_A7_T2.js | 20 - .../prototype/call/S15.3.4.4_A7_T3.js | 4 +- .../prototype/call/S15.3.4.4_A7_T4.js | 4 +- .../prototype/call/S15.3.4.4_A7_T5.js | 4 +- .../prototype/call/S15.3.4.4_A7_T6.js | 6 +- .../Function/prototype/call/S15.3.4.4_A9.js | 25 +- .../prototype/call/not-a-constructor.js | 8 + .../prototype/constructor/S15.3.4.1_A1_T1.js | 10 +- .../restricted-property-arguments.js | 3 +- .../prototype/restricted-property-caller.js | 3 +- .../prototype/toString/S15.3.4.2_A10.js | 20 +- .../prototype/toString/S15.3.4.2_A11.js | 18 +- .../prototype/toString/S15.3.4.2_A12.js | 2 +- .../prototype/toString/S15.3.4.2_A13.js | 2 +- .../prototype/toString/S15.3.4.2_A14.js | 2 +- .../prototype/toString/S15.3.4.2_A16.js | 2 +- .../prototype/toString/S15.3.4.2_A6.js | 10 +- .../prototype/toString/S15.3.4.2_A7.js | 16 - .../prototype/toString/S15.3.4.2_A8.js | 23 +- .../prototype/toString/S15.3.4.2_A9.js | 25 +- .../prototype/toString/not-a-constructor.js | 4 + .../built-ins/Infinity/S15.1.1.2_A1.js | 28 +- .../built-ins/Infinity/S15.1.1.2_A2_T2.js | 6 +- .../built-ins/Infinity/S15.1.1.2_A3_T2.js | 6 +- .../built-ins/Infinity/S15.1.1.2_A4.js | 6 +- .../built-ins/JSON/parse/S15.12.2_A1.js | 14 +- .../built-ins/Map/bigint-number-same-value.js | 46 + .../test262/built-ins/Map/constructor.js | 2 +- ...does-not-throw-when-set-is-not-callable.js | 2 +- .../built-ins/Map/get-set-method-failure.js | 2 +- .../built-ins/Map/iterable-calls-set.js | 6 +- .../Map/iterator-close-after-set-failure.js | 2 +- ...terator-item-first-entry-returns-abrupt.js | 2 +- ...erator-item-second-entry-returns-abrupt.js | 2 +- ...tor-items-are-not-object-close-iterator.js | 2 +- .../Map/iterator-items-are-not-object.js | 2 +- .../built-ins/Map/iterator-next-failure.js | 2 +- .../built-ins/Map/iterator-value-failure.js | 2 +- .../map-iterable-empty-does-not-call-set.js | 2 +- ...terable-throws-when-set-is-not-callable.js | 2 +- .../test262/built-ins/Map/map-iterable.js | 2 +- .../Map/map-no-iterable-does-not-call-set.js | 2 +- .../test262/built-ins/Map/map-no-iterable.js | 2 +- js/src/tests/test262/built-ins/Map/map.js | 2 +- js/src/tests/test262/built-ins/Map/name.js | 2 +- .../tests/test262/built-ins/Map/newtarget.js | 2 +- .../Map/prototype/Symbol.iterator.js | 2 +- .../Map/prototype/Symbol.toStringTag.js | 2 +- .../Map/prototype/clear/clear-map.js | 2 +- .../built-ins/Map/prototype/clear/clear.js | 2 +- .../clear/context-is-not-map-object.js | 2 +- .../prototype/clear/context-is-not-object.js | 2 +- .../clear/context-is-set-object-throws.js | 2 +- .../clear/context-is-weakmap-object-throws.js | 2 +- .../built-ins/Map/prototype/clear/length.js | 2 +- .../clear/map-data-list-is-preserved.js | 2 +- .../built-ins/Map/prototype/clear/name.js | 2 +- .../Map/prototype/clear/returns-undefined.js | 2 +- .../built-ins/Map/prototype/constructor.js | 2 +- .../delete/context-is-not-map-object.js | 2 +- .../prototype/delete/context-is-not-object.js | 2 +- .../delete/context-is-set-object-throws.js | 2 +- .../context-is-weakmap-object-throws.js | 2 +- .../built-ins/Map/prototype/delete/delete.js | 2 +- .../delete/does-not-break-iterators.js | 2 +- .../built-ins/Map/prototype/delete/length.js | 2 +- .../built-ins/Map/prototype/delete/name.js | 2 +- .../Map/prototype/delete/returns-false.js | 2 +- .../delete/returns-true-for-deleted-entry.js | 2 +- .../built-ins/Map/prototype/descriptor.js | 2 +- ...does-not-have-mapdata-internal-slot-set.js | 2 +- ...-not-have-mapdata-internal-slot-weakmap.js | 2 +- .../does-not-have-mapdata-internal-slot.js | 2 +- .../Map/prototype/entries/entries.js | 2 +- .../built-ins/Map/prototype/entries/length.js | 2 +- .../built-ins/Map/prototype/entries/name.js | 2 +- .../entries/returns-iterator-empty.js | 2 +- .../Map/prototype/entries/returns-iterator.js | 2 +- .../entries/this-not-object-throw.js | 2 +- .../prototype/forEach/callback-parameters.js | 2 +- .../forEach/callback-result-is-abrupt.js | 2 +- .../forEach/callback-this-non-strict.js | 2 +- .../forEach/callback-this-strict-strict.js | 2 +- .../forEach/deleted-values-during-foreach.js | 2 +- ...does-not-have-mapdata-internal-slot-set.js | 2 +- ...-not-have-mapdata-internal-slot-weakmap.js | 2 +- .../does-not-have-mapdata-internal-slot.js | 2 +- .../forEach/first-argument-is-not-callable.js | 2 +- .../Map/prototype/forEach/forEach.js | 2 +- .../iterates-in-key-insertion-order.js | 2 +- ...rates-values-added-after-foreach-begins.js | 2 +- .../iterates-values-deleted-then-readded.js | 2 +- .../built-ins/Map/prototype/forEach/length.js | 2 +- .../built-ins/Map/prototype/forEach/name.js | 2 +- .../Map/prototype/forEach/return-undefined.js | 2 +- .../second-parameter-as-callback-context.js | 2 +- .../forEach/this-not-object-throw.js | 2 +- ...does-not-have-mapdata-internal-slot-set.js | 2 +- ...-not-have-mapdata-internal-slot-weakmap.js | 2 +- .../does-not-have-mapdata-internal-slot.js | 2 +- .../built-ins/Map/prototype/get/get.js | 2 +- .../built-ins/Map/prototype/get/length.js | 2 +- .../built-ins/Map/prototype/get/name.js | 2 +- .../Map/prototype/get/returns-undefined.js | 2 +- .../get/returns-value-different-key-types.js | 2 +- .../get/returns-value-normalized-zero-key.js | 2 +- .../prototype/get/this-not-object-throw.js | 2 +- ...does-not-have-mapdata-internal-slot-set.js | 2 +- ...-not-have-mapdata-internal-slot-weakmap.js | 2 +- .../does-not-have-mapdata-internal-slot.js | 2 +- .../built-ins/Map/prototype/has/has.js | 2 +- .../built-ins/Map/prototype/has/length.js | 2 +- .../built-ins/Map/prototype/has/name.js | 2 +- .../Map/prototype/has/normalizes-zero-key.js | 2 +- .../has/return-false-different-key-types.js | 2 +- .../has/return-true-different-key-types.js | 2 +- .../prototype/has/this-not-object-throw.js | 2 +- ...does-not-have-mapdata-internal-slot-set.js | 2 +- ...-not-have-mapdata-internal-slot-weakmap.js | 2 +- .../does-not-have-mapdata-internal-slot.js | 2 +- .../built-ins/Map/prototype/keys/keys.js | 2 +- .../built-ins/Map/prototype/keys/length.js | 2 +- .../built-ins/Map/prototype/keys/name.js | 2 +- .../prototype/keys/returns-iterator-empty.js | 2 +- .../Map/prototype/keys/returns-iterator.js | 2 +- .../prototype/keys/this-not-object-throw.js | 2 +- .../append-new-values-normalizes-zero-key.js | 2 +- .../set/append-new-values-return-map.js | 2 +- .../Map/prototype/set/append-new-values.js | 2 +- ...does-not-have-mapdata-internal-slot-set.js | 2 +- ...-not-have-mapdata-internal-slot-weakmap.js | 2 +- .../does-not-have-mapdata-internal-slot.js | 2 +- .../built-ins/Map/prototype/set/length.js | 2 +- .../built-ins/Map/prototype/set/name.js | 2 +- .../replaces-a-value-normalizes-zero-key.js | 2 +- .../set/replaces-a-value-returns-map.js | 2 +- .../Map/prototype/set/replaces-a-value.js | 2 +- .../built-ins/Map/prototype/set/set.js | 2 +- .../prototype/set/this-not-object-throw.js | 2 +- ...does-not-have-mapdata-internal-slot-set.js | 6 +- ...-not-have-mapdata-internal-slot-weakmap.js | 2 +- .../does-not-have-mapdata-internal-slot.js | 2 +- .../built-ins/Map/prototype/size/length.js | 2 +- .../built-ins/Map/prototype/size/name.js | 2 +- ...f-present-values-before-after-set-clear.js | 2 +- ...-present-values-before-after-set-delete.js | 2 +- ...ns-count-of-present-values-by-insertion.js | 2 +- ...rns-count-of-present-values-by-iterable.js | 2 +- .../built-ins/Map/prototype/size/size.js | 2 +- .../prototype/size/this-not-object-throw.js | 2 +- ...does-not-have-mapdata-internal-slot-set.js | 2 +- ...-not-have-mapdata-internal-slot-weakmap.js | 2 +- .../does-not-have-mapdata-internal-slot.js | 2 +- .../built-ins/Map/prototype/values/length.js | 2 +- .../built-ins/Map/prototype/values/name.js | 2 +- .../values/returns-iterator-empty.js | 2 +- .../Map/prototype/values/returns-iterator.js | 2 +- .../prototype/values/this-not-object-throw.js | 2 +- .../built-ins/Map/prototype/values/values.js | 2 +- .../built-ins/Map/symbol-as-entry-key.js | 20 - .../built-ins/Map/undefined-newtarget.js | 2 +- .../tests/test262/built-ins/Map/valid-keys.js | 486 ++ .../Math/hypot/Math.hypot_ToNumberErr.js | 37 + .../built-ins/Math/hypot/Math.hypot_Zero_2.js | 6 +- .../test262/built-ins/NaN/S15.1.1.1_A2_T2.js | 6 +- .../test262/built-ins/NaN/S15.1.1.1_A3_T2.js | 6 +- .../test262/built-ins/NaN/S15.1.1.1_A4.js | 6 +- .../Number/MAX_VALUE/S15.7.3.2_A2.js | 6 +- .../Number/MAX_VALUE/S15.7.3.2_A3.js | 10 +- .../Number/MAX_VALUE/S15.7.3.2_A4.js | 14 +- .../Number/MIN_VALUE/S15.7.3.3_A2.js | 6 +- .../Number/MIN_VALUE/S15.7.3.3_A3.js | 11 +- .../Number/MIN_VALUE/S15.7.3.3_A4.js | 14 +- .../Number/NEGATIVE_INFINITY/S15.7.3.5_A1.js | 10 +- .../Number/NEGATIVE_INFINITY/S15.7.3.5_A2.js | 14 +- .../Number/POSITIVE_INFINITY/S15.7.3.6_A1.js | 10 +- .../Number/POSITIVE_INFINITY/S15.7.3.6_A2.js | 14 +- .../test262/built-ins/Number/S15.7.1.1_A1.js | 35 +- .../test262/built-ins/Number/S15.7.1.1_A2.js | 14 +- .../test262/built-ins/Number/S15.7.2.1_A1.js | 44 +- .../test262/built-ins/Number/S15.7.2.1_A2.js | 24 +- .../test262/built-ins/Number/S15.7.2.1_A3.js | 12 +- .../test262/built-ins/Number/S15.7.2.1_A4.js | 5 +- .../test262/built-ins/Number/S15.7.3_A1.js | 5 +- .../test262/built-ins/Number/S15.7.3_A2.js | 5 +- .../test262/built-ins/Number/S15.7.3_A3.js | 5 +- .../test262/built-ins/Number/S15.7.3_A4.js | 5 +- .../test262/built-ins/Number/S15.7.3_A5.js | 8 +- .../test262/built-ins/Number/S15.7.3_A6.js | 8 +- .../test262/built-ins/Number/S15.7.3_A7.js | 9 +- .../test262/built-ins/Number/S15.7.3_A8.js | 12 +- .../built-ins/Number/S15.7.5_A1_T01.js | 19 +- .../built-ins/Number/S15.7.5_A1_T02.js | 19 +- .../built-ins/Number/S15.7.5_A1_T03.js | 19 +- .../built-ins/Number/S15.7.5_A1_T04.js | 19 +- .../built-ins/Number/S15.7.5_A1_T05.js | 19 +- .../built-ins/Number/S15.7.5_A1_T06.js | 19 +- .../built-ins/Number/S15.7.5_A1_T07.js | 19 +- .../test262/built-ins/Number/S8.12.8_A3.js | 9 +- .../test262/built-ins/Number/S8.12.8_A4.js | 8 +- .../test262/built-ins/Number/S9.1_A1_T1.js | 18 +- .../test262/built-ins/Number/S9.3.1_A1.js | 10 +- .../test262/built-ins/Number/S9.3.1_A10.js | 6 +- .../test262/built-ins/Number/S9.3.1_A11.js | 14 +- .../test262/built-ins/Number/S9.3.1_A12.js | 12 +- .../test262/built-ins/Number/S9.3.1_A13.js | 28 +- .../test262/built-ins/Number/S9.3.1_A14.js | 6 +- .../test262/built-ins/Number/S9.3.1_A15.js | 10 +- .../test262/built-ins/Number/S9.3.1_A16.js | 18 +- .../test262/built-ins/Number/S9.3.1_A17.js | 18 +- .../test262/built-ins/Number/S9.3.1_A18.js | 18 +- .../test262/built-ins/Number/S9.3.1_A19.js | 18 +- .../test262/built-ins/Number/S9.3.1_A2.js | 303 +- .../test262/built-ins/Number/S9.3.1_A20.js | 18 +- .../test262/built-ins/Number/S9.3.1_A21.js | 18 +- .../test262/built-ins/Number/S9.3.1_A22.js | 18 +- .../test262/built-ins/Number/S9.3.1_A23.js | 18 +- .../test262/built-ins/Number/S9.3.1_A24.js | 18 +- .../test262/built-ins/Number/S9.3.1_A25.js | 18 +- .../test262/built-ins/Number/S9.3.1_A26.js | 24 +- .../test262/built-ins/Number/S9.3.1_A27.js | 24 +- .../test262/built-ins/Number/S9.3.1_A28.js | 24 +- .../test262/built-ins/Number/S9.3.1_A29.js | 24 +- .../test262/built-ins/Number/S9.3.1_A30.js | 24 +- .../test262/built-ins/Number/S9.3.1_A31.js | 24 +- .../test262/built-ins/Number/S9.3.1_A32.js | 46 +- .../test262/built-ins/Number/S9.3.1_A3_T1.js | 33 +- .../test262/built-ins/Number/S9.3.1_A3_T2.js | 32 +- .../test262/built-ins/Number/S9.3.1_A4_T1.js | 59 +- .../test262/built-ins/Number/S9.3.1_A4_T2.js | 61 +- .../test262/built-ins/Number/S9.3.1_A5_T1.js | 70 +- .../test262/built-ins/Number/S9.3.1_A5_T2.js | 162 +- .../test262/built-ins/Number/S9.3.1_A5_T3.js | 74 +- .../test262/built-ins/Number/S9.3.1_A6_T1.js | 27 +- .../test262/built-ins/Number/S9.3.1_A6_T2.js | 36 +- .../test262/built-ins/Number/S9.3.1_A7.js | 10 +- .../test262/built-ins/Number/S9.3.1_A8.js | 12 +- .../test262/built-ins/Number/S9.3.1_A9.js | 19 +- .../test262/built-ins/Number/S9.3_A2_T1.js | 10 +- .../test262/built-ins/Number/S9.3_A3_T1.js | 16 +- .../test262/built-ins/Number/S9.3_A4.1_T1.js | 24 +- .../test262/built-ins/Number/S9.3_A4.2_T1.js | 50 +- .../test262/built-ins/Number/S9.3_A5_T1.js | 80 +- .../Number/prototype/S15.7.3.1_A2_T1.js | 18 +- .../Number/prototype/S15.7.3.1_A2_T2.js | 18 +- .../Number/prototype/S15.7.3.1_A3.js | 8 +- .../built-ins/Number/prototype/S15.7.4_A1.js | 25 +- .../built-ins/Number/prototype/S15.7.4_A2.js | 9 +- .../Number/prototype/S15.7.4_A3.1.js | 10 +- .../Number/prototype/S15.7.4_A3.2.js | 10 +- .../Number/prototype/S15.7.4_A3.3.js | 10 +- .../Number/prototype/S15.7.4_A3.4.js | 10 +- .../Number/prototype/S15.7.4_A3.5.js | 10 +- .../Number/prototype/S15.7.4_A3.6.js | 10 +- .../Number/prototype/S15.7.4_A3.7.js | 10 +- .../prototype/toFixed/S15.7.4.5_A1.1_T01.js | 69 +- .../prototype/toFixed/S15.7.4.5_A1.1_T02.js | 68 +- .../prototype/toFixed/S15.7.4.5_A1.3_T01.js | 71 +- .../prototype/toFixed/S15.7.4.5_A1.3_T02.js | 65 +- .../prototype/toFixed/S15.7.4.5_A1.4_T01.js | 96 +- .../prototype/toFixed/S15.7.4.5_A2_T01.js | 19 +- .../prototype/toString/S15.7.4.2_A1_T01.js | 54 +- .../prototype/toString/S15.7.4.2_A1_T02.js | 57 +- .../prototype/toString/S15.7.4.2_A1_T03.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T01.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T02.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T03.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T04.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T05.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T06.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T07.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T08.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T09.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T10.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T11.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T12.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T13.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T14.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T15.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T16.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T17.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T18.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T19.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T20.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T21.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T22.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T23.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T24.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T25.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T26.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T27.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T28.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T29.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T30.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T31.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T32.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T33.js | 57 +- .../prototype/toString/S15.7.4.2_A2_T34.js | 57 +- .../prototype/toString/S15.7.4.2_A3_T01.js | 8 - .../prototype/toString/S15.7.4.2_A3_T02.js | 8 - .../prototype/toString/S15.7.4.2_A3_T03.js | 8 - .../prototype/toString/S15.7.4.2_A3_T04.js | 8 - .../prototype/toString/S15.7.4.2_A4_T01.js | 10 +- .../prototype/toString/S15.7.4.2_A4_T02.js | 10 +- .../prototype/toString/S15.7.4.2_A4_T03.js | 10 +- .../prototype/toString/S15.7.4.2_A4_T04.js | 10 +- .../prototype/toString/S15.7.4.2_A4_T05.js | 10 +- .../prototype/valueOf/S15.7.4.4_A1_T01.js | 51 +- .../prototype/valueOf/S15.7.4.4_A1_T02.js | 51 +- .../prototype/valueOf/S15.7.4.4_A2_T01.js | 10 +- .../prototype/valueOf/S15.7.4.4_A2_T02.js | 10 +- .../prototype/valueOf/S15.7.4.4_A2_T03.js | 10 +- .../prototype/valueOf/S15.7.4.4_A2_T04.js | 10 +- .../prototype/valueOf/S15.7.4.4_A2_T05.js | 10 +- .../built-ins/Object/S15.2.1.1_A1_T1.js | 36 +- .../built-ins/Object/S15.2.1.1_A1_T2.js | 36 +- .../built-ins/Object/S15.2.1.1_A1_T3.js | 36 +- .../built-ins/Object/S15.2.1.1_A1_T4.js | 36 +- .../built-ins/Object/S15.2.1.1_A1_T5.js | 36 +- .../built-ins/Object/S15.2.1.1_A2_T1.js | 23 +- .../built-ins/Object/S15.2.1.1_A2_T10.js | 11 +- .../built-ins/Object/S15.2.1.1_A2_T11.js | 21 +- .../built-ins/Object/S15.2.1.1_A2_T12.js | 19 +- .../built-ins/Object/S15.2.1.1_A2_T13.js | 23 +- .../built-ins/Object/S15.2.1.1_A2_T14.js | 18 +- .../built-ins/Object/S15.2.1.1_A2_T2.js | 23 +- .../built-ins/Object/S15.2.1.1_A2_T3.js | 23 +- .../built-ins/Object/S15.2.1.1_A2_T4.js | 11 +- .../built-ins/Object/S15.2.1.1_A2_T5.js | 17 +- .../built-ins/Object/S15.2.1.1_A2_T6.js | 23 +- .../built-ins/Object/S15.2.1.1_A2_T7.js | 23 +- .../built-ins/Object/S15.2.1.1_A2_T8.js | 11 +- .../built-ins/Object/S15.2.1.1_A2_T9.js | 18 +- .../built-ins/Object/S15.2.1.1_A3_T1.js | 16 +- .../built-ins/Object/S15.2.1.1_A3_T2.js | 11 +- .../built-ins/Object/S15.2.1.1_A3_T3.js | 16 +- .../built-ins/Object/S15.2.2.1_A1_T1.js | 33 +- .../built-ins/Object/S15.2.2.1_A1_T2.js | 33 +- .../built-ins/Object/S15.2.2.1_A1_T3.js | 33 +- .../built-ins/Object/S15.2.2.1_A1_T4.js | 33 +- .../built-ins/Object/S15.2.2.1_A1_T5.js | 33 +- .../built-ins/Object/S15.2.2.1_A2_T1.js | 11 +- .../built-ins/Object/S15.2.2.1_A2_T2.js | 12 +- .../built-ins/Object/S15.2.2.1_A2_T3.js | 11 +- .../built-ins/Object/S15.2.2.1_A2_T5.js | 12 +- .../built-ins/Object/S15.2.2.1_A2_T6.js | 13 +- .../built-ins/Object/S15.2.2.1_A2_T7.js | 26 +- .../built-ins/Object/S15.2.2.1_A3_T1.js | 28 +- .../built-ins/Object/S15.2.2.1_A3_T2.js | 28 +- .../built-ins/Object/S15.2.2.1_A3_T3.js | 23 +- .../built-ins/Object/S15.2.2.1_A4_T1.js | 31 +- .../built-ins/Object/S15.2.2.1_A4_T2.js | 31 +- .../built-ins/Object/S15.2.2.1_A4_T3.js | 26 +- .../built-ins/Object/S15.2.2.1_A5_T1.js | 28 +- .../built-ins/Object/S15.2.2.1_A5_T2.js | 16 +- .../built-ins/Object/S15.2.2.1_A5_T3.js | 28 +- .../built-ins/Object/S15.2.2.1_A5_T4.js | 23 +- .../built-ins/Object/S15.2.2.1_A6_T1.js | 17 +- .../built-ins/Object/S15.2.2.1_A6_T2.js | 11 +- .../built-ins/Object/S15.2.2.1_A6_T3.js | 18 +- .../test262/built-ins/Object/S15.2.3_A1.js | 8 +- .../test262/built-ins/Object/S15.2.3_A2.js | 9 +- .../test262/built-ins/Object/S15.2.3_A3.js | 14 +- .../test262/built-ins/Object/S15.2_A1.js | 4 +- .../tests/test262/built-ins/Object/S9.9_A3.js | 41 +- .../tests/test262/built-ins/Object/S9.9_A4.js | 252 +- .../tests/test262/built-ins/Object/S9.9_A5.js | 94 +- .../tests/test262/built-ins/Object/S9.9_A6.js | 26 +- .../Object/assign/Source-Null-Undefined.js | 2 +- .../assign/Source-Number-Boolen-Symbol.js | 2 +- .../built-ins/Object/assign/Source-String.js | 6 +- .../Object/assign/assign-descriptor.js | 3 +- .../defineProperties/15.2.3.7-6-a-36.js | 3 +- .../Object/defineProperty/S15.2.3.6_A1.js | 4 +- .../Object/defineProperty/S15.2.3.6_A2.js | 8 +- .../getOwnPropertyNames/15.2.3.4-4-2.js | 18 +- .../getOwnPropertyNames/15.2.3.4-4-44.js | 5 +- .../getOwnPropertyNames/15.2.3.4-4-49.js | 5 +- .../getOwnPropertyNames/15.2.3.4-4-b-2.js | 5 +- .../getOwnPropertyNames/S15.2.3.4_A1_T1.js | 4 +- .../Object/getOwnPropertyNames/shell.js | 31 - .../built-ins/Object/hasOwn/descriptor.js | 3 +- .../Object/prototype/S15.2.3.1_A1.js | 12 +- .../Object/prototype/S15.2.3.1_A2.js | 20 +- .../Object/prototype/S15.2.3.1_A3.js | 14 +- .../Object/prototype/S15.2.4_A1_T1.js | 10 +- .../Object/prototype/S15.2.4_A1_T2.js | 15 +- .../built-ins/Object/prototype/S15.2.4_A2.js | 5 +- .../built-ins/Object/prototype/S15.2.4_A3.js | 2 +- .../built-ins/Object/prototype/S15.2.4_A4.js | 2 +- .../prototype/constructor/S15.2.4.1_A1_T1.js | 10 +- .../prototype/constructor/S15.2.4.1_A1_T2.js | 30 +- .../prototype/hasOwnProperty/S15.2.4.5_A12.js | 2 +- .../prototype/hasOwnProperty/S15.2.4.5_A13.js | 2 +- .../hasOwnProperty/S15.2.4.5_A1_T1.js | 19 +- .../hasOwnProperty/S15.2.4.5_A1_T2.js | 36 +- .../hasOwnProperty/S15.2.4.5_A1_T3.js | 34 +- .../prototype/hasOwnProperty/S15.2.4.5_A6.js | 11 +- .../prototype/hasOwnProperty/S15.2.4.5_A7.js | 16 - .../propertyIsEnumerable/S15.2.4.7_A10.js | 20 +- .../propertyIsEnumerable/S15.2.4.7_A11.js | 18 +- .../propertyIsEnumerable/S15.2.4.7_A12.js | 2 +- .../propertyIsEnumerable/S15.2.4.7_A13.js | 2 +- .../propertyIsEnumerable/S15.2.4.7_A1_T1.js | 38 +- .../propertyIsEnumerable/S15.2.4.7_A2_T1.js | 19 +- .../propertyIsEnumerable/S15.2.4.7_A2_T2.js | 35 +- .../propertyIsEnumerable/S15.2.4.7_A6.js | 11 +- .../propertyIsEnumerable/S15.2.4.7_A7.js | 18 - .../propertyIsEnumerable/S15.2.4.7_A8.js | 24 +- .../propertyIsEnumerable/S15.2.4.7_A9.js | 18 +- .../prototype/toLocaleString/S15.2.4.3_A1.js | 28 +- .../prototype/toLocaleString/S15.2.4.3_A10.js | 20 +- .../prototype/toLocaleString/S15.2.4.3_A11.js | 18 +- .../prototype/toLocaleString/S15.2.4.3_A12.js | 2 +- .../prototype/toLocaleString/S15.2.4.3_A13.js | 2 +- .../prototype/toLocaleString/S15.2.4.3_A6.js | 11 +- .../prototype/toLocaleString/S15.2.4.3_A7.js | 16 - .../prototype/toLocaleString/S15.2.4.3_A8.js | 24 +- .../prototype/toLocaleString/S15.2.4.3_A9.js | 25 +- .../Object/prototype/toString/not-ctor.js | 17 - .../Object/prototype/valueOf/S15.2.4.4_A10.js | 20 +- .../Object/prototype/valueOf/S15.2.4.4_A11.js | 18 +- .../Object/prototype/valueOf/S15.2.4.4_A12.js | 2 +- .../Object/prototype/valueOf/S15.2.4.4_A13.js | 2 +- .../Object/prototype/valueOf/S15.2.4.4_A14.js | 2 +- .../Object/prototype/valueOf/S15.2.4.4_A15.js | 7 +- .../prototype/valueOf/S15.2.4.4_A1_T1.js | 21 +- .../prototype/valueOf/S15.2.4.4_A1_T2.js | 21 +- .../prototype/valueOf/S15.2.4.4_A1_T3.js | 21 +- .../prototype/valueOf/S15.2.4.4_A1_T4.js | 21 +- .../prototype/valueOf/S15.2.4.4_A1_T5.js | 21 +- .../prototype/valueOf/S15.2.4.4_A1_T6.js | 21 +- .../prototype/valueOf/S15.2.4.4_A1_T7.js | 21 +- .../Object/prototype/valueOf/S15.2.4.4_A6.js | 11 +- .../Object/prototype/valueOf/S15.2.4.4_A7.js | 16 - .../Object/prototype/valueOf/S15.2.4.4_A8.js | 24 +- .../Object/prototype/valueOf/S15.2.4.4_A9.js | 25 +- .../Object/seal/seal-aggregateerror.js | 1 + .../Promise/Symbol.species/symbol-species.js | 3 +- .../Promise/all/S25.4.4.1_A1.1_T1.js | 5 +- .../Promise/all/S25.4.4.1_A2.1_T1.js | 4 +- .../Promise/all/S25.4.4.1_A2.3_T1.js | 4 +- .../Promise/all/S25.4.4.1_A2.3_T2.js | 4 +- .../Promise/all/S25.4.4.1_A2.3_T3.js | 4 +- .../Promise/all/S25.4.4.1_A3.1_T1.js | 4 +- .../Promise/all/S25.4.4.1_A3.1_T2.js | 4 +- .../Promise/all/S25.4.4.1_A3.1_T3.js | 4 +- .../Promise/all/S25.4.4.1_A5.1_T1.js | 2 +- .../Promise/all/S25.4.4.1_A7.1_T1.js | 16 +- .../Promise/all/S25.4.4.1_A8.2_T1.js | 4 +- .../Promise/all/S25.4.4.1_A8.2_T2.js | 4 +- .../Promise/prototype/S25.4.4.2_A1.1_T1.js | 9 +- .../Promise/prototype/S25.4.5_A3.1_T1.js | 9 +- .../prototype/catch/S25.4.5.1_A1.1_T1.js | 8 +- .../prototype/catch/S25.4.5.1_A2.1_T1.js | 7 +- .../prototype/catch/S25.4.5.1_A3.1_T1.js | 10 +- .../prototype/catch/S25.4.5.1_A3.1_T2.js | 10 +- .../prototype/then/S25.4.5.3_A1.1_T1.js | 8 +- .../prototype/then/S25.4.5.3_A1.1_T2.js | 9 +- .../prototype/then/S25.4.5.3_A4.1_T1.js | 12 +- .../prototype/then/S25.4.5.3_A4.1_T2.js | 10 +- .../prototype/then/S25.4.5.3_A4.2_T1.js | 12 +- .../prototype/then/S25.4.5.3_A4.2_T2.js | 10 +- .../prototype/then/S25.4.5.3_A5.3_T1.js | 6 +- .../Promise/race/S25.4.4.3_A1.1_T1.js | 5 +- .../Promise/race/S25.4.4.3_A2.1_T1.js | 4 +- .../Promise/race/S25.4.4.3_A2.2_T1.js | 4 +- .../Promise/race/S25.4.4.3_A2.2_T2.js | 4 +- .../Promise/race/S25.4.4.3_A2.2_T3.js | 4 +- .../Promise/race/S25.4.4.3_A4.1_T1.js | 2 +- .../Promise/race/S25.4.4.3_A4.1_T2.js | 4 +- .../Promise/race/S25.4.4.3_A6.2_T1.js | 6 +- .../Promise/race/S25.4.4.3_A7.1_T1.js | 12 +- .../Promise/race/S25.4.4.3_A7.1_T2.js | 12 +- .../Promise/race/S25.4.4.3_A7.1_T3.js | 12 +- .../Promise/race/S25.4.4.3_A7.2_T1.js | 12 +- .../Promise/race/S25.4.4.3_A7.3_T1.js | 6 +- .../Promise/race/S25.4.4.3_A7.3_T2.js | 6 +- .../race/resolved-sequence-with-rejections.js | 2 +- .../Promise/race/resolved-sequence.js | 2 +- .../Promise/reject/S25.4.4.4_A1.1_T1.js | 9 +- .../Promise/reject/S25.4.4.4_A2.1_T1.js | 10 +- .../Promise/resolve/S25.4.4.5_A1.1_T1.js | 9 +- .../Promise/resolve/S25.4.4.5_A2.1_T1.js | 4 +- .../Promise/resolve/S25.4.4.5_A2.2_T1.js | 14 +- .../Promise/resolve/S25.4.4.5_A2.3_T1.js | 14 +- .../Promise/resolve/S25.4.4.5_A4.1_T1.js | 4 +- .../return-not-object-throws-number.js | 2 - .../return-not-object-throws-string.js | 2 - .../return-not-object-throws-symbol.js | 2 - .../enumerate/removed-does-not-trigger.js | 4 +- .../Proxy/revocable/tco-fn-realm-strict.js | 27 + .../test262/built-ins/Realm/constructor.js | 21 - .../tests/test262/built-ins/Realm/instance.js | 33 - ...other-realm-is-wrapped-into-a-typeerror.js | 24 - .../prototype/evaluate/not-constructor.js | 37 - .../evaluate/returns-symbol-values.js | 26 - .../evaluate/validates-realm-object.js | 24 - .../prototype/importValue/import-value.js | 24 - .../prototype/importValue/not-constructor.js | 34 - .../importValue/specifier-tostring.js | 33 - .../importValue/validates-realm-object.js | 24 - .../return-from-accessor-descriptor.js | 7 +- .../return-from-data-descriptor.js | 7 +- .../symbol-property.js | 7 +- .../return-array-with-own-keys-only.js | 5 +- .../Reflect/ownKeys/return-empty-array.js | 4 +- .../ownKeys/return-non-enumerable-keys.js | 12 +- .../RegExp/CharacterClassEscapes/shell.js | 62 +- .../built-ins/RegExp/S15.10.1_A1_T1.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T10.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T11.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T12.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T13.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T14.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T15.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T16.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T2.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T3.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T4.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T5.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T6.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T7.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T8.js | 13 +- .../built-ins/RegExp/S15.10.1_A1_T9.js | 13 +- .../built-ins/RegExp/S15.10.2.10_A1.1_T1.js | 2 - .../built-ins/RegExp/S15.10.2.10_A1.2_T1.js | 2 - .../built-ins/RegExp/S15.10.2.10_A1.3_T1.js | 2 - .../built-ins/RegExp/S15.10.2.10_A1.4_T1.js | 2 - .../built-ins/RegExp/S15.10.2.10_A1.5_T1.js | 2 - .../built-ins/RegExp/S15.10.2.10_A2.1_T1.js | 7 +- .../built-ins/RegExp/S15.10.2.10_A2.1_T2.js | 7 +- .../built-ins/RegExp/S15.10.2.10_A3.1_T1.js | 4 - .../built-ins/RegExp/S15.10.2.10_A3.1_T2.js | 10 +- .../built-ins/RegExp/S15.10.2.10_A4.1_T1.js | 6 - .../built-ins/RegExp/S15.10.2.10_A4.1_T2.js | 10 +- .../built-ins/RegExp/S15.10.2.10_A4.1_T3.js | 10 +- .../built-ins/RegExp/S15.10.2.10_A5.1_T1.js | 1 - .../built-ins/RegExp/S15.10.2.11_A1_T1.js | 2 - .../built-ins/RegExp/S15.10.2.11_A1_T4.js | 2 - .../built-ins/RegExp/S15.10.2.11_A1_T5.js | 2 - .../built-ins/RegExp/S15.10.2.11_A1_T6.js | 3 - .../built-ins/RegExp/S15.10.2.11_A1_T7.js | 3 - .../built-ins/RegExp/S15.10.2.11_A1_T8.js | 4 +- .../built-ins/RegExp/S15.10.2.11_A1_T9.js | 4 +- .../built-ins/RegExp/S15.10.2.12_A3_T5.js | 15 +- .../built-ins/RegExp/S15.10.2.12_A4_T5.js | 15 +- .../built-ins/RegExp/S15.10.2.13_A1_T1.js | 8 +- .../built-ins/RegExp/S15.10.2.13_A1_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T12.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T13.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T14.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T15.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T17.js | 5 +- .../built-ins/RegExp/S15.10.2.13_A1_T2.js | 8 +- .../built-ins/RegExp/S15.10.2.13_A1_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T7.js | 5 +- .../built-ins/RegExp/S15.10.2.13_A1_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A1_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A2_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A2_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A2_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A2_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A2_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A2_T6.js | 5 +- .../built-ins/RegExp/S15.10.2.13_A2_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A2_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A3_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A3_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A3_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.13_A3_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.15_A1_T1.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T10.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T11.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T12.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T13.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T14.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T15.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T16.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T17.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T18.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T19.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T2.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T20.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T21.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T22.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T23.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T24.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T25.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T26.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T27.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T28.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T29.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T3.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T30.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T31.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T32.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T33.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T34.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T35.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T36.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T37.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T38.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T39.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T4.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T40.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T41.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T5.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T6.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T7.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T8.js | 11 +- .../built-ins/RegExp/S15.10.2.15_A1_T9.js | 11 +- .../built-ins/RegExp/S15.10.2.3_A1_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T12.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T13.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T14.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T15.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T16.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T17.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T5.js | 5 +- .../built-ins/RegExp/S15.10.2.3_A1_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T7.js | 5 +- .../built-ins/RegExp/S15.10.2.3_A1_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.3_A1_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.5_A1_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.5_A1_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.5_A1_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.5_A1_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.5_A1_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A1_T1.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A1_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A1_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A1_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A1_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A2_T1.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A2_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A2_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A2_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A2_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A2_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A2_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A2_T7.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A2_T8.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A2_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T12.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T13.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A3_T14.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T15.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A3_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T3.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A3_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T5.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A3_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A3_T9.js | 5 +- .../built-ins/RegExp/S15.10.2.6_A4_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A4_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A4_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A4_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A4_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A4_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A4_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A4_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A5_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A5_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A6_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A6_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A6_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.6_A6_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T12.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T2.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A1_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A1_T9.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A2_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A2_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A2_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A2_T4.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A3_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T10.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A3_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T12.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T13.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T14.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T3.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A3_T4.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A3_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A3_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T12.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T13.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T14.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T15.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T16.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T17.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T18.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T19.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T20.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T21.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A4_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A4_T8.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A4_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T12.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T3.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A5_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A5_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A6_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A6_T2.js | 5 +- .../built-ins/RegExp/S15.10.2.7_A6_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A6_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A6_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.7_A6_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A1_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A1_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A1_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A1_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A1_T5.js | 5 +- .../built-ins/RegExp/S15.10.2.8_A2_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A2_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A2_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A2_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A2_T3.js | 5 +- .../built-ins/RegExp/S15.10.2.8_A2_T4.js | 5 +- .../built-ins/RegExp/S15.10.2.8_A2_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A2_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A2_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A2_T8.js | 5 +- .../built-ins/RegExp/S15.10.2.8_A2_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T10.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T11.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T12.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T13.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T14.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T15.js | 42 +- .../built-ins/RegExp/S15.10.2.8_A3_T16.js | 42 +- .../built-ins/RegExp/S15.10.2.8_A3_T17.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T18.js | 5 +- .../built-ins/RegExp/S15.10.2.8_A3_T19.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T20.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T21.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T22.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T23.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T24.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T25.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T26.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T27.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T28.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T29.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T3.js | 5 +- .../built-ins/RegExp/S15.10.2.8_A3_T30.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T31.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T32.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T33.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A3_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T4.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T5.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T6.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T7.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T8.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A4_T9.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A5_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.8_A5_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.9_A1_T1.js | 36 +- .../built-ins/RegExp/S15.10.2.9_A1_T2.js | 36 +- .../built-ins/RegExp/S15.10.2.9_A1_T3.js | 36 +- .../built-ins/RegExp/S15.10.2.9_A1_T5.js | 36 +- .../built-ins/RegExp/S15.10.2_A1_T1.js | 9 +- .../built-ins/RegExp/S15.10.3.1_A1_T1.js | 5 +- .../built-ins/RegExp/S15.10.3.1_A1_T2.js | 5 +- .../built-ins/RegExp/S15.10.3.1_A1_T3.js | 5 +- .../built-ins/RegExp/S15.10.3.1_A1_T4.js | 5 +- .../built-ins/RegExp/S15.10.3.1_A1_T5.js | 5 +- .../built-ins/RegExp/S15.10.3.1_A2_T1.js | 13 +- .../built-ins/RegExp/S15.10.3.1_A2_T2.js | 13 +- .../built-ins/RegExp/S15.10.3.1_A3_T1.js | 14 +- .../built-ins/RegExp/S15.10.3.1_A3_T2.js | 14 +- .../built-ins/RegExp/S15.10.4.1_A1_T1.js | 38 +- .../built-ins/RegExp/S15.10.4.1_A1_T2.js | 36 +- .../built-ins/RegExp/S15.10.4.1_A1_T3.js | 36 +- .../built-ins/RegExp/S15.10.4.1_A1_T4.js | 36 +- .../built-ins/RegExp/S15.10.4.1_A1_T5.js | 36 +- .../built-ins/RegExp/S15.10.4.1_A2_T1.js | 1 - .../built-ins/RegExp/S15.10.4.1_A2_T2.js | 11 +- .../built-ins/RegExp/S15.10.4.1_A3_T1.js | 17 +- .../built-ins/RegExp/S15.10.4.1_A3_T2.js | 17 +- .../built-ins/RegExp/S15.10.4.1_A3_T3.js | 17 +- .../built-ins/RegExp/S15.10.4.1_A3_T4.js | 17 +- .../built-ins/RegExp/S15.10.4.1_A3_T5.js | 17 +- .../built-ins/RegExp/S15.10.4.1_A4_T1.js | 23 +- .../built-ins/RegExp/S15.10.4.1_A4_T2.js | 17 +- .../built-ins/RegExp/S15.10.4.1_A4_T3.js | 17 +- .../built-ins/RegExp/S15.10.4.1_A4_T4.js | 23 +- .../built-ins/RegExp/S15.10.4.1_A4_T5.js | 17 +- .../built-ins/RegExp/S15.10.4.1_A5_T1.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A5_T3.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A5_T4.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A5_T6.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A5_T7.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A5_T8.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A5_T9.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A6_T1.js | 5 +- .../built-ins/RegExp/S15.10.4.1_A7_T1.js | 5 +- .../built-ins/RegExp/S15.10.4.1_A7_T2.js | 9 +- .../built-ins/RegExp/S15.10.4.1_A8_T1.js | 29 +- .../built-ins/RegExp/S15.10.4.1_A8_T10.js | 29 +- .../built-ins/RegExp/S15.10.4.1_A8_T11.js | 29 +- .../built-ins/RegExp/S15.10.4.1_A8_T12.js | 9 +- .../built-ins/RegExp/S15.10.4.1_A8_T13.js | 9 +- .../built-ins/RegExp/S15.10.4.1_A8_T2.js | 29 +- .../built-ins/RegExp/S15.10.4.1_A8_T3.js | 29 +- .../built-ins/RegExp/S15.10.4.1_A8_T4.js | 29 +- .../built-ins/RegExp/S15.10.4.1_A8_T5.js | 29 +- .../built-ins/RegExp/S15.10.4.1_A8_T6.js | 9 +- .../built-ins/RegExp/S15.10.4.1_A8_T7.js | 9 +- .../built-ins/RegExp/S15.10.4.1_A8_T8.js | 9 +- .../built-ins/RegExp/S15.10.4.1_A8_T9.js | 29 +- .../built-ins/RegExp/S15.10.4.1_A9_T1.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A9_T2.js | 13 +- .../built-ins/RegExp/S15.10.4.1_A9_T3.js | 13 +- .../test262/built-ins/RegExp/S15.10.5_A1.js | 6 +- .../built-ins/RegExp/S15.10.5_A2_T1.js | 10 +- .../built-ins/RegExp/S15.10.5_A2_T2.js | 5 +- .../built-ins/RegExp/S15.10.7_A1_T1.js | 13 +- .../built-ins/RegExp/S15.10.7_A1_T2.js | 11 +- .../built-ins/RegExp/S15.10.7_A2_T1.js | 11 +- .../built-ins/RegExp/S15.10.7_A2_T2.js | 11 +- .../built-ins/RegExp/S15.10.7_A3_T1.js | 20 +- .../built-ins/RegExp/S15.10.7_A3_T2.js | 20 +- .../indices-array-non-unicode-match.js | 2 +- .../indices-array-unicode-match.js | 2 +- .../indices-array-unicode-property-names.js | 2 +- .../RegExp/named-groups/groups-properties.js | 5 +- .../RegExp/named-groups/lookbehind.js | 29 +- .../RegExp/named-groups/non-unicode-match.js | 51 +- .../named-groups/non-unicode-references.js | 12 +- .../RegExp/named-groups/unicode-match.js | 56 +- .../RegExp/named-groups/unicode-references.js | 12 +- .../property-escapes/generated/ASCII.js | 4 +- .../generated/ASCII_Hex_Digit.js | 4 +- .../property-escapes/generated/Alphabetic.js | 156 +- .../RegExp/property-escapes/generated/Any.js | 4 +- .../property-escapes/generated/Assigned.js | 256 +- .../generated/Bidi_Control.js | 4 +- .../generated/Bidi_Mirrored.js | 8 +- .../generated/Case_Ignorable.js | 82 +- .../property-escapes/generated/Cased.js | 56 +- .../generated/Changes_When_Casefolded.js | 32 +- .../generated/Changes_When_Casemapped.js | 40 +- .../generated/Changes_When_Lowercased.js | 32 +- .../generated/Changes_When_NFKC_Casefolded.js | 42 +- .../generated/Changes_When_Titlecased.js | 32 +- .../generated/Changes_When_Uppercased.js | 32 +- .../RegExp/property-escapes/generated/Dash.js | 8 +- .../generated/Default_Ignorable_Code_Point.js | 8 +- .../property-escapes/generated/Deprecated.js | 4 +- .../property-escapes/generated/Diacritic.js | 62 +- .../property-escapes/generated/Emoji.js | 46 +- .../generated/Emoji_Component.js | 4 +- .../generated/Emoji_Modifier.js | 4 +- .../generated/Emoji_Modifier_Base.js | 12 +- .../generated/Emoji_Presentation.js | 46 +- .../generated/Extended_Pictographic.js | 4 +- .../property-escapes/generated/Extender.js | 8 +- .../General_Category_-_Cased_Letter.js | 48 +- .../General_Category_-_Close_Punctuation.js | 14 +- ...eneral_Category_-_Connector_Punctuation.js | 4 +- .../generated/General_Category_-_Control.js | 4 +- .../General_Category_-_Currency_Symbol.js | 8 +- .../General_Category_-_Dash_Punctuation.js | 8 +- .../General_Category_-_Decimal_Number.js | 8 +- .../General_Category_-_Enclosing_Mark.js | 4 +- .../General_Category_-_Final_Punctuation.js | 4 +- .../generated/General_Category_-_Format.js | 8 +- .../General_Category_-_Initial_Punctuation.js | 4 +- .../generated/General_Category_-_Letter.js | 150 +- .../General_Category_-_Letter_Number.js | 4 +- .../General_Category_-_Line_Separator.js | 4 +- .../General_Category_-_Lowercase_Letter.js | 42 +- .../generated/General_Category_-_Mark.js | 56 +- .../General_Category_-_Math_Symbol.js | 4 +- .../General_Category_-_Modifier_Letter.js | 30 +- .../General_Category_-_Modifier_Symbol.js | 12 +- .../General_Category_-_Nonspacing_Mark.js | 56 +- .../generated/General_Category_-_Number.js | 8 +- .../General_Category_-_Open_Punctuation.js | 14 +- .../generated/General_Category_-_Other.js | 256 +- .../General_Category_-_Other_Letter.js | 96 +- .../General_Category_-_Other_Number.js | 4 +- .../General_Category_-_Other_Punctuation.js | 28 +- .../General_Category_-_Other_Symbol.js | 62 +- .../General_Category_-_Paragraph_Separator.js | 4 +- .../General_Category_-_Private_Use.js | 4 +- .../General_Category_-_Punctuation.js | 28 +- .../generated/General_Category_-_Separator.js | 4 +- .../General_Category_-_Space_Separator.js | 4 +- .../General_Category_-_Spacing_Mark.js | 10 +- .../generated/General_Category_-_Surrogate.js | 4 +- .../generated/General_Category_-_Symbol.js | 72 +- .../General_Category_-_Titlecase_Letter.js | 4 +- .../General_Category_-_Unassigned.js | 256 +- .../General_Category_-_Uppercase_Letter.js | 30 +- .../generated/Grapheme_Base.js | 242 +- .../generated/Grapheme_Extend.js | 56 +- .../property-escapes/generated/Hex_Digit.js | 4 +- .../generated/IDS_Binary_Operator.js | 4 +- .../generated/IDS_Trinary_Operator.js | 4 +- .../property-escapes/generated/ID_Continue.js | 176 +- .../property-escapes/generated/ID_Start.js | 150 +- .../property-escapes/generated/Ideographic.js | 16 +- .../generated/Join_Control.js | 4 +- .../generated/Logical_Order_Exception.js | 4 +- .../property-escapes/generated/Lowercase.js | 50 +- .../RegExp/property-escapes/generated/Math.js | 4 +- .../generated/Noncharacter_Code_Point.js | 4 +- .../generated/Pattern_Syntax.js | 4 +- .../generated/Pattern_White_Space.js | 4 +- .../generated/Quotation_Mark.js | 4 +- .../property-escapes/generated/Radical.js | 4 +- .../generated/Regional_Indicator.js | 4 +- .../generated/Script_-_Adlam.js | 4 +- .../generated/Script_-_Ahom.js | 8 +- .../Script_-_Anatolian_Hieroglyphs.js | 4 +- .../generated/Script_-_Arabic.js | 36 +- .../generated/Script_-_Armenian.js | 4 +- .../generated/Script_-_Avestan.js | 4 +- .../generated/Script_-_Balinese.js | 12 +- .../generated/Script_-_Bamum.js | 4 +- .../generated/Script_-_Bassa_Vah.js | 4 +- .../generated/Script_-_Batak.js | 4 +- .../generated/Script_-_Bengali.js | 4 +- .../generated/Script_-_Bhaiksuki.js | 4 +- .../generated/Script_-_Bopomofo.js | 4 +- .../generated/Script_-_Brahmi.js | 8 +- .../generated/Script_-_Braille.js | 4 +- .../generated/Script_-_Buginese.js | 4 +- .../generated/Script_-_Buhid.js | 4 +- .../generated/Script_-_Canadian_Aboriginal.js | 10 +- .../generated/Script_-_Carian.js | 4 +- .../generated/Script_-_Caucasian_Albanian.js | 4 +- .../generated/Script_-_Chakma.js | 4 +- .../generated/Script_-_Cham.js | 4 +- .../generated/Script_-_Cherokee.js | 4 +- .../generated/Script_-_Chorasmian.js | 4 +- .../generated/Script_-_Common.js | 62 +- .../generated/Script_-_Coptic.js | 4 +- .../generated/Script_-_Cuneiform.js | 4 +- .../generated/Script_-_Cypriot.js | 4 +- .../generated/Script_-_Cypro_Minoan.js | 73 + .../generated/Script_-_Cyrillic.js | 4 +- .../generated/Script_-_Deseret.js | 4 +- .../generated/Script_-_Devanagari.js | 4 +- .../generated/Script_-_Dives_Akuru.js | 4 +- .../generated/Script_-_Dogra.js | 4 +- .../generated/Script_-_Duployan.js | 4 +- .../Script_-_Egyptian_Hieroglyphs.js | 4 +- .../generated/Script_-_Elbasan.js | 4 +- .../generated/Script_-_Elymaic.js | 4 +- .../generated/Script_-_Ethiopic.js | 18 +- .../generated/Script_-_Georgian.js | 4 +- .../generated/Script_-_Glagolitic.js | 10 +- .../generated/Script_-_Gothic.js | 4 +- .../generated/Script_-_Grantha.js | 4 +- .../generated/Script_-_Greek.js | 4 +- .../generated/Script_-_Gujarati.js | 4 +- .../generated/Script_-_Gunjala_Gondi.js | 4 +- .../generated/Script_-_Gurmukhi.js | 4 +- .../generated/Script_-_Han.js | 20 +- .../generated/Script_-_Hangul.js | 4 +- .../generated/Script_-_Hanifi_Rohingya.js | 4 +- .../generated/Script_-_Hanunoo.js | 4 +- .../generated/Script_-_Hatran.js | 4 +- .../generated/Script_-_Hebrew.js | 4 +- .../generated/Script_-_Hiragana.js | 8 +- .../generated/Script_-_Imperial_Aramaic.js | 4 +- .../generated/Script_-_Inherited.js | 20 +- .../Script_-_Inscriptional_Pahlavi.js | 4 +- .../Script_-_Inscriptional_Parthian.js | 4 +- .../generated/Script_-_Javanese.js | 4 +- .../generated/Script_-_Kaithi.js | 8 +- .../generated/Script_-_Kannada.js | 11 +- .../generated/Script_-_Katakana.js | 18 +- .../generated/Script_-_Kayah_Li.js | 4 +- .../generated/Script_-_Kharoshthi.js | 4 +- .../generated/Script_-_Khitan_Small_Script.js | 4 +- .../generated/Script_-_Khmer.js | 4 +- .../generated/Script_-_Khojki.js | 4 +- .../generated/Script_-_Khudawadi.js | 4 +- .../generated/Script_-_Lao.js | 4 +- .../generated/Script_-_Latin.js | 34 +- .../generated/Script_-_Lepcha.js | 4 +- .../generated/Script_-_Limbu.js | 4 +- .../generated/Script_-_Linear_A.js | 4 +- .../generated/Script_-_Linear_B.js | 4 +- .../generated/Script_-_Lisu.js | 4 +- .../generated/Script_-_Lycian.js | 4 +- .../generated/Script_-_Lydian.js | 4 +- .../generated/Script_-_Mahajani.js | 4 +- .../generated/Script_-_Makasar.js | 4 +- .../generated/Script_-_Malayalam.js | 4 +- .../generated/Script_-_Mandaic.js | 4 +- .../generated/Script_-_Manichaean.js | 4 +- .../generated/Script_-_Marchen.js | 4 +- .../generated/Script_-_Masaram_Gondi.js | 4 +- .../generated/Script_-_Medefaidrin.js | 4 +- .../generated/Script_-_Meetei_Mayek.js | 4 +- .../generated/Script_-_Mende_Kikakui.js | 4 +- .../generated/Script_-_Meroitic_Cursive.js | 4 +- .../Script_-_Meroitic_Hieroglyphs.js | 4 +- .../generated/Script_-_Miao.js | 4 +- .../generated/Script_-_Modi.js | 4 +- .../generated/Script_-_Mongolian.js | 10 +- .../generated/Script_-_Mro.js | 4 +- .../generated/Script_-_Multani.js | 4 +- .../generated/Script_-_Myanmar.js | 4 +- .../generated/Script_-_Nabataean.js | 4 +- .../generated/Script_-_Nandinagari.js | 4 +- .../generated/Script_-_New_Tai_Lue.js | 4 +- .../generated/Script_-_Newa.js | 4 +- .../generated/Script_-_Nko.js | 4 +- .../generated/Script_-_Nushu.js | 4 +- .../Script_-_Nyiakeng_Puachue_Hmong.js | 4 +- .../generated/Script_-_Ogham.js | 4 +- .../generated/Script_-_Ol_Chiki.js | 4 +- .../generated/Script_-_Old_Hungarian.js | 4 +- .../generated/Script_-_Old_Italic.js | 4 +- .../generated/Script_-_Old_North_Arabian.js | 4 +- .../generated/Script_-_Old_Permic.js | 4 +- .../generated/Script_-_Old_Persian.js | 4 +- .../generated/Script_-_Old_Sogdian.js | 4 +- .../generated/Script_-_Old_South_Arabian.js | 4 +- .../generated/Script_-_Old_Turkic.js | 4 +- .../generated/Script_-_Old_Uyghur.js | 73 + .../generated/Script_-_Oriya.js | 4 +- .../generated/Script_-_Osage.js | 4 +- .../generated/Script_-_Osmanya.js | 4 +- .../generated/Script_-_Pahawh_Hmong.js | 4 +- .../generated/Script_-_Palmyrene.js | 4 +- .../generated/Script_-_Pau_Cin_Hau.js | 4 +- .../generated/Script_-_Phags_Pa.js | 4 +- .../generated/Script_-_Phoenician.js | 4 +- .../generated/Script_-_Psalter_Pahlavi.js | 4 +- .../generated/Script_-_Rejang.js | 4 +- .../generated/Script_-_Runic.js | 4 +- .../generated/Script_-_Samaritan.js | 4 +- .../generated/Script_-_Saurashtra.js | 4 +- .../generated/Script_-_Sharada.js | 4 +- .../generated/Script_-_Shavian.js | 4 +- .../generated/Script_-_Siddham.js | 4 +- .../generated/Script_-_SignWriting.js | 4 +- .../generated/Script_-_Sinhala.js | 4 +- .../generated/Script_-_Sogdian.js | 4 +- .../generated/Script_-_Sora_Sompeng.js | 4 +- .../generated/Script_-_Soyombo.js | 4 +- .../generated/Script_-_Sundanese.js | 4 +- .../generated/Script_-_Syloti_Nagri.js | 4 +- .../generated/Script_-_Syriac.js | 4 +- .../generated/Script_-_Tagalog.js | 18 +- .../generated/Script_-_Tagbanwa.js | 4 +- .../generated/Script_-_Tai_Le.js | 4 +- .../generated/Script_-_Tai_Tham.js | 4 +- .../generated/Script_-_Tai_Viet.js | 4 +- .../generated/Script_-_Takri.js | 8 +- .../generated/Script_-_Tamil.js | 4 +- .../generated/Script_-_Tangsa.js | 76 + .../generated/Script_-_Tangut.js | 4 +- .../generated/Script_-_Telugu.js | 15 +- .../generated/Script_-_Thaana.js | 4 +- .../generated/Script_-_Thai.js | 4 +- .../generated/Script_-_Tibetan.js | 4 +- .../generated/Script_-_Tifinagh.js | 4 +- .../generated/Script_-_Tirhuta.js | 4 +- .../generated/Script_-_Toto.js | 73 + .../generated/Script_-_Ugaritic.js | 4 +- .../generated/Script_-_Vai.js | 4 +- .../generated/Script_-_Vithkuqi.js | 88 + .../generated/Script_-_Wancho.js | 4 +- .../generated/Script_-_Warang_Citi.js | 4 +- .../generated/Script_-_Yezidi.js | 4 +- .../property-escapes/generated/Script_-_Yi.js | 4 +- .../generated/Script_-_Zanabazar_Square.js | 4 +- .../generated/Script_Extensions_-_Adlam.js | 8 +- .../generated/Script_Extensions_-_Ahom.js | 8 +- ...ript_Extensions_-_Anatolian_Hieroglyphs.js | 4 +- .../generated/Script_Extensions_-_Arabic.js | 36 +- .../generated/Script_Extensions_-_Armenian.js | 4 +- .../generated/Script_Extensions_-_Avestan.js | 4 +- .../generated/Script_Extensions_-_Balinese.js | 12 +- .../generated/Script_Extensions_-_Bamum.js | 4 +- .../Script_Extensions_-_Bassa_Vah.js | 4 +- .../generated/Script_Extensions_-_Batak.js | 4 +- .../generated/Script_Extensions_-_Bengali.js | 4 +- .../Script_Extensions_-_Bhaiksuki.js | 4 +- .../generated/Script_Extensions_-_Bopomofo.js | 4 +- .../generated/Script_Extensions_-_Brahmi.js | 8 +- .../generated/Script_Extensions_-_Braille.js | 4 +- .../generated/Script_Extensions_-_Buginese.js | 4 +- .../generated/Script_Extensions_-_Buhid.js | 4 +- ...Script_Extensions_-_Canadian_Aboriginal.js | 10 +- .../generated/Script_Extensions_-_Carian.js | 4 +- .../Script_Extensions_-_Caucasian_Albanian.js | 4 +- .../generated/Script_Extensions_-_Chakma.js | 4 +- .../generated/Script_Extensions_-_Cham.js | 4 +- .../generated/Script_Extensions_-_Cherokee.js | 4 +- .../Script_Extensions_-_Chorasmian.js | 4 +- .../generated/Script_Extensions_-_Common.js | 64 +- .../generated/Script_Extensions_-_Coptic.js | 4 +- .../Script_Extensions_-_Cuneiform.js | 4 +- .../generated/Script_Extensions_-_Cypriot.js | 4 +- .../Script_Extensions_-_Cypro_Minoan.js | 75 + .../generated/Script_Extensions_-_Cyrillic.js | 4 +- .../generated/Script_Extensions_-_Deseret.js | 4 +- .../Script_Extensions_-_Devanagari.js | 4 +- .../Script_Extensions_-_Dives_Akuru.js | 4 +- .../generated/Script_Extensions_-_Dogra.js | 4 +- .../generated/Script_Extensions_-_Duployan.js | 4 +- ...cript_Extensions_-_Egyptian_Hieroglyphs.js | 4 +- .../generated/Script_Extensions_-_Elbasan.js | 4 +- .../generated/Script_Extensions_-_Elymaic.js | 4 +- .../generated/Script_Extensions_-_Ethiopic.js | 18 +- .../generated/Script_Extensions_-_Georgian.js | 4 +- .../Script_Extensions_-_Glagolitic.js | 10 +- .../generated/Script_Extensions_-_Gothic.js | 4 +- .../generated/Script_Extensions_-_Grantha.js | 4 +- .../generated/Script_Extensions_-_Greek.js | 4 +- .../generated/Script_Extensions_-_Gujarati.js | 4 +- .../Script_Extensions_-_Gunjala_Gondi.js | 4 +- .../generated/Script_Extensions_-_Gurmukhi.js | 4 +- .../generated/Script_Extensions_-_Han.js | 20 +- .../generated/Script_Extensions_-_Hangul.js | 4 +- .../Script_Extensions_-_Hanifi_Rohingya.js | 4 +- .../generated/Script_Extensions_-_Hanunoo.js | 4 +- .../generated/Script_Extensions_-_Hatran.js | 4 +- .../generated/Script_Extensions_-_Hebrew.js | 4 +- .../generated/Script_Extensions_-_Hiragana.js | 8 +- .../Script_Extensions_-_Imperial_Aramaic.js | 4 +- .../Script_Extensions_-_Inherited.js | 14 +- ...ript_Extensions_-_Inscriptional_Pahlavi.js | 4 +- ...ipt_Extensions_-_Inscriptional_Parthian.js | 4 +- .../generated/Script_Extensions_-_Javanese.js | 4 +- .../generated/Script_Extensions_-_Kaithi.js | 8 +- .../generated/Script_Extensions_-_Kannada.js | 8 +- .../generated/Script_Extensions_-_Katakana.js | 18 +- .../generated/Script_Extensions_-_Kayah_Li.js | 4 +- .../Script_Extensions_-_Kharoshthi.js | 4 +- ...Script_Extensions_-_Khitan_Small_Script.js | 4 +- .../generated/Script_Extensions_-_Khmer.js | 4 +- .../generated/Script_Extensions_-_Khojki.js | 4 +- .../Script_Extensions_-_Khudawadi.js | 4 +- .../generated/Script_Extensions_-_Lao.js | 4 +- .../generated/Script_Extensions_-_Latin.js | 32 +- .../generated/Script_Extensions_-_Lepcha.js | 4 +- .../generated/Script_Extensions_-_Limbu.js | 4 +- .../generated/Script_Extensions_-_Linear_A.js | 4 +- .../generated/Script_Extensions_-_Linear_B.js | 4 +- .../generated/Script_Extensions_-_Lisu.js | 4 +- .../generated/Script_Extensions_-_Lycian.js | 4 +- .../generated/Script_Extensions_-_Lydian.js | 4 +- .../generated/Script_Extensions_-_Mahajani.js | 4 +- .../generated/Script_Extensions_-_Makasar.js | 4 +- .../Script_Extensions_-_Malayalam.js | 4 +- .../generated/Script_Extensions_-_Mandaic.js | 4 +- .../Script_Extensions_-_Manichaean.js | 4 +- .../generated/Script_Extensions_-_Marchen.js | 4 +- .../Script_Extensions_-_Masaram_Gondi.js | 4 +- .../Script_Extensions_-_Medefaidrin.js | 4 +- .../Script_Extensions_-_Meetei_Mayek.js | 4 +- .../Script_Extensions_-_Mende_Kikakui.js | 4 +- .../Script_Extensions_-_Meroitic_Cursive.js | 4 +- ...cript_Extensions_-_Meroitic_Hieroglyphs.js | 4 +- .../generated/Script_Extensions_-_Miao.js | 4 +- .../generated/Script_Extensions_-_Modi.js | 4 +- .../Script_Extensions_-_Mongolian.js | 11 +- .../generated/Script_Extensions_-_Mro.js | 4 +- .../generated/Script_Extensions_-_Multani.js | 4 +- .../generated/Script_Extensions_-_Myanmar.js | 4 +- .../Script_Extensions_-_Nabataean.js | 4 +- .../Script_Extensions_-_Nandinagari.js | 4 +- .../Script_Extensions_-_New_Tai_Lue.js | 4 +- .../generated/Script_Extensions_-_Newa.js | 4 +- .../generated/Script_Extensions_-_Nko.js | 21 +- .../generated/Script_Extensions_-_Nushu.js | 4 +- ...ipt_Extensions_-_Nyiakeng_Puachue_Hmong.js | 4 +- .../generated/Script_Extensions_-_Ogham.js | 4 +- .../generated/Script_Extensions_-_Ol_Chiki.js | 4 +- .../Script_Extensions_-_Old_Hungarian.js | 4 +- .../Script_Extensions_-_Old_Italic.js | 4 +- .../Script_Extensions_-_Old_North_Arabian.js | 4 +- .../Script_Extensions_-_Old_Permic.js | 4 +- .../Script_Extensions_-_Old_Persian.js | 4 +- .../Script_Extensions_-_Old_Sogdian.js | 4 +- .../Script_Extensions_-_Old_South_Arabian.js | 4 +- .../Script_Extensions_-_Old_Turkic.js | 4 +- .../Script_Extensions_-_Old_Uyghur.js | 78 + .../generated/Script_Extensions_-_Oriya.js | 4 +- .../generated/Script_Extensions_-_Osage.js | 4 +- .../generated/Script_Extensions_-_Osmanya.js | 4 +- .../Script_Extensions_-_Pahawh_Hmong.js | 4 +- .../Script_Extensions_-_Palmyrene.js | 4 +- .../Script_Extensions_-_Pau_Cin_Hau.js | 4 +- .../generated/Script_Extensions_-_Phags_Pa.js | 4 +- .../Script_Extensions_-_Phoenician.js | 4 +- .../Script_Extensions_-_Psalter_Pahlavi.js | 4 +- .../generated/Script_Extensions_-_Rejang.js | 4 +- .../generated/Script_Extensions_-_Runic.js | 4 +- .../Script_Extensions_-_Samaritan.js | 4 +- .../Script_Extensions_-_Saurashtra.js | 4 +- .../generated/Script_Extensions_-_Sharada.js | 4 +- .../generated/Script_Extensions_-_Shavian.js | 4 +- .../generated/Script_Extensions_-_Siddham.js | 4 +- .../Script_Extensions_-_SignWriting.js | 4 +- .../generated/Script_Extensions_-_Sinhala.js | 4 +- .../generated/Script_Extensions_-_Sogdian.js | 4 +- .../Script_Extensions_-_Sora_Sompeng.js | 4 +- .../generated/Script_Extensions_-_Soyombo.js | 4 +- .../Script_Extensions_-_Sundanese.js | 4 +- .../Script_Extensions_-_Syloti_Nagri.js | 4 +- .../generated/Script_Extensions_-_Syriac.js | 12 +- .../generated/Script_Extensions_-_Tagalog.js | 18 +- .../generated/Script_Extensions_-_Tagbanwa.js | 4 +- .../generated/Script_Extensions_-_Tai_Le.js | 4 +- .../generated/Script_Extensions_-_Tai_Tham.js | 4 +- .../generated/Script_Extensions_-_Tai_Viet.js | 4 +- .../generated/Script_Extensions_-_Takri.js | 8 +- .../generated/Script_Extensions_-_Tamil.js | 4 +- .../generated/Script_Extensions_-_Tangsa.js | 76 + .../generated/Script_Extensions_-_Tangut.js | 4 +- .../generated/Script_Extensions_-_Telugu.js | 12 +- .../generated/Script_Extensions_-_Thaana.js | 4 +- .../generated/Script_Extensions_-_Thai.js | 4 +- .../generated/Script_Extensions_-_Tibetan.js | 4 +- .../generated/Script_Extensions_-_Tifinagh.js | 4 +- .../generated/Script_Extensions_-_Tirhuta.js | 4 +- .../generated/Script_Extensions_-_Toto.js | 73 + .../generated/Script_Extensions_-_Ugaritic.js | 4 +- .../generated/Script_Extensions_-_Vai.js | 4 +- .../generated/Script_Extensions_-_Vithkuqi.js | 88 + .../generated/Script_Extensions_-_Wancho.js | 4 +- .../Script_Extensions_-_Warang_Citi.js | 4 +- .../generated/Script_Extensions_-_Yezidi.js | 4 +- .../generated/Script_Extensions_-_Yi.js | 4 +- .../Script_Extensions_-_Zanabazar_Square.js | 4 +- .../generated/Sentence_Terminal.js | 20 +- .../property-escapes/generated/Soft_Dotted.js | 10 +- .../generated/Terminal_Punctuation.js | 20 +- .../generated/Unified_Ideograph.js | 16 +- .../property-escapes/generated/Uppercase.js | 30 +- .../generated/Variation_Selector.js | 14 +- .../property-escapes/generated/White_Space.js | 4 +- .../generated/XID_Continue.js | 176 +- .../property-escapes/generated/XID_Start.js | 150 +- .../property-escapes/generated/shell.js | 62 +- .../Basic_Emoji-negative-CharacterClass.js | 21 + .../strings/Basic_Emoji-negative-P.js | 21 + .../strings/Basic_Emoji-negative-u.js | 21 + .../generated/strings/Basic_Emoji.js | 1402 +++++ ...Keycap_Sequence-negative-CharacterClass.js | 21 + .../Emoji_Keycap_Sequence-negative-P.js | 21 + .../Emoji_Keycap_Sequence-negative-u.js | 21 + .../strings/Emoji_Keycap_Sequence.js | 53 + .../Emoji_Test-negative-CharacterClass.js | 21 + .../strings/Emoji_Test-negative-P.js | 21 + .../strings/Emoji_Test-negative-u.js | 21 + .../generated/strings/Emoji_Test.js | 4743 +++++++++++++++++ .../RGI_Emoji-negative-CharacterClass.js | 21 + .../generated/strings/RGI_Emoji-negative-P.js | 21 + .../generated/strings/RGI_Emoji-negative-u.js | 21 + .../generated/strings/RGI_Emoji.js | 3674 +++++++++++++ ...i_Flag_Sequence-negative-CharacterClass.js | 21 + .../RGI_Emoji_Flag_Sequence-negative-P.js | 21 + .../RGI_Emoji_Flag_Sequence-negative-u.js | 21 + .../strings/RGI_Emoji_Flag_Sequence.js | 294 + ...difier_Sequence-negative-CharacterClass.js | 21 + .../RGI_Emoji_Modifier_Sequence-negative-P.js | 21 + .../RGI_Emoji_Modifier_Sequence-negative-u.js | 21 + .../strings/RGI_Emoji_Modifier_Sequence.js | 681 +++ ...ji_Tag_Sequence-negative-CharacterClass.js | 21 + .../RGI_Emoji_Tag_Sequence-negative-P.js | 21 + .../RGI_Emoji_Tag_Sequence-negative-u.js | 21 + .../strings/RGI_Emoji_Tag_Sequence.js | 38 + ...ji_ZWJ_Sequence-negative-CharacterClass.js | 21 + .../RGI_Emoji_ZWJ_Sequence-negative-P.js | 21 + .../RGI_Emoji_ZWJ_Sequence-negative-u.js | 21 + .../strings/RGI_Emoji_ZWJ_Sequence.js | 1390 +++++ .../generated/strings}/browser.js | 0 .../generated/strings}/shell.js | 0 .../RegExp/prototype/S15.10.5.1_A1.js | 6 +- .../RegExp/prototype/S15.10.5.1_A2.js | 26 +- .../RegExp/prototype/S15.10.5.1_A3.js | 21 +- .../RegExp/prototype/S15.10.5.1_A4.js | 13 +- .../RegExp/prototype/S15.10.6.1_A1_T1.js | 10 +- .../RegExp/prototype/S15.10.6.1_A1_T2.js | 18 +- .../RegExp/prototype/S15.10.6_A1_T1.js | 10 +- .../RegExp/prototype/S15.10.6_A1_T2.js | 5 +- .../RegExp/prototype/Symbol.matchAll/shell.js | 62 +- .../RegExp/prototype/exec/S15.10.6.2_A10.js | 21 +- .../RegExp/prototype/exec/S15.10.6.2_A11.js | 15 +- .../RegExp/prototype/exec/S15.10.6.2_A12.js | 8 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T1.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T10.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T11.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T12.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T13.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T14.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T15.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T16.js | 4 +- .../prototype/exec/S15.10.6.2_A1_T17.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T18.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T19.js | 45 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T2.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T20.js | 45 +- .../prototype/exec/S15.10.6.2_A1_T21.js | 45 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T3.js | 45 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T4.js | 45 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T5.js | 45 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T6.js | 45 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T7.js | 9 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T8.js | 7 +- .../RegExp/prototype/exec/S15.10.6.2_A1_T9.js | 7 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T1.js | 13 +- .../prototype/exec/S15.10.6.2_A2_T10.js | 13 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T2.js | 13 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T3.js | 13 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T4.js | 15 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T5.js | 11 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T6.js | 13 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T7.js | 13 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T8.js | 13 +- .../RegExp/prototype/exec/S15.10.6.2_A2_T9.js | 13 +- .../RegExp/prototype/exec/S15.10.6.2_A3_T1.js | 18 +- .../RegExp/prototype/exec/S15.10.6.2_A3_T2.js | 13 +- .../RegExp/prototype/exec/S15.10.6.2_A3_T3.js | 17 +- .../RegExp/prototype/exec/S15.10.6.2_A3_T4.js | 17 +- .../RegExp/prototype/exec/S15.10.6.2_A3_T5.js | 22 +- .../RegExp/prototype/exec/S15.10.6.2_A3_T6.js | 22 +- .../RegExp/prototype/exec/S15.10.6.2_A3_T7.js | 22 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T1.js | 72 +- .../prototype/exec/S15.10.6.2_A4_T10.js | 72 +- .../prototype/exec/S15.10.6.2_A4_T11.js | 43 +- .../prototype/exec/S15.10.6.2_A4_T12.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T2.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T3.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T4.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T5.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T6.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T7.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T8.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A4_T9.js | 72 +- .../RegExp/prototype/exec/S15.10.6.2_A5_T1.js | 47 +- .../RegExp/prototype/exec/S15.10.6.2_A5_T2.js | 11 +- .../RegExp/prototype/exec/S15.10.6.2_A5_T3.js | 22 +- .../RegExp/prototype/exec/S15.10.6.2_A6.js | 10 +- .../RegExp/prototype/exec/S15.10.6.2_A7.js | 10 +- .../RegExp/prototype/exec/S15.10.6.2_A8.js | 30 +- .../RegExp/prototype/exec/S15.10.6.2_A9.js | 28 +- .../prototype/exec/failure-lastindex-set.js | 73 + .../RegExp/prototype/global/S15.10.7.2_A10.js | 10 +- .../RegExp/prototype/global/S15.10.7.2_A8.js | 25 +- .../RegExp/prototype/global/S15.10.7.2_A9.js | 17 +- .../prototype/ignoreCase/S15.10.7.3_A10.js | 14 +- .../prototype/ignoreCase/S15.10.7.3_A8.js | 25 +- .../prototype/ignoreCase/S15.10.7.3_A9.js | 17 +- .../prototype/multiline/S15.10.7.4_A10.js | 10 +- .../prototype/multiline/S15.10.7.4_A8.js | 25 +- .../prototype/multiline/S15.10.7.4_A9.js | 17 +- .../RegExp/prototype/test/S15.10.6.3_A10.js | 21 +- .../RegExp/prototype/test/S15.10.6.3_A11.js | 15 +- .../RegExp/prototype/test/S15.10.6.3_A1_T1.js | 9 +- .../prototype/test/S15.10.6.3_A1_T10.js | 9 +- .../prototype/test/S15.10.6.3_A1_T11.js | 9 +- .../prototype/test/S15.10.6.3_A1_T12.js | 9 +- .../prototype/test/S15.10.6.3_A1_T13.js | 9 +- .../prototype/test/S15.10.6.3_A1_T14.js | 9 +- .../prototype/test/S15.10.6.3_A1_T15.js | 9 +- .../prototype/test/S15.10.6.3_A1_T16.js | 5 +- .../prototype/test/S15.10.6.3_A1_T17.js | 5 +- .../prototype/test/S15.10.6.3_A1_T18.js | 9 +- .../prototype/test/S15.10.6.3_A1_T19.js | 9 +- .../RegExp/prototype/test/S15.10.6.3_A1_T2.js | 9 +- .../prototype/test/S15.10.6.3_A1_T20.js | 5 +- .../prototype/test/S15.10.6.3_A1_T21.js | 9 +- .../prototype/test/S15.10.6.3_A1_T22.js | 22 +- .../RegExp/prototype/test/S15.10.6.3_A1_T3.js | 9 +- .../RegExp/prototype/test/S15.10.6.3_A1_T4.js | 9 +- .../RegExp/prototype/test/S15.10.6.3_A1_T5.js | 9 +- .../RegExp/prototype/test/S15.10.6.3_A1_T6.js | 9 +- .../RegExp/prototype/test/S15.10.6.3_A1_T7.js | 9 +- .../RegExp/prototype/test/S15.10.6.3_A1_T8.js | 7 +- .../RegExp/prototype/test/S15.10.6.3_A1_T9.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A2_T1.js | 11 +- .../prototype/test/S15.10.6.3_A2_T10.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A2_T2.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A2_T3.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A2_T4.js | 13 +- .../RegExp/prototype/test/S15.10.6.3_A2_T5.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A2_T6.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A2_T7.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A2_T8.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A2_T9.js | 11 +- .../RegExp/prototype/test/S15.10.6.3_A6.js | 10 +- .../RegExp/prototype/test/S15.10.6.3_A7.js | 10 +- .../RegExp/prototype/test/S15.10.6.3_A8.js | 30 +- .../RegExp/prototype/test/S15.10.6.3_A9.js | 28 +- .../prototype/toString/S15.10.6.4_A10.js | 21 +- .../prototype/toString/S15.10.6.4_A11.js | 19 +- .../prototype/toString/S15.10.6.4_A6.js | 10 +- .../prototype/toString/S15.10.6.4_A7.js | 14 +- .../prototype/toString/S15.10.6.4_A8.js | 30 +- .../prototype/toString/S15.10.6.4_A9.js | 28 +- .../next/shell.js | 62 +- .../built-ins/Set/Symbol.species/length.js | 2 +- .../Set/Symbol.species/symbol-species-name.js | 2 +- .../Set/Symbol.species/symbol-species.js | 6 +- .../built-ins/Set/bigint-number-same-value.js | 46 + .../test262/built-ins/Set/constructor.js | 2 +- js/src/tests/test262/built-ins/Set/length.js | 2 +- js/src/tests/test262/built-ins/Set/name.js | 2 +- .../properties-of-the-set-prototype-object.js | 2 +- .../test262/built-ins/Set/prototype-of-set.js | 2 +- .../Set/prototype/Symbol.iterator.js | 2 +- .../Set/prototype/Symbol.toStringTag.js | 2 +- .../Symbol.toStringTag/property-descriptor.js | 2 +- .../built-ins/Set/prototype/add/add.js | 2 +- ...es-not-have-setdata-internal-slot-array.js | 2 +- ...does-not-have-setdata-internal-slot-map.js | 2 +- ...s-not-have-setdata-internal-slot-object.js | 2 +- ...ave-setdata-internal-slot-set-prototype.js | 2 +- ...-not-have-setdata-internal-slot-weakset.js | 2 +- .../built-ins/Set/prototype/add/length.js | 2 +- .../built-ins/Set/prototype/add/name.js | 2 +- .../add/preserves-insertion-order.js | 2 +- .../returns-this-when-ignoring-duplicate.js | 2 +- .../Set/prototype/add/returns-this.js | 2 +- .../add/this-not-object-throw-boolean.js | 2 +- .../add/this-not-object-throw-null.js | 2 +- .../add/this-not-object-throw-number.js | 2 +- .../add/this-not-object-throw-string.js | 2 +- .../add/this-not-object-throw-symbol.js | 2 +- .../add/this-not-object-throw-undefined.js | 2 +- ...ot-add-duplicate-entry-initial-iterable.js | 2 +- ...not-add-duplicate-entry-normalizes-zero.js | 2 +- .../add/will-not-add-duplicate-entry.js | 2 +- .../built-ins/Set/prototype/clear/clear.js | 2 +- .../clears-all-contents-from-iterable.js | 2 +- .../prototype/clear/clears-all-contents.js | 2 +- .../prototype/clear/clears-an-empty-set.js | 2 +- ...es-not-have-setdata-internal-slot-array.js | 2 +- ...does-not-have-setdata-internal-slot-map.js | 2 +- ...s-not-have-setdata-internal-slot-object.js | 2 +- ...ave-setdata-internal-slot-set.prototype.js | 2 +- ...-not-have-setdata-internal-slot-weakset.js | 2 +- .../built-ins/Set/prototype/clear/length.js | 2 +- .../built-ins/Set/prototype/clear/name.js | 2 +- .../Set/prototype/clear/returns-undefined.js | 2 +- .../clear/this-not-object-throw-boolean.js | 2 +- .../clear/this-not-object-throw-null.js | 2 +- .../clear/this-not-object-throw-number.js | 2 +- .../clear/this-not-object-throw-string.js | 2 +- .../clear/this-not-object-throw-symbol.js | 2 +- .../clear/this-not-object-throw-undefined.js | 2 +- .../set-prototype-constructor-intrinsic.js | 2 +- .../constructor/set-prototype-constructor.js | 2 +- .../delete/delete-entry-initial-iterable.js | 2 +- .../delete/delete-entry-normalizes-zero.js | 2 +- .../Set/prototype/delete/delete-entry.js | 2 +- .../built-ins/Set/prototype/delete/delete.js | 2 +- ...es-not-have-setdata-internal-slot-array.js | 2 +- ...does-not-have-setdata-internal-slot-map.js | 2 +- ...s-not-have-setdata-internal-slot-object.js | 2 +- ...ave-setdata-internal-slot-set-prototype.js | 2 +- ...-not-have-setdata-internal-slot-weakset.js | 2 +- .../built-ins/Set/prototype/delete/length.js | 2 +- .../built-ins/Set/prototype/delete/name.js | 2 +- .../returns-false-when-delete-is-noop.js | 2 +- ...turns-true-when-delete-operation-occurs.js | 2 +- .../delete/this-not-object-throw-boolean.js | 2 +- .../delete/this-not-object-throw-null.js | 2 +- .../delete/this-not-object-throw-number.js | 2 +- .../delete/this-not-object-throw-string.js | 2 +- .../delete/this-not-object-throw-symbol.js | 2 +- .../delete/this-not-object-throw-undefined.js | 2 +- ...es-not-have-setdata-internal-slot-array.js | 2 +- ...does-not-have-setdata-internal-slot-map.js | 2 +- ...s-not-have-setdata-internal-slot-object.js | 2 +- ...ave-setdata-internal-slot-set-prototype.js | 2 +- ...-not-have-setdata-internal-slot-weakset.js | 2 +- .../Set/prototype/entries/entries.js | 2 +- .../built-ins/Set/prototype/entries/length.js | 2 +- .../built-ins/Set/prototype/entries/name.js | 2 +- .../entries/returns-iterator-empty.js | 2 +- .../Set/prototype/entries/returns-iterator.js | 2 +- .../entries/this-not-object-throw-boolean.js | 2 +- .../entries/this-not-object-throw-null.js | 2 +- .../entries/this-not-object-throw-number.js | 2 +- .../entries/this-not-object-throw-string.js | 2 +- .../entries/this-not-object-throw-symbol.js | 2 +- .../this-not-object-throw-undefined.js | 2 +- .../forEach/callback-not-callable-boolean.js | 2 +- .../forEach/callback-not-callable-null.js | 2 +- .../forEach/callback-not-callable-number.js | 2 +- .../forEach/callback-not-callable-string.js | 2 +- .../forEach/callback-not-callable-symbol.js | 2 +- .../callback-not-callable-undefined.js | 2 +- ...es-not-have-setdata-internal-slot-array.js | 2 +- ...does-not-have-setdata-internal-slot-map.js | 2 +- ...s-not-have-setdata-internal-slot-object.js | 2 +- ...ave-setdata-internal-slot-set-prototype.js | 2 +- ...-not-have-setdata-internal-slot-weakset.js | 2 +- .../Set/prototype/forEach/forEach.js | 2 +- .../forEach/iterates-in-insertion-order.js | 2 +- .../iterates-in-iterable-entry-order.js | 2 +- ...rates-values-added-after-foreach-begins.js | 2 +- .../iterates-values-deleted-then-readded.js | 2 +- .../forEach/iterates-values-not-deleted.js | 2 +- ...tes-values-revisits-after-delete-re-add.js | 2 +- .../built-ins/Set/prototype/forEach/length.js | 2 +- .../built-ins/Set/prototype/forEach/name.js | 2 +- .../prototype/forEach/returns-undefined.js | 2 +- ...icit-cannot-override-lexical-this-arrow.js | 2 +- .../prototype/forEach/this-arg-explicit.js | 2 +- .../Set/prototype/forEach/this-non-strict.js | 2 +- .../forEach/this-not-object-throw-boolean.js | 2 +- .../forEach/this-not-object-throw-null.js | 2 +- .../forEach/this-not-object-throw-number.js | 2 +- .../forEach/this-not-object-throw-string.js | 2 +- .../forEach/this-not-object-throw-symbol.js | 2 +- .../this-not-object-throw-undefined.js | 2 +- .../prototype/forEach/this-strict-strict.js | 2 +- .../forEach/throws-when-callback-throws.js | 2 +- ...es-not-have-setdata-internal-slot-array.js | 2 +- ...does-not-have-setdata-internal-slot-map.js | 2 +- ...s-not-have-setdata-internal-slot-object.js | 2 +- ...ave-setdata-internal-slot-set-prototype.js | 2 +- ...-not-have-setdata-internal-slot-weakset.js | 2 +- .../built-ins/Set/prototype/has/has.js | 2 +- .../built-ins/Set/prototype/has/length.js | 2 +- .../built-ins/Set/prototype/has/name.js | 2 +- ...ned-added-deleted-not-present-undefined.js | 2 +- ...ns-false-when-value-not-present-boolean.js | 2 +- ...eturns-false-when-value-not-present-nan.js | 2 +- ...turns-false-when-value-not-present-null.js | 2 +- ...rns-false-when-value-not-present-number.js | 2 +- ...rns-false-when-value-not-present-string.js | 2 +- ...rns-false-when-value-not-present-symbol.js | 2 +- ...-false-when-value-not-present-undefined.js | 2 +- ...returns-true-when-value-present-boolean.js | 2 +- .../returns-true-when-value-present-nan.js | 2 +- .../returns-true-when-value-present-null.js | 2 +- .../returns-true-when-value-present-number.js | 2 +- .../returns-true-when-value-present-string.js | 2 +- .../returns-true-when-value-present-symbol.js | 2 +- ...turns-true-when-value-present-undefined.js | 2 +- .../has/this-not-object-throw-boolean.js | 2 +- .../has/this-not-object-throw-null.js | 2 +- .../has/this-not-object-throw-number.js | 2 +- .../has/this-not-object-throw-string.js | 2 +- .../has/this-not-object-throw-symbol.js | 2 +- .../has/this-not-object-throw-undefined.js | 2 +- .../built-ins/Set/prototype/keys/keys.js | 8 +- .../built-ins/Set/prototype/set-prototype.js | 17 - .../built-ins/Set/prototype/size/length.js | 2 +- .../built-ins/Set/prototype/size/name.js | 2 +- ...-present-values-before-after-add-delete.js | 2 +- ...ns-count-of-present-values-by-insertion.js | 2 +- ...rns-count-of-present-values-by-iterable.js | 2 +- .../built-ins/Set/prototype/size/size.js | 2 +- ...es-not-have-setdata-internal-slot-array.js | 2 +- ...does-not-have-setdata-internal-slot-map.js | 2 +- ...s-not-have-setdata-internal-slot-object.js | 2 +- ...ave-setdata-internal-slot-set-prototype.js | 2 +- ...-not-have-setdata-internal-slot-weakset.js | 2 +- .../built-ins/Set/prototype/values/length.js | 2 +- .../built-ins/Set/prototype/values/name.js | 2 +- .../values/returns-iterator-empty.js | 6 +- .../Set/prototype/values/returns-iterator.js | 8 +- .../values/this-not-object-throw-boolean.js | 2 +- .../values/this-not-object-throw-null.js | 2 +- .../values/this-not-object-throw-number.js | 2 +- .../values/this-not-object-throw-string.js | 2 +- .../values/this-not-object-throw-symbol.js | 2 +- .../values/this-not-object-throw-undefined.js | 2 +- .../values/values-iteration-mutable.js | 12 +- .../built-ins/Set/prototype/values/values.js | 2 +- ...does-not-throw-when-add-is-not-callable.js | 2 +- .../Set/set-get-add-method-failure.js | 2 +- .../built-ins/Set/set-iterable-calls-add.js | 2 +- .../set-iterable-empty-does-not-call-add.js | 2 +- ...terable-throws-when-add-is-not-callable.js | 2 +- .../test262/built-ins/Set/set-iterable.js | 2 +- .../set-iterator-close-after-add-failure.js | 2 +- .../Set/set-iterator-next-failure.js | 2 +- .../Set/set-iterator-value-failure.js | 2 +- .../test262/built-ins/Set/set-newtarget.js | 2 +- .../test262/built-ins/Set/set-no-iterable.js | 2 +- .../built-ins/Set/set-undefined-newtarget.js | 2 +- js/src/tests/test262/built-ins/Set/set.js | 2 +- .../test262/built-ins/Set/symbol-as-entry.js | 19 - .../test262/built-ins/Set/valid-values.js | 390 ++ .../next/iteration-mutable.js | 2 +- .../SetIteratorPrototype/next/iteration.js | 2 +- .../WrappedFunction}/browser.js | 0 .../length-throws-typeerror.js | 39 + .../ShadowRealm/WrappedFunction/length.js | 125 + .../WrappedFunction/name-throws-typeerror.js | 39 + .../ShadowRealm/WrappedFunction/name.js | 86 + .../WrappedFunction}/shell.js | 0 .../throws-typeerror-on-revoked-proxy.js | 43 + .../evaluate => ShadowRealm}/browser.js | 0 .../built-ins/ShadowRealm/constructor.js | 21 + .../{Realm => ShadowRealm}/descriptor.js | 10 +- .../{Realm => ShadowRealm}/extensibility.js | 10 +- .../instance-extensibility.js | 16 +- .../test262/built-ins/ShadowRealm/instance.js | 36 + .../{Realm => ShadowRealm}/length.js | 12 +- .../built-ins/{Realm => ShadowRealm}/name.js | 20 +- .../built-ins/{Realm => ShadowRealm}/proto.js | 10 +- .../prototype/Symbol.toStringTag.js | 12 +- .../prototype}/browser.js | 0 .../prototype/evaluate}/browser.js | 0 .../prototype/evaluate/descriptor.js | 10 +- ...other-realm-is-wrapped-into-a-typeerror.js | 29 + .../globalthis-available-properties.js | 108 + .../globalthis-config-only-properties.js | 101 + .../evaluate/globalthis-orginary-object.js | 69 + .../prototype/evaluate/length.js | 12 +- .../prototype/evaluate/name.js | 20 +- .../prototype/evaluate/nested-realms.js | 40 + .../evaluate/no-conditional-strict-mode.js | 37 + .../prototype/evaluate/not-constructor.js | 37 + .../prototype/evaluate/proto.js | 10 +- .../evaluate/returns-primitive-values.js | 14 +- .../evaluate/returns-proxy-callable-object.js | 28 + .../evaluate/returns-symbol-values.js | 54 + .../prototype/evaluate}/shell.js | 0 .../evaluate/throws-error-from-ctor-realm.js | 35 + .../throws-syntaxerror-on-bad-syntax.js | 33 + ...if-evaluation-resolves-to-non-primitive.js | 14 +- .../throws-typeerror-wrap-throwing.js | 73 + .../throws-when-argument-is-not-a-string.js | 14 +- .../evaluate/validates-realm-object.js | 24 + ...e-wrapped-into-the-inner-realm-extended.js | 14 +- ...uments-are-wrapped-into-the-inner-realm.js | 14 +- ...on-from-return-values-share-no-identity.js | 14 +- ...nction-multiple-different-realms-nested.js | 58 + ...pped-function-multiple-different-realms.js | 51 + ...wrapped-function-observing-their-scopes.js | 16 +- ...rapped-function-proto-from-caller-realm.js | 56 + ...pped-function-proxied-observes-boundary.js | 44 + ...tion-throws-typeerror-from-caller-realm.js | 42 + ...on-throws-typeerror-on-exceptional-exit.js | 42 + ...ws-typeerror-on-non-primitive-arguments.js | 36 + ...rows-typeerror-on-non-primitive-returns.js | 31 + ...pped-functions-accepts-callable-objects.js | 15 +- ...-functions-can-resolve-callable-returns.js | 14 +- ...nctions-new-wrapping-on-each-evaluation.js | 18 +- ...-functions-share-no-properties-extended.js | 14 +- .../wrapped-functions-share-no-properties.js | 14 +- .../prototype/importValue}/browser.js | 0 .../prototype/importValue/descriptor.js | 10 +- .../importValue/exportName-tostring.js | 14 +- .../prototype/importValue/import-value.js | 24 + .../importValue/import-value_FIXTURE.js | 0 .../import-value_syntax_error_FIXTURE.js | 5 + .../import-value_throws_FIXTURE.js | 5 + .../prototype/importValue/length.js | 10 +- .../prototype/importValue/name.js | 22 +- .../prototype/importValue/not-constructor.js | 34 + .../prototype/importValue/proto.js | 10 +- .../prototype/importValue}/shell.js | 0 .../importValue/specifier-tostring.js | 76 + .../throws-if-import-value-does-not-exist.js | 29 +- .../throws-typeerror-import-syntax-error.js | 35 + .../throws-typeerror-import-throws.js | 35 + .../importValue/validates-realm-object.js | 24 + .../{Realm => ShadowRealm}/prototype/proto.js | 8 +- .../prototype}/shell.js | 0 .../built-ins/{Realm => ShadowRealm}/shell.js | 0 .../options-maxbytelength-diminuitive.js | 2 +- .../options-maxbytelength-excessive.js | 2 +- .../options-maxbytelength-negative.js | 2 +- .../options-maxbytelength-object.js | 2 +- .../options-maxbytelength-poisoned.js | 2 +- .../options-maxbytelength-undefined.js | 2 +- .../SharedArrayBuffer/options-non-object.js | 2 +- .../prototype-from-newtarget.js | 2 +- .../prototype/grow/descriptor.js | 2 +- .../prototype/grow/extensible.js | 2 +- .../prototype/grow/grow-larger-size.js | 2 +- .../prototype/grow/grow-same-size.js | 2 +- .../prototype/grow/grow-smaller-size.js | 2 +- .../prototype/grow/length.js | 2 +- .../SharedArrayBuffer/prototype/grow/name.js | 2 +- .../prototype/grow/new-length-excessive.js | 2 +- .../prototype/grow/new-length-negative.js | 2 +- .../prototype/grow/new-length-non-number.js | 2 +- .../prototype/grow/nonconstructor.js | 2 +- .../grow/this-is-not-arraybuffer-object.js | 2 +- .../prototype/grow/this-is-not-object.js | 2 +- ...his-is-not-resizable-arraybuffer-object.js | 2 +- .../grow/this-is-sharedarraybuffer.js | 2 +- .../prototype/growable/invoked-as-accessor.js | 2 +- .../prototype/growable/invoked-as-func.js | 2 +- .../prototype/growable/length.js | 2 +- .../prototype/growable/name.js | 2 +- .../prototype/growable/prop-desc.js | 2 +- .../prototype/growable/return-growable.js | 2 +- .../this-has-no-arraybufferdata-internal.js | 2 +- .../prototype/growable/this-is-arraybuffer.js | 2 +- .../prototype/growable/this-is-not-object.js | 2 +- .../maxByteLength/invoked-as-accessor.js | 2 +- .../maxByteLength/invoked-as-func.js | 2 +- .../prototype/maxByteLength/length.js | 2 +- .../prototype/maxByteLength/name.js | 2 +- .../prototype/maxByteLength/prop-desc.js | 2 +- .../return-maxbytelength-growable.js | 2 +- .../return-maxbytelength-non-growable.js | 2 +- .../this-has-no-arraybufferdata-internal.js | 2 +- .../maxByteLength/this-is-arraybuffer.js | 2 +- .../maxByteLength/this-is-not-object.js | 2 +- .../SharedArrayBuffer/prototype/prop-desc.js | 18 + .../prototype/slice/this-is-arraybuffer.js | 2 +- .../prototype/localeCompare/15.5.4.9_CE.js | 42 +- .../String/prototype/matchAll/shell.js | 62 +- .../test262/built-ins/Symbol/species/basic.js | 3 +- .../built-ins/Temporal/Calendar/builtin.js | 30 + .../Temporal/Calendar/constructor.js | 15 + .../era => Calendar/from}/browser.js | 0 .../Temporal/Calendar/from/builtin.js | 33 + .../Calendar/from/calendar-object-invalid.js | 14 + .../from/calendar-object-operations.js | 42 + .../Temporal/Calendar/from/calendar-object.js | 24 + .../Calendar/from/calendar-string-builtin.js | 22 + .../from/calendar-string-not-builtin.js | 22 + .../Calendar/from/calendar-temporal-object.js | 23 + .../Temporal/Calendar/from/length.js | 28 + .../built-ins/Temporal/Calendar/from/name.js | 26 + .../Calendar/from/not-a-constructor.js | 23 + .../Temporal/Calendar/from/prop-desc.js | 24 + .../built-ins/Temporal/Calendar/from/shell.js | 1517 ++++++ .../Calendar/from/subclassing-ignored.js | 22 + .../built-ins/Temporal/Calendar/length.js | 28 + .../Temporal/Calendar/missing-arguments.js | 14 + .../built-ins/Temporal/Calendar/name.js | 26 + .../built-ins/Temporal/Calendar/prop-desc.js | 24 + .../dateAdd/argument-plaindatetime.js | 26 + .../dateAdd/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 20 + ...ne-getoffsetnanosecondsfor-not-callable.js | 24 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 20 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 29 + .../dateAdd/balance-smaller-units.js | 25 + .../Calendar/prototype/dateAdd/basic.js | 53 + .../Calendar/prototype/dateAdd/branding.js | 20 +- .../Calendar/prototype/dateAdd/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../dateAdd/calendar-fields-iterable.js | 36 + .../dateAdd/calendar-temporal-object.js | 30 + .../date-infinity-throws-rangeerror.js | 29 + ...gument-string-negative-fractional-units.js | 21 + .../Calendar/prototype/dateAdd/length.js | 28 + .../Calendar/prototype/dateAdd/name.js | 26 + .../prototype/dateAdd/not-a-constructor.js | 24 + .../dateAdd/overflow-invalid-string.js | 30 + .../prototype/dateAdd/overflow-undefined.js | 28 + .../prototype/dateAdd/overflow-wrong-type.js | 27 + .../Calendar/prototype/dateAdd/prop-desc.js | 24 + .../Calendar/prototype/dateAdd/shell.js | 1329 ++++- ...row-range-error-from-ToTemporalOverflow.js | 18 - ...row-type-error-from-RequireInternalSlot.js | 20 - .../Calendar/prototype/dateAdd/year-zero.js | 20 + .../prototype/dateFromFields/branding.js | 20 +- .../prototype/dateFromFields/builtin.js | 36 + .../dateFromFields/fields-not-object.js | 23 + .../infinity-throws-rangeerror.js | 28 + .../prototype/dateFromFields/length.js | 28 + .../Calendar/prototype/dateFromFields/name.js | 26 + .../dateFromFields/not-a-constructor.js | 24 + .../dateFromFields/overflow-invalid-string.js | 31 + .../dateFromFields/overflow-undefined.js | 28 + .../dateFromFields/overflow-wrong-type.js | 27 + .../prototype/dateFromFields/prop-desc.js | 24 + .../prototype/dateFromFields/shell.js | 1329 ++++- ...hrow-range-error-from-ISODateFromFields.js | 17 - .../throw-type-error-fields-is-not-object.js | 22 - ...row-type-error-from-RequireInternalSlot.js | 18 - .../dateFromFields/throws-range-error.js | 3 +- .../argument-infinity-throws-rangeerror.js | 34 + .../dateUntil/argument-plaindatetime.js | 33 + .../dateUntil/argument-string-invalid.js | 70 + .../argument-string-with-utc-designator.js | 30 + ...one-getoffsetnanosecondsfor-non-integer.js | 22 + ...ne-getoffsetnanosecondsfor-not-callable.js | 30 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 22 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 31 + .../Calendar/prototype/dateUntil/basic.js | 48 + .../Calendar/prototype/dateUntil/branding.js | 20 +- .../Calendar/prototype/dateUntil/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../dateUntil/calendar-fields-iterable.js | 43 + .../dateUntil/calendar-temporal-object.js | 33 + .../dateUntil/largestunit-plurals-accepted.js | 23 + .../Calendar/prototype/dateUntil/length.js | 28 + .../Calendar/prototype/dateUntil/name.js | 26 + .../prototype/dateUntil/not-a-constructor.js | 24 + .../Calendar/prototype/dateUntil/prop-desc.js | 24 + .../Calendar/prototype/dateUntil/shell.js | 1329 ++++- ...hrows-range-error-ToLargestTemporalUnit.js | 2 +- .../throws-type-error-RequireInternalSlot.js | 19 - .../Calendar/prototype/dateUntil/year-zero.js | 27 + .../prototype/day/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Temporal/Calendar/prototype/day/basic.js | 20 + .../Calendar/prototype/day/branding.js | 20 +- .../Calendar/prototype/day/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../prototype/day/calendar-fields-iterable.js | 37 + .../prototype/day/calendar-temporal-object.js | 31 + .../Calendar/prototype/day/date-time.js | 3 +- .../Temporal/Calendar/prototype/day/date.js | 3 +- .../day/infinity-throws-rangeerror.js | 26 + .../Temporal/Calendar/prototype/day/length.js | 28 + .../Calendar/prototype/day/month-day.js | 3 +- .../Temporal/Calendar/prototype/day/name.js | 26 + .../prototype/day/not-a-constructor.js | 24 + .../Calendar/prototype/day/prop-desc.js | 24 + .../Temporal/Calendar/prototype/day/shell.js | 1517 ++++++ .../Temporal/Calendar/prototype/day/string.js | 3 +- .../day/throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 18 - .../Calendar/prototype/day/year-zero.js | 20 + .../dayOfWeek/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/dayOfWeek/basic.js | 19 + .../Calendar/prototype/dayOfWeek/branding.js | 20 +- .../Calendar/prototype/dayOfWeek/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../dayOfWeek/calendar-fields-iterable.js | 35 + .../dayOfWeek/calendar-temporal-object.js | 29 + .../dayOfWeek/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/dayOfWeek/length.js | 28 + .../Calendar/prototype/dayOfWeek/name.js | 26 + .../prototype/dayOfWeek/not-a-constructor.js | 24 + .../prototype/dayOfWeek/plain-date-time.js | 3 +- .../prototype/dayOfWeek/plain-date.js | 3 +- .../Calendar/prototype/dayOfWeek/prop-desc.js | 24 + .../Calendar/prototype/dayOfWeek/shell.js | 1517 ++++++ .../Calendar/prototype/dayOfWeek/string.js | 3 +- .../throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 18 - .../Calendar/prototype/dayOfWeek/year-zero.js | 20 + .../dayOfYear/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/dayOfYear/basic.js | 19 + .../Calendar/prototype/dayOfYear/branding.js | 20 +- .../Calendar/prototype/dayOfYear/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../dayOfYear/calendar-fields-iterable.js | 35 + .../dayOfYear/calendar-temporal-object.js | 29 + .../dayOfYear/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/dayOfYear/length.js | 28 + .../Calendar/prototype/dayOfYear/name.js | 26 + .../prototype/dayOfYear/not-a-constructor.js | 24 + .../prototype/dayOfYear/plain-date-time.js | 3 +- .../prototype/dayOfYear/plain-date.js | 3 +- .../Calendar/prototype/dayOfYear/prop-desc.js | 24 + .../Calendar/prototype/dayOfYear/shell.js | 1517 ++++++ .../Calendar/prototype/dayOfYear/string.js | 3 +- .../throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 18 - .../Calendar/prototype/dayOfYear/year-zero.js | 20 + .../daysInMonth/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/daysInMonth/basic.js | 19 + .../prototype/daysInMonth/branding.js | 20 +- .../Calendar/prototype/daysInMonth/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../daysInMonth/calendar-fields-iterable.js | 35 + .../daysInMonth/calendar-temporal-object.js | 29 + .../daysInMonth/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/daysInMonth/length.js | 28 + .../Calendar/prototype/daysInMonth/name.js | 26 + .../daysInMonth/not-a-constructor.js | 24 + .../prototype/daysInMonth/plain-date-time.js | 3 +- .../prototype/daysInMonth/plain-date.js | 3 +- .../prototype/daysInMonth/prop-desc.js | 24 + .../Calendar/prototype/daysInMonth/shell.js | 1517 ++++++ .../Calendar/prototype/daysInMonth/string.js | 3 +- .../throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 18 - .../prototype/daysInMonth/year-zero.js | 20 + .../daysInWeek/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/daysInWeek/basic.js | 19 + .../Calendar/prototype/daysInWeek/branding.js | 20 +- .../Calendar/prototype/daysInWeek/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../daysInWeek/calendar-fields-iterable.js | 35 + .../daysInWeek/calendar-temporal-object.js | 29 + .../daysInWeek/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/daysInWeek/length.js | 28 + .../Calendar/prototype/daysInWeek/name.js | 26 + .../prototype/daysInWeek/not-a-constructor.js | 24 + .../prototype/daysInWeek/prop-desc.js | 24 + .../Calendar/prototype/daysInWeek/shell.js | 1517 ++++++ .../Calendar/prototype/daysInWeek/string.js | 3 +- .../throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 18 - .../prototype/daysInWeek/year-zero.js | 20 + .../daysInYear/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/daysInYear/basic.js | 20 + .../Calendar/prototype/daysInYear/branding.js | 20 +- .../Calendar/prototype/daysInYear/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../daysInYear/calendar-fields-iterable.js | 37 + .../daysInYear/calendar-temporal-object.js | 31 + .../daysInYear/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/daysInYear/length.js | 28 + .../Calendar/prototype/daysInYear/name.js | 26 + .../prototype/daysInYear/not-a-constructor.js | 24 + .../prototype/daysInYear/plain-date-time.js | 3 +- .../prototype/daysInYear/plain-date.js | 3 +- .../prototype/daysInYear/prop-desc.js | 24 + .../Calendar/prototype/daysInYear/shell.js | 1517 ++++++ .../Calendar/prototype/daysInYear/string.js | 3 +- .../throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 18 - .../prototype/daysInYear/year-zero.js | 20 + .../fields/argument-iterable-not-array.js | 30 + .../fields/argument-throws-duplicate-keys.js | 31 + .../fields/argument-throws-invalid-keys.js | 38 + .../Calendar/prototype/fields/builtin.js | 36 + .../Calendar/prototype/fields/length.js | 28 + .../Calendar/prototype/fields/long-input.js | 44 +- .../Calendar/prototype/fields/name.js | 26 + .../fields/non-string-element-throws.js | 20 + .../prototype/fields/not-a-constructor.js | 24 + .../Calendar/prototype/fields/prop-desc.js | 24 + .../prototype/fields/repeated-throw.js | 59 + .../Calendar/prototype/fields/reverse.js | 45 + .../Calendar/prototype/fields/shell.js | 19 + .../inLeapYear/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + .../prototype/inLeapYear/argument-string.js | 29 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/inLeapYear/basic.js | 29 + .../Calendar/prototype/inLeapYear/branding.js | 20 +- .../Calendar/prototype/inLeapYear/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../inLeapYear/calendar-fields-iterable.js | 37 + .../inLeapYear/calendar-temporal-object.js | 29 + .../inLeapYear/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/inLeapYear/length.js | 28 + .../Calendar/prototype/inLeapYear/name.js | 26 + .../prototype/inLeapYear/not-a-constructor.js | 24 + .../prototype/inLeapYear/prop-desc.js | 24 + .../Calendar/prototype/inLeapYear/shell.js | 1517 ++++++ .../prototype/inLeapYear/year-zero.js | 20 + .../mergeFields/arguments-empty-object.js | 35 + .../mergeFields/arguments-not-object.js | 43 + .../Calendar/prototype/mergeFields/basic.js | 36 + .../Calendar/prototype/mergeFields/builtin.js | 36 + .../iso8601-calendar-month-monthCode.js | 102 + .../Calendar/prototype/mergeFields/length.js | 28 + .../Calendar/prototype/mergeFields/name.js | 26 + .../mergeFields/non-string-properties.js | 37 + .../mergeFields/not-a-constructor.js | 24 + .../prototype/mergeFields/prop-desc.js | 24 + .../Calendar/prototype/mergeFields/shell.js | 348 ++ .../month/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/month/basic.js | 21 + .../Calendar/prototype/month/branding.js | 20 +- .../Calendar/prototype/month/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../month/calendar-fields-iterable.js | 37 + .../month/calendar-temporal-object.js | 31 + .../Calendar/prototype/month/date-time.js | 3 +- .../Temporal/Calendar/prototype/month/date.js | 3 +- .../month/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/month/length.js | 28 + .../month/month-day-throw-type-error.js | 3 +- .../Temporal/Calendar/prototype/month/name.js | 26 + .../prototype/month/not-a-constructor.js | 24 + .../Calendar/prototype/month/prop-desc.js | 24 + .../Calendar/prototype/month/shell.js | 1517 ++++++ .../Calendar/prototype/month/string.js | 3 +- .../month/throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 18 - .../Calendar/prototype/month/year-month.js | 3 +- .../Calendar/prototype/month/year-zero.js | 20 + .../monthCode/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/monthCode/basic.js | 21 + .../Calendar/prototype/monthCode/branding.js | 20 +- .../Calendar/prototype/monthCode/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../monthCode/calendar-fields-iterable.js | 37 + .../monthCode/calendar-temporal-object.js | 31 + .../Calendar/prototype/monthCode/date-time.js | 3 +- .../Calendar/prototype/monthCode/date.js | 3 +- .../monthCode/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/monthCode/length.js | 28 + .../Calendar/prototype/monthCode/month-day.js | 3 +- .../Calendar/prototype/monthCode/name.js | 26 + .../prototype/monthCode/not-a-constructor.js | 24 + .../Calendar/prototype/monthCode/prop-desc.js | 24 + .../Calendar/prototype/monthCode/shell.js | 1517 ++++++ .../Calendar/prototype/monthCode/string.js | 3 +- .../throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 18 - .../prototype/monthCode/year-month.js | 3 +- .../Calendar/prototype/monthCode/year-zero.js | 20 + .../prototype/monthDayFromFields/basic.js | 43 + .../prototype/monthDayFromFields/builtin.js | 36 + .../fields-missing-properties.js | 27 + .../monthDayFromFields/fields-not-object.js | 17 + .../infinity-throws-rangeerror.js | 28 + .../prototype/monthDayFromFields/length.js | 28 + .../monthDayFromFields/monthcode-invalid.js | 34 + .../prototype/monthDayFromFields/name.js | 26 + .../monthDayFromFields/not-a-constructor.js | 24 + .../monthDayFromFields/overflow-constrain.js | 94 + .../overflow-invalid-string.js | 30 + .../monthDayFromFields/overflow-reject.js | 67 + .../monthDayFromFields/overflow-undefined.js | 28 + .../monthDayFromFields/overflow-wrong-type.js | 27 + .../prototype/monthDayFromFields/prop-desc.js | 24 + .../monthDayFromFields/reference-year-1972.js | 26 + .../prototype/monthDayFromFields/shell.js | 1517 ++++++ .../monthsInYear/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + .../prototype/monthsInYear/argument-string.js | 21 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/monthsInYear/basic.js | 20 + .../prototype/monthsInYear/branding.js | 20 +- .../prototype/monthsInYear/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../monthsInYear/calendar-fields-iterable.js | 35 + .../monthsInYear/calendar-temporal-object.js | 29 + .../infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/monthsInYear/length.js | 28 + .../Calendar/prototype/monthsInYear/name.js | 26 + .../monthsInYear/not-a-constructor.js | 24 + .../prototype/monthsInYear/prop-desc.js | 24 + .../Calendar/prototype/monthsInYear/shell.js | 1517 ++++++ .../prototype/monthsInYear/year-zero.js | 20 + .../Temporal/Calendar/prototype/prop-desc.js | 21 + .../Calendar/prototype/toJSON/branding.js | 25 + .../prototype/toJSON}/browser.js | 0 .../Calendar/prototype/toJSON/builtin.js | 36 + .../Calendar/prototype/toJSON/length.js | 28 + .../Calendar/prototype/toJSON/name.js | 26 + .../prototype/toJSON/not-a-constructor.js | 24 + .../Calendar/prototype/toJSON/prop-desc.js | 24 + .../Calendar/prototype/toJSON/shell.js | 19 + .../Calendar/prototype/toString/builtin.js | 36 + .../Calendar/prototype/toString/length.js | 28 + .../Calendar/prototype/toString/name.js | 26 + .../prototype/toString/not-a-constructor.js | 24 + .../Calendar/prototype/toString/prop-desc.js | 24 + .../Calendar/prototype/toString/shell.js | 19 + .../weekOfYear/argument-plaindate.js | 79 + .../weekOfYear/argument-plaindatetime.js | 79 + .../weekOfYear/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + .../prototype/weekOfYear/argument-string.js | 42 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Calendar/prototype/weekOfYear/basic.js | 19 + .../Calendar/prototype/weekOfYear/branding.js | 20 +- .../Calendar/prototype/weekOfYear/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../weekOfYear/calendar-fields-iterable.js | 35 + .../weekOfYear/calendar-temporal-object.js | 29 + .../prototype/weekOfYear/cross-year.js | 15 + .../weekOfYear/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/weekOfYear/length.js | 28 + .../Calendar/prototype/weekOfYear/name.js | 26 + .../prototype/weekOfYear/not-a-constructor.js | 24 + .../prototype/weekOfYear/prop-desc.js | 24 + .../Calendar/prototype/weekOfYear/shell.js | 1517 ++++++ .../prototype/weekOfYear/year-zero.js | 20 + .../prototype/year/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Temporal/Calendar/prototype/year/basic.js | 20 + .../Calendar/prototype/year/branding.js | 20 +- .../Calendar/prototype/year/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../year/calendar-fields-iterable.js | 37 + .../year/calendar-temporal-object.js | 31 + .../Calendar/prototype/year/date-time.js | 3 +- .../Temporal/Calendar/prototype/year/date.js | 3 +- .../year/infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/year/length.js | 28 + .../Temporal/Calendar/prototype/year/name.js | 26 + .../prototype/year/not-a-constructor.js | 24 + .../Calendar/prototype/year/prop-desc.js | 24 + .../Temporal/Calendar/prototype/year/shell.js | 1517 ++++++ .../Calendar/prototype/year/string.js | 3 +- .../year/throw-range-error-ToTemporalDate.js | 3 +- .../throw-type-error-RequireInternalSlot.js | 19 - .../Calendar/prototype/year/year-month.js | 3 +- .../Calendar/prototype/year/year-zero.js | 20 + .../prototype/yearMonthFromFields/basic.js | 43 + .../prototype/yearMonthFromFields/branding.js | 20 +- .../prototype/yearMonthFromFields/builtin.js | 36 + .../fields-missing-properties.js | 25 + .../yearMonthFromFields/fields-not-object.js | 17 + .../infinity-throws-rangeerror.js | 28 + .../prototype/yearMonthFromFields/length.js | 28 + .../yearMonthFromFields/monthcode-invalid.js | 34 + .../prototype/yearMonthFromFields/name.js | 26 + .../yearMonthFromFields/not-a-constructor.js | 24 + .../yearMonthFromFields/options-not-object.js | 20 + .../yearMonthFromFields/overflow-constrain.js | 94 + .../overflow-invalid-string.js | 30 + .../yearMonthFromFields/overflow-reject.js | 29 + .../yearMonthFromFields/overflow-undefined.js | 28 + .../overflow-wrong-type.js | 27 + .../yearMonthFromFields/prop-desc.js | 24 + .../prototype/yearMonthFromFields/shell.js | 1517 ++++++ .../built-ins/Temporal/Duration/basic.js | 19 + .../built-ins/Temporal/Duration/builtin.js | 30 + .../Temporal/Duration/call-builtin.js | 18 + ...t-string-fractional-units-rounding-mode.js | 23 + ...gument-string-negative-fractional-units.js | 23 + .../era => Duration/compare}/browser.js | 0 .../Temporal/Duration/compare/builtin.js | 33 + ...r-dateadd-called-with-options-undefined.js | 25 + ...-dateadd-called-with-plaindate-instance.js | 20 + .../compare/calendar-fields-iterable.js | 41 + .../compare/calendar-possibly-required.js | 51 + .../compare/calendar-temporal-object.js | 30 + .../Temporal/Duration/compare/length.js | 28 + .../Temporal/Duration/compare/name.js | 26 + .../Duration/compare/not-a-constructor.js | 23 + .../Duration/compare/options-undefined.js | 16 + .../Temporal/Duration/compare/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 25 + ...-propertybag-infinity-throws-rangeerror.js | 27 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../compare/relativeto-string-invalid.js | 17 + .../relativeto-string-plaindatetime.js | 18 + ...iveto-string-zoneddatetime-wrong-offset.js | 16 + .../relativeto-string-zoneddatetime.js | 23 + .../compare/relativeto-sub-minute-offset.js | 24 + ...iveto-undefined-throw-on-calendar-units.js | 29 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 20 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 20 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 29 + .../Temporal/Duration/compare/shell.js | 19 + ...imezone-getpossibleinstantsfor-iterable.js | 41 + .../compare/timezone-string-datetime.js | 37 + .../Duration/compare/twenty-five-hour-day.js | 36 + .../Temporal/Duration/compare/year-zero.js | 21 + .../Temporal/Duration/constructor.js | 15 + .../Temporal/Duration/days-undefined.js | 20 + .../Duration/fractional-throws-rangeerror.js | 35 + .../Duration/from/argument-existing-object.js | 20 + .../Duration/from/argument-non-string.js | 18 + .../Duration/from/argument-object-invalid.js | 29 + ...t-string-fractional-units-rounding-mode.js | 31 + .../Duration/from/argument-string-invalid.js | 35 + ...gument-string-negative-fractional-units.js | 18 + .../Temporal/Duration/from/argument-string.js | 51 + .../eraYear => Duration/from}/browser.js | 0 .../Temporal/Duration/from/builtin.js | 33 + .../from/infinity-throws-rangeerror.js | 31 + .../Temporal/Duration/from/length.js | 28 + .../built-ins/Temporal/Duration/from/name.js | 26 + .../negative-inifinity-throws-rangeerror.js | 31 + .../from/non-integer-throws-rangeerror.js | 28 + .../Duration/from/not-a-constructor.js | 23 + .../Duration/from/order-of-operations.js | 72 + .../Temporal/Duration/from/prop-desc.js | 24 + .../built-ins/Temporal/Duration/from/shell.js | 19 + .../from/string-with-skipped-units.js | 34 + .../Duration/from/subclassing-ignored.js | 19 + .../Temporal/Duration/hours-undefined.js | 20 + .../Duration/infinity-throws-rangeerror.js | 84 + .../built-ins/Temporal/Duration/length.js | 28 + .../Duration/microseconds-undefined.js | 20 + .../Duration/milliseconds-undefined.js | 20 + .../Temporal/Duration/minutes-undefined.js | 20 + .../built-ins/Temporal/Duration/mixed.js | 22 + .../Temporal/Duration/months-undefined.js | 20 + .../built-ins/Temporal/Duration/name.js | 26 + .../Duration/nanoseconds-undefined.js | 20 + .../negative-infinity-throws-rangeerror.js | 84 + .../built-ins/Temporal/Duration/prop-desc.js | 24 + .../Temporal/Duration/prototype/abs/basic.js | 42 + .../Duration/prototype/abs/builtin.js | 36 + .../Temporal/Duration/prototype/abs/length.js | 28 + .../Temporal/Duration/prototype/abs/name.js | 26 + .../prototype/abs/not-a-constructor.js | 24 + .../Duration/prototype/abs/prop-desc.js | 24 + .../Temporal/Duration/prototype/abs/shell.js | 19 + .../prototype/abs/subclassing-ignored.js | 20 + ...t-string-fractional-units-rounding-mode.js | 19 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/add/balance-negative-result.js | 39 + .../add/balance-negative-time-units.js | 63 + .../Duration/prototype/add/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 20 + ...-dateadd-called-with-plaindate-instance.js | 21 + ...euntil-called-with-singular-largestunit.js | 81 + .../prototype/add/calendar-fields-iterable.js | 41 + .../prototype/add/calendar-temporal-object.js | 30 + .../add/infinity-throws-rangeerror.js | 34 + .../Temporal/Duration/prototype/add/length.js | 28 + .../Temporal/Duration/prototype/add/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 34 + .../add/non-integer-throws-rangeerror.js | 29 + .../prototype/add/not-a-constructor.js | 24 + .../prototype/add/options-undefined.js | 16 + .../prototype/add/order-of-operations.js | 77 + .../Duration/prototype/add/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 25 + .../relativeto-infinity-throws-rangeerror.js | 26 + .../relativeto-propertybag-no-time-units.js | 18 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../add/relativeto-string-datetime.js | 43 + .../add/relativeto-string-invalid.js | 16 + .../add/relativeto-string-plaindatetime.js | 18 + ...iveto-string-zoneddatetime-wrong-offset.js | 19 + .../add/relativeto-string-zoneddatetime.js | 23 + .../add/relativeto-sub-minute-offset.js | 25 + ...zoneddatetime-negative-epochnanoseconds.js | 27 + ...one-getoffsetnanosecondsfor-non-integer.js | 20 + ...ne-getoffsetnanosecondsfor-not-callable.js | 24 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 20 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 29 + .../Temporal/Duration/prototype/add/shell.js | 19 + .../prototype/add/subclassing-ignored.js | 20 + ...imezone-getpossibleinstantsfor-iterable.js | 46 + .../prototype/add/timezone-string-datetime.js | 39 + .../Duration/prototype/add/year-zero.js | 20 + .../Duration/prototype/blank/prop-desc.js | 17 + .../Duration/prototype/days/prop-desc.js | 17 + .../Duration/prototype/hours/prop-desc.js | 17 + .../prototype/microseconds/prop-desc.js | 17 + .../prototype/milliseconds/prop-desc.js | 17 + .../Duration/prototype/minutes/prop-desc.js | 17 + .../Duration/prototype/months/prop-desc.js | 17 + .../prototype/nanoseconds/prop-desc.js | 17 + .../Duration/prototype/negated/basic.js | 54 + .../Duration/prototype/negated/builtin.js | 36 + .../Duration/prototype/negated/length.js | 28 + .../Duration/prototype/negated/name.js | 26 + .../prototype/negated/not-a-constructor.js | 24 + .../Duration/prototype/negated/prop-desc.js | 24 + .../Duration/prototype/negated/shell.js | 19 + .../prototype/negated/subclassing-ignored.js | 20 + .../Temporal/Duration/prototype/prop-desc.js | 21 + .../round/balance-negative-result.js | 25 + .../Duration/prototype/round/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 76 + ...-dateadd-called-with-plaindate-instance.js | 21 + ...euntil-called-with-singular-largestunit.js | 163 + .../round/calendar-fields-iterable.js | 40 + .../round/calendar-possibly-required.js | 65 + .../round/calendar-temporal-object.js | 29 + .../prototype/round/dateuntil-field.js | 48 + .../round/largestunit-invalid-string.js | 14 + .../round/largestunit-plurals-accepted.js | 28 + .../prototype/round/largestunit-undefined.js | 24 + .../prototype/round/largestunit-wrong-type.js | 18 + .../Duration/prototype/round/length.js | 28 + .../Temporal/Duration/prototype/round/name.js | 26 + .../prototype/round/not-a-constructor.js | 24 + .../Duration/prototype/round/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 24 + .../relativeto-infinity-throws-rangeerror.js | 26 + .../relativeto-propertybag-no-time-units.js | 18 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../round/relativeto-string-datetime.js | 43 + .../round/relativeto-string-invalid.js | 16 + .../round/relativeto-string-plaindatetime.js | 18 + ...iveto-string-zoneddatetime-wrong-offset.js | 19 + .../round/relativeto-string-zoneddatetime.js | 23 + .../round/relativeto-sub-minute-offset.js | 25 + ...iveto-undefined-throw-on-calendar-units.js | 31 + ...zoneddatetime-negative-epochnanoseconds.js | 27 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/round/round-negative-result.js | 26 + .../prototype/round/roundingincrement-nan.js | 21 + .../round/roundingincrement-undefined.js | 27 + .../round/roundingincrement-wrong-type.js | 27 + .../round/roundingmode-invalid-string.js | 16 + .../prototype/round/roundingmode-undefined.js | 29 + .../round/roundingmode-wrong-type.js | 18 + .../Duration/prototype/round/shell.js | 19 + .../smallestunit-disallowed-units-string.js | 29 + .../round/smallestunit-invalid-string.js | 14 + .../smallestunit-plurals-accepted-string.js | 24 + .../round/smallestunit-plurals-accepted.js | 28 + .../smallestunit-string-shorthand-string.js | 28 + .../prototype/round/smallestunit-undefined.js | 18 + .../round/smallestunit-wrong-type.js | 18 + .../prototype/round/subclassing-ignored.js | 20 + ...imezone-getpossibleinstantsfor-iterable.js | 48 + .../round/timezone-string-datetime.js | 39 + .../Duration/prototype/round/year-zero.js | 20 + .../Duration/prototype/seconds/prop-desc.js | 17 + .../Duration/prototype/sign/prop-desc.js | 17 + ...t-string-fractional-units-rounding-mode.js | 19 + ...gument-string-negative-fractional-units.js | 20 + .../subtract/balance-negative-result.js | 39 + .../subtract/balance-negative-time-units.js | 63 + .../Duration/prototype/subtract/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 20 + ...-dateadd-called-with-plaindate-instance.js | 21 + ...euntil-called-with-singular-largestunit.js | 81 + .../subtract/calendar-fields-iterable.js | 41 + .../subtract/calendar-temporal-object.js | 30 + .../subtract/infinity-throws-rangeerror.js | 34 + .../Duration/prototype/subtract/length.js | 28 + .../Duration/prototype/subtract/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 34 + .../subtract/non-integer-throws-rangeerror.js | 29 + .../prototype/subtract/not-a-constructor.js | 24 + .../prototype/subtract/options-undefined.js | 16 + .../prototype/subtract/order-of-operations.js | 77 + .../Duration/prototype/subtract/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 25 + .../relativeto-infinity-throws-rangeerror.js | 26 + .../relativeto-propertybag-no-time-units.js | 18 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../subtract/relativeto-string-datetime.js | 43 + .../subtract/relativeto-string-invalid.js | 16 + .../relativeto-string-plaindatetime.js | 18 + ...iveto-string-zoneddatetime-wrong-offset.js | 19 + .../relativeto-string-zoneddatetime.js | 23 + .../subtract/relativeto-sub-minute-offset.js | 25 + ...zoneddatetime-negative-epochnanoseconds.js | 27 + ...one-getoffsetnanosecondsfor-non-integer.js | 20 + ...ne-getoffsetnanosecondsfor-not-callable.js | 24 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 20 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 29 + .../Duration/prototype/subtract/shell.js | 19 + .../prototype/subtract/subclassing-ignored.js | 20 + ...imezone-getpossibleinstantsfor-iterable.js | 46 + .../subtract/timezone-string-datetime.js | 39 + .../Duration/prototype/subtract/year-zero.js | 20 + .../Duration/prototype/toJSON/basic.js | 243 + .../Duration/prototype/toJSON/builtin.js | 36 + .../Duration/prototype/toJSON/length.js | 28 + .../Duration/prototype/toJSON/name.js | 26 + .../prototype/toJSON/negative-components.js | 14 + .../prototype/toJSON/not-a-constructor.js | 24 + .../Duration/prototype/toJSON/prop-desc.js | 24 + .../Duration/prototype/toJSON/shell.js | 19 + .../prototype/toLocaleString/builtin.js | 36 + .../prototype/toLocaleString/length.js | 28 + .../Duration/prototype/toLocaleString/name.js | 26 + .../toLocaleString/not-a-constructor.js | 24 + .../prototype/toLocaleString/prop-desc.js | 24 + .../prototype/toLocaleString/shell.js | 19 + .../Duration/prototype/toString/balance.js | 27 + .../toString/blank-duration-precision.js | 25 + .../Duration/prototype/toString/builtin.js | 36 + ...onalseconddigits-exact-number-of-digits.js | 40 + .../fractionalseconddigits-invalid-string.js | 24 + .../toString/fractionalseconddigits-nan.js | 23 + .../fractionalseconddigits-non-integer.js | 23 + .../fractionalseconddigits-out-of-range.js | 25 + .../fractionalseconddigits-undefined.js | 28 + .../fractionalseconddigits-wrong-type.js | 28 + .../Duration/prototype/toString/length.js | 28 + .../Duration/prototype/toString/name.js | 26 + .../prototype/toString/negative-components.js | 41 + .../prototype/toString/not-a-constructor.js | 24 + .../prototype/toString/options-undefined.js | 19 + .../Duration/prototype/toString/precision.js | 22 + .../Duration/prototype/toString/prop-desc.js | 24 + .../toString/roundingmode-invalid-string.js | 16 + .../toString/roundingmode-undefined.js | 28 + .../toString/roundingmode-wrong-type.js | 18 + .../Duration/prototype/toString/shell.js | 19 + .../toString/smallestunit-invalid-string.js | 17 + .../toString/smallestunit-plurals-accepted.js | 21 + .../toString/smallestunit-undefined.js | 23 + .../toString/smallestunit-valid-units.js | 31 + .../toString/smallestunit-wrong-type.js | 18 + .../total/balance-negative-result.js | 24 + .../Duration/prototype/total/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 52 + ...-dateadd-called-with-plaindate-instance.js | 21 + ...euntil-called-with-singular-largestunit.js | 96 + .../total/calendar-fields-iterable.js | 40 + .../total/calendar-possibly-required.js | 49 + .../total/calendar-temporal-object.js | 29 + .../prototype/total/dateuntil-field.js | 31 + .../Duration/prototype/total/length.js | 28 + .../Temporal/Duration/prototype/total/name.js | 26 + .../prototype/total/not-a-constructor.js | 24 + .../prototype/total/options-wrong-type.js | 26 + .../Duration/prototype/total/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 24 + .../relativeto-infinity-throws-rangeerror.js | 26 + .../relativeto-propertybag-no-time-units.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../total/relativeto-string-datetime.js | 42 + .../total/relativeto-string-invalid.js | 16 + .../total/relativeto-string-plaindatetime.js | 17 + ...iveto-string-zoneddatetime-wrong-offset.js | 19 + .../total/relativeto-string-zoneddatetime.js | 22 + .../total/relativeto-sub-minute-offset.js | 24 + ...iveto-undefined-throw-on-calendar-units.js | 35 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../Duration/prototype/total/shell.js | 19 + ...imezone-getpossibleinstantsfor-iterable.js | 36 + .../total/timezone-string-datetime.js | 39 + .../total/unit-disallowed-units-string.js | 29 + .../prototype/total/unit-invalid-string.js | 21 + .../total/unit-plurals-accepted-string.js | 24 + .../prototype/total/unit-plurals-accepted.js | 28 + .../total/unit-string-shorthand-string.js | 27 + .../prototype/total/unit-wrong-type.js | 25 + .../Duration/prototype/total/year-zero.js | 20 + .../Duration/prototype/valueOf/builtin.js | 36 + .../Duration/prototype/valueOf/length.js | 28 + .../Duration/prototype/valueOf/name.js | 26 + .../prototype/valueOf/not-a-constructor.js | 24 + .../Duration/prototype/valueOf/prop-desc.js | 24 + .../Duration/prototype/valueOf/shell.js | 19 + .../Duration/prototype/weeks/prop-desc.js | 17 + .../Duration/prototype/with/all-negative.js | 96 + .../Duration/prototype/with/all-positive.js | 95 + .../with/argument-object-wrong-shape.js | 34 + .../prototype/with/argument-wrong-type.js | 30 + .../Duration/prototype/with/branding.js | 20 +- .../Duration/prototype/with/builtin.js | 36 + .../with/copy-properties-not-undefined.js | 26 + .../with/infinity-throws-rangeerror.js | 33 + .../Duration/prototype/with/length.js | 28 + .../Temporal/Duration/prototype/with/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 33 + .../with/non-integer-throws-rangeerror.js | 29 + .../prototype/with/not-a-constructor.js | 24 + .../prototype/with/order-of-operations.js | 76 + .../prototype/with/partial-positive.js | 89 + .../Duration/prototype/with/prop-desc.js | 24 + .../Temporal/Duration/prototype/with/shell.js | 19 + .../with/sign-conflict-throws-rangeerror.js | 31 + .../prototype/with/subclassing-ignored.js | 20 + .../Duration/prototype/years/prop-desc.js | 17 + .../Temporal/Duration/seconds-undefined.js | 20 + .../built-ins/Temporal/Duration/shell.js | 1498 ++++++ .../Temporal/Duration/weeks-undefined.js | 20 + .../Temporal/Duration/years-undefined.js | 20 + .../built-ins/Temporal/Instant/argument.js | 17 + .../built-ins/Temporal/Instant/basic.js | 23 + .../built-ins/Temporal/Instant/builtin.js | 30 + .../Instant/compare/argument-zoneddatetime.js | 31 + .../era => Instant/compare}/browser.js | 0 .../Temporal/Instant/compare/builtin.js | 33 + .../instant-string-multiple-offsets.js | 17 + .../Instant/compare/instant-string.js | 37 + .../Temporal/Instant/compare/length.js | 28 + .../Temporal/Instant/compare/name.js | 26 + .../Instant/compare/not-a-constructor.js | 23 + .../Temporal/Instant/compare/prop-desc.js | 24 + .../Temporal/Instant/compare/shell.js | 1517 ++++++ .../Temporal/Instant/compare/year-zero.js | 22 + .../built-ins/Temporal/Instant/constructor.js | 15 + .../Instant/from/argument-zoneddatetime.js | 23 + .../eraYear => Instant/from}/browser.js | 0 .../Temporal/Instant/from/builtin.js | 33 + .../from/instant-string-multiple-offsets.js | 16 + .../Temporal/Instant/from/instant-string.js | 32 + .../built-ins/Temporal/Instant/from/length.js | 28 + .../built-ins/Temporal/Instant/from/name.js | 26 + .../Instant/from/not-a-constructor.js | 23 + .../Temporal/Instant/from/prop-desc.js | 24 + .../built-ins/Temporal/Instant/from/shell.js | 1517 ++++++ .../Instant/from/subclassing-ignored.js | 19 + .../Temporal/Instant/from/timezone-custom.js | 22 + .../Temporal/Instant/from/year-zero.js | 25 + .../Instant/fromEpochMicroseconds/basic.js | 17 + .../fromEpochMicroseconds}/browser.js | 0 .../Instant/fromEpochMicroseconds/builtin.js | 33 + .../Instant/fromEpochMicroseconds/length.js | 28 + .../Instant/fromEpochMicroseconds/name.js | 26 + .../not-a-constructor.js | 23 + .../fromEpochMicroseconds/prop-desc.js | 24 + .../Instant/fromEpochMicroseconds/shell.js | 1517 ++++++ .../subclassing-ignored.js | 21 + .../Instant/fromEpochMilliseconds/basic.js | 17 + .../fromEpochMilliseconds}/browser.js | 0 .../Instant/fromEpochMilliseconds/builtin.js | 33 + .../Instant/fromEpochMilliseconds/length.js | 28 + .../Instant/fromEpochMilliseconds/name.js | 26 + .../not-a-constructor.js | 23 + .../fromEpochMilliseconds/prop-desc.js | 24 + .../Instant/fromEpochMilliseconds/shell.js | 1517 ++++++ .../subclassing-ignored.js | 21 + .../Instant/fromEpochNanoseconds/basic.js | 17 + .../fromEpochNanoseconds/browser.js} | 0 .../Instant/fromEpochNanoseconds/builtin.js | 33 + .../Instant/fromEpochNanoseconds/length.js | 28 + .../Instant/fromEpochNanoseconds/name.js | 26 + .../fromEpochNanoseconds/not-a-constructor.js | 23 + .../Instant/fromEpochNanoseconds/prop-desc.js | 24 + .../Instant/fromEpochNanoseconds/shell.js | 1517 ++++++ .../subclassing-ignored.js | 21 + .../Instant/fromEpochSeconds/basic.js | 17 + .../fromEpochSeconds/browser.js} | 0 .../Instant/fromEpochSeconds/builtin.js | 33 + .../Instant/fromEpochSeconds/length.js | 28 + .../Temporal/Instant/fromEpochSeconds/name.js | 26 + .../fromEpochSeconds/not-a-constructor.js | 23 + .../Instant/fromEpochSeconds/prop-desc.js | 24 + .../Instant/fromEpochSeconds/shell.js | 1517 ++++++ .../fromEpochSeconds/subclassing-ignored.js | 21 + .../built-ins/Temporal/Instant/length.js | 28 + .../built-ins/Temporal/Instant/name.js | 26 + .../built-ins/Temporal/Instant/prop-desc.js | 24 + ...t-string-fractional-units-rounding-mode.js | 18 + ...gument-string-negative-fractional-units.js | 19 + .../Instant/prototype/add/argument-string.js | 15 + .../Temporal/Instant/prototype/add/basic.js | 75 + .../Instant/prototype/add/branding.js | 20 +- .../Temporal/Instant/prototype/add/builtin.js | 36 + .../add/disallowed-duration-units.js | 34 + .../add/infinity-throws-rangeerror.js | 33 + .../Temporal/Instant/prototype/add/length.js | 28 + .../Temporal/Instant/prototype/add/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 33 + .../add/non-integer-throws-rangeerror.js | 29 + .../prototype/add/not-a-constructor.js | 24 + .../prototype/add/order-of-operations.js | 64 + .../Instant/prototype/add/prop-desc.js | 24 + .../prototype/add/result-out-of-range.js | 33 + .../Temporal/Instant/prototype/add/shell.js | 1517 ++++++ .../prototype/add/subclassing-ignored.js | 22 + .../Temporal/Instant/prototype/builtin.js | 35 + .../prototype/epochMicroseconds/basic.js | 19 + .../prototype/epochMicroseconds/prop-desc.js | 17 + .../prototype/epochMilliseconds/basic.js | 19 + .../prototype/epochMilliseconds/prop-desc.js | 17 + .../prototype/epochNanoseconds/basic.js | 19 + .../prototype/epochNanoseconds/prop-desc.js | 17 + .../Instant/prototype/epochSeconds/basic.js | 19 + .../prototype/epochSeconds/prop-desc.js | 17 + .../prototype/equals/argument-wrong-type.js | 23 + .../equals/argument-zoneddatetime.js | 23 + .../Instant/prototype/equals/builtin.js | 36 + .../equals/instant-string-multiple-offsets.js | 17 + .../prototype/equals/instant-string.js | 34 + .../Instant/prototype/equals/length.js | 28 + .../Temporal/Instant/prototype/equals/name.js | 26 + .../prototype/equals/not-a-constructor.js | 24 + .../Instant/prototype/equals/prop-desc.js | 24 + .../Instant/prototype/equals/shell.js | 1517 ++++++ .../Instant/prototype/equals/year-zero.js | 25 + .../Temporal/Instant/prototype/prop-desc.js | 21 + .../Instant/prototype/round/builtin.js | 36 + .../Instant/prototype/round/length.js | 28 + .../Temporal/Instant/prototype/round/name.js | 26 + .../prototype/round/not-a-constructor.js | 24 + .../prototype/round/options-wrong-type.js | 26 + .../Instant/prototype/round/prop-desc.js | 24 + .../prototype/round/roundingincrement-nan.js | 21 + .../round/roundingincrement-non-integer.js | 18 + .../round/roundingincrement-out-of-range.js | 20 + .../round/roundingincrement-undefined.js | 26 + .../round/roundingincrement-wrong-type.js | 27 + .../round/roundingmode-invalid-string.js | 16 + .../prototype/round/roundingmode-undefined.js | 28 + .../round/roundingmode-wrong-type.js | 18 + .../Temporal/Instant/prototype/round/shell.js | 1517 ++++++ .../round/smallestunit-disallowed-units.js | 37 + .../round/smallestunit-invalid-string.js | 14 + .../round/smallestunit-plurals-accepted.js | 24 + .../round/smallestunit-string-shorthand.js | 27 + .../round/smallestunit-wrong-type.js | 18 + .../prototype/round/subclassing-ignored.js | 22 + .../prototype/since/argument-zoneddatetime.js | 24 + .../Instant/prototype/since/builtin.js | 36 + .../since/instant-string-multiple-offsets.js | 18 + .../Instant/prototype/since/instant-string.js | 35 + .../since/largestunit-invalid-string.js | 18 + .../since/largestunit-plurals-accepted.js | 24 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/since/largestunit-undefined.js | 20 + .../prototype/since/largestunit-wrong-type.js | 19 + .../Instant/prototype/since/largestunit.js | 21 + .../Instant/prototype/since/length.js | 28 + .../Temporal/Instant/prototype/since/name.js | 26 + .../prototype/since/not-a-constructor.js | 24 + .../prototype/since/options-undefined.js | 34 + .../Instant/prototype/since/prop-desc.js | 24 + .../prototype/since/roundingincrement-nan.js | 22 + .../since/roundingincrement-non-integer.js | 20 + .../since/roundingincrement-out-of-range.js | 21 + .../since/roundingincrement-undefined.js | 28 + .../since/roundingincrement-wrong-type.js | 28 + .../since/roundingmode-invalid-string.js | 17 + .../prototype/since/roundingmode-undefined.js | 30 + .../since/roundingmode-wrong-type.js | 19 + .../Temporal/Instant/prototype/since/shell.js | 1517 ++++++ .../since/smallestunit-invalid-string.js | 18 + .../since/smallestunit-plurals-accepted.js | 24 + .../prototype/since/smallestunit-undefined.js | 20 + .../since/smallestunit-wrong-type.js | 19 + .../Instant/prototype/since/year-zero.js | 25 + ...t-string-fractional-units-rounding-mode.js | 18 + ...gument-string-negative-fractional-units.js | 19 + .../prototype/subtract/argument-string.js | 15 + .../Instant/prototype/subtract/basic.js | 75 + .../Instant/prototype/subtract/branding.js | 20 +- .../Instant/prototype/subtract/builtin.js | 36 + .../subtract/disallowed-duration-units.js | 34 + .../subtract/infinity-throws-rangeerror.js | 33 + .../Instant/prototype/subtract/length.js | 28 + .../Instant/prototype/subtract/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 33 + .../subtract/non-integer-throws-rangeerror.js | 29 + .../prototype/subtract/not-a-constructor.js | 24 + .../prototype/subtract/order-of-operations.js | 64 + .../Instant/prototype/subtract/prop-desc.js | 24 + .../prototype/subtract/result-out-of-range.js | 33 + .../Instant/prototype/subtract/shell.js | 1517 ++++++ .../prototype/subtract/subclassing-ignored.js | 22 + .../Instant/prototype/toJSON/basic.js | 19 + .../Instant/prototype/toJSON/builtin.js | 36 + .../Instant/prototype/toJSON/length.js | 28 + .../Temporal/Instant/prototype/toJSON/name.js | 26 + .../toJSON/negative-epochnanoseconds.js | 24 + .../prototype/toJSON/not-a-constructor.js | 24 + .../Instant/prototype/toJSON/prop-desc.js | 24 + .../Instant/prototype/toJSON/shell.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + .../Instant/prototype/toJSON/year-format.js | 56 + .../prototype/toLocaleString/builtin.js | 36 + .../prototype/toLocaleString/length.js | 28 + .../Instant/prototype/toLocaleString/name.js | 26 + .../toLocaleString/not-a-constructor.js | 24 + .../prototype/toLocaleString/prop-desc.js | 24 + .../prototype/toLocaleString/return-string.js | 17 + .../Instant/prototype/toLocaleString/shell.js | 19 + .../Instant/prototype/toString/basic.js | 17 + .../Instant/prototype/toString/builtin.js | 36 + .../fractionalseconddigits-invalid-string.js | 22 + .../toString/fractionalseconddigits-nan.js | 23 + .../fractionalseconddigits-non-integer.js | 23 + .../fractionalseconddigits-out-of-range.js | 25 + .../fractionalseconddigits-undefined.js | 28 + .../fractionalseconddigits-wrong-type.js | 28 + .../Instant/prototype/toString/length.js | 28 + .../Instant/prototype/toString/name.js | 26 + .../toString/negative-epochnanoseconds.js | 24 + .../prototype/toString/not-a-constructor.js | 24 + .../prototype/toString/options-undefined.js | 41 + .../Instant/prototype/toString/precision.js | 21 + .../Instant/prototype/toString/prop-desc.js | 24 + .../toString/roundingmode-invalid-string.js | 16 + .../toString/roundingmode-undefined.js | 28 + .../toString/roundingmode-wrong-type.js | 18 + .../Instant/prototype/toString/shell.js | 1517 ++++++ .../toString/smallestunit-invalid-string.js | 14 + .../toString/smallestunit-plurals-accepted.js | 22 + .../toString/smallestunit-undefined.js | 23 + .../toString/smallestunit-valid-units.js | 32 + .../toString/smallestunit-wrong-type.js | 18 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/toString/timezone-offset.js | 24 + .../toString/timezone-string-datetime.js | 47 + .../timezone-string-multiple-offsets.js | 19 + .../Instant/prototype/toString/timezone.js | 56 + .../Instant/prototype/toString/year-format.js | 56 + .../prototype/toStringTag/browser.js} | 0 .../prototype/toStringTag/prop-desc.js | 20 + .../prototype/toStringTag}/shell.js | 0 .../prototype/toZonedDateTime/builtin.js | 36 + .../calendar-temporal-object.js | 24 + .../prototype/toZonedDateTime/length.js | 28 + .../Instant/prototype/toZonedDateTime/name.js | 26 + .../toZonedDateTime/not-a-constructor.js | 24 + .../toZonedDateTime/plain-custom-timezone.js | 41 + .../prototype/toZonedDateTime/prop-desc.js | 24 + .../prototype/toZonedDateTime/shell.js | 1517 ++++++ .../timezone-string-datetime.js | 47 + .../timezone-string-multiple-offsets.js | 19 + .../prototype/toZonedDateTimeISO/builtin.js | 36 + .../prototype/toZonedDateTimeISO/length.js | 28 + .../prototype/toZonedDateTimeISO/name.js | 26 + .../toZonedDateTimeISO/not-a-constructor.js | 24 + .../prototype/toZonedDateTimeISO/prop-desc.js | 24 + .../prototype/toZonedDateTimeISO/shell.js | 19 + .../timezone-string-datetime.js | 47 + .../timezone-string-multiple-offsets.js | 19 + .../prototype/until/argument-zoneddatetime.js | 24 + .../Instant/prototype/until/builtin.js | 36 + .../until/instant-string-multiple-offsets.js | 18 + .../Instant/prototype/until/instant-string.js | 35 + .../until/largestunit-invalid-string.js | 18 + .../until/largestunit-plurals-accepted.js | 24 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/until/largestunit-undefined.js | 20 + .../prototype/until/largestunit-wrong-type.js | 19 + .../Instant/prototype/until/length.js | 28 + .../Temporal/Instant/prototype/until/name.js | 26 + .../prototype/until/not-a-constructor.js | 24 + .../prototype/until/options-undefined.js | 34 + .../Instant/prototype/until/prop-desc.js | 24 + .../prototype/until/roundingincrement-nan.js | 22 + .../until/roundingincrement-non-integer.js | 20 + .../until/roundingincrement-out-of-range.js | 21 + .../until/roundingincrement-undefined.js | 28 + .../until/roundingincrement-wrong-type.js | 28 + .../until/roundingmode-invalid-string.js | 17 + .../prototype/until/roundingmode-undefined.js | 30 + .../until/roundingmode-wrong-type.js | 19 + .../Temporal/Instant/prototype/until/shell.js | 1517 ++++++ .../until/smallestunit-invalid-string.js | 18 + .../until/smallestunit-plurals-accepted.js | 24 + .../prototype/until/smallestunit-undefined.js | 20 + .../until/smallestunit-wrong-type.js | 19 + .../Instant/prototype/until/year-zero.js | 25 + .../Instant/prototype/valueOf/builtin.js | 36 + .../Instant/prototype/valueOf/length.js | 28 + .../Instant/prototype/valueOf/name.js | 26 + .../prototype/valueOf/not-a-constructor.js | 24 + .../Instant/prototype/valueOf/prop-desc.js | 24 + .../Instant/prototype/valueOf/shell.js | 19 + .../test262/built-ins/Temporal/Now/builtin.js | 30 + .../built-ins/Temporal/Now/instant/length.js | 9 + .../Temporal/Now/instant/prop-desc.js | 2 + .../Now/instant/return-value-instance.js | 14 + .../era/shell.js => Now/plainDate/browser.js} | 0 .../Now/plainDate/calendar-temporal-object.js | 25 + .../Now/plainDate/calendar-undefined.js | 14 + .../Temporal/Now/plainDate/length.js | 28 + .../Temporal/Now/plainDate/prop-desc.js | 20 + .../built-ins/Temporal/Now/plainDate/shell.js | 1498 ++++++ ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 21 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../Now/plainDate/timezone-string-datetime.js | 37 + .../Now/plainDate/toPlainDate-override.js | 51 + .../shell.js => Now/plainDateISO/browser.js} | 0 .../Temporal/Now/plainDateISO/length.js | 28 + .../Temporal/Now/plainDateISO/prop-desc.js | 20 + .../Temporal/Now/plainDateISO/return-value.js | 15 + .../Temporal/Now/plainDateISO/shell.js | 1498 ++++++ ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 21 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../plainDateISO/timezone-string-datetime.js | 37 + .../Now/plainDateTime/calendar-object.js | 16 +- .../plainDateTime/calendar-temporal-object.js | 2 +- .../Now/plainDateTime/calendar-undefined.js | 14 + .../Temporal/Now/plainDateTime/prop-desc.js | 2 + .../Temporal/Now/plainDateTime/shell.js | 1310 ++++- ...ne-getoffsetnanosecondsfor-not-callable.js | 21 + .../plainDateTime/timezone-string-datetime.js | 37 + .../Temporal/Now/plainDateTime/timezone.js | 45 + .../plainDateTimeISO/browser.js} | 0 .../Now/plainDateTimeISO/extensible.js | 15 + .../Temporal/Now/plainDateTimeISO/length.js | 28 + .../Temporal/Now/plainDateTimeISO/name.js | 23 + .../Now/plainDateTimeISO/not-a-constructor.js | 17 + .../Now/plainDateTimeISO/prop-desc.js | 19 + .../plainDateTimeISO/return-value-calendar.js | 15 + .../Now/plainDateTimeISO/return-value.js | 21 + .../Temporal/Now/plainDateTimeISO/shell.js | 1517 ++++++ .../plainDateTimeISO/time-zone-undefined.js | 38 + ...zone-getoffsetnanosecondsfor-invocation.js | 31 + ...one-getoffsetnanosecondsfor-non-integer.js | 20 + ...zone-getoffsetnanosecondsfor-non-method.js | 18 + ...ne-getoffsetnanosecondsfor-not-a-number.js | 40 + ...ne-getoffsetnanosecondsfor-not-callable.js | 21 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 20 + ...mezone-getoffsetnanosecondsfor-poisoned.js | 20 + ...timezone-getoffsetnanosecondsfor-throws.js | 20 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 24 + .../timezone-object-fail-call-tostring.js | 23 + .../timezone-object-fail-get-timezone.js | 20 + ...imezone-object-fail-has-nested-timezone.js | 24 + .../timezone-object-fail-has-timezone.js | 22 + .../Now/plainDateTimeISO/timezone-object.js | 80 + .../timezone-string-datetime.js | 37 + .../shell.js => Now/plainTimeISO/browser.js} | 0 .../Temporal/Now/plainTimeISO/length.js | 28 + .../Temporal/Now/plainTimeISO/prop-desc.js | 20 + .../Temporal/Now/plainTimeISO/return-value.js | 15 + .../Temporal/Now/plainTimeISO/shell.js | 1498 ++++++ ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 21 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../plainTimeISO/timezone-string-datetime.js | 37 + .../Temporal/Now/plainTimeISO/timezone.js | 44 + .../Now/plainTimeISO/toPlainTime-override.js | 53 + .../built-ins/Temporal/Now/prop-desc.js | 24 + .../Temporal/Now/timeZone/prop-desc.js | 2 + .../Temporal/Now/toStringTag/browser.js | 0 .../Temporal/Now/toStringTag/prop-desc.js | 19 + .../Temporal/Now/toStringTag/shell.js | 0 .../Temporal/Now/toStringTag/string.js | 13 + .../Temporal/Now/zonedDateTime/browser.js | 0 .../Now/zonedDateTime/calendar-function.js | 50 + .../calendar-object-fail-call-tostring.js | 23 + .../calendar-object-fail-get-calendar.js | 20 + .../calendar-object-fail-has-calendar.js | 23 + ...alendar-object-fail-has-nested-calendar.js | 24 + .../Now/zonedDateTime/calendar-object.js | 76 + .../zonedDateTime/calendar-temporal-object.js | 25 + .../Now/zonedDateTime/calendar-undefined.js | 14 + .../Temporal/Now/zonedDateTime/extensible.js | 15 + .../Temporal/Now/zonedDateTime/length.js | 28 + .../Temporal/Now/zonedDateTime/name.js | 23 + .../Now/zonedDateTime/not-a-constructor.js | 17 + .../Temporal/Now/zonedDateTime/prop-desc.js | 19 + .../Temporal/Now/zonedDateTime/shell.js | 1517 ++++++ .../Now/zonedDateTime/time-zone-undefined.js | 34 + .../timezone-object-fail-call-tostring.js | 23 + .../timezone-object-fail-get-timezone.js | 20 + ...imezone-object-fail-has-nested-timezone.js | 24 + .../timezone-object-fail-has-timezone.js | 22 + .../Now/zonedDateTime/timezone-object.js | 78 + .../zonedDateTime/timezone-string-datetime.js | 45 + .../timezone-string-multiple-offsets.js | 18 + .../Temporal/Now/zonedDateTimeISO/browser.js | 0 .../Now/zonedDateTimeISO/extensible.js | 15 + .../Temporal/Now/zonedDateTimeISO/length.js | 28 + .../Temporal/Now/zonedDateTimeISO/name.js | 23 + .../Now/zonedDateTimeISO/not-a-constructor.js | 17 + .../Now/zonedDateTimeISO/prop-desc.js | 19 + .../Now/zonedDateTimeISO/return-value.js | 19 + .../Temporal/Now/zonedDateTimeISO/shell.js | 19 + .../zonedDateTimeISO/time-zone-undefined.js | 34 + .../timezone-object-fail-call-tostring.js | 23 + .../timezone-object-fail-get-timezone.js | 20 + ...imezone-object-fail-has-nested-timezone.js | 24 + .../timezone-object-fail-has-timezone.js | 22 + .../Now/zonedDateTimeISO/timezone-object.js | 78 + .../timezone-string-datetime.js | 45 + .../timezone-string-multiple-offsets.js | 18 + .../built-ins/Temporal/PlainDate/basic.js | 28 + .../built-ins/Temporal/PlainDate/builtin.js | 30 + .../PlainDate/calendar-temporal-object.js | 25 + .../Temporal/PlainDate/calendar-undefined.js | 25 + .../PlainDate/compare/argument-object.js | 25 + .../compare/argument-plaindatetime.js | 31 + .../compare/argument-string-invalid.js | 69 + .../argument-string-with-utc-designator.js | 29 + .../PlainDate/compare/argument-string.js | 22 + ...one-getoffsetnanosecondsfor-non-integer.js | 21 + ...ne-getoffsetnanosecondsfor-not-callable.js | 28 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 21 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 30 + .../Temporal/PlainDate/compare/basic.js | 19 + .../Temporal/PlainDate/compare/browser.js | 0 .../Temporal/PlainDate/compare/builtin.js | 33 + ...romfields-called-with-options-undefined.js | 18 + .../compare/calendar-fields-iterable.js | 41 + .../compare/calendar-temporal-object.js | 32 + .../Temporal/PlainDate/compare/calendar.js | 40 + .../compare/infinity-throws-rangeerror.js | 33 + .../Temporal/PlainDate/compare/length.js | 28 + .../Temporal/PlainDate/compare/name.js | 26 + .../PlainDate/compare/not-a-constructor.js | 23 + .../Temporal/PlainDate/compare/prop-desc.js | 24 + .../Temporal/PlainDate/compare/shell.js | 19 + .../PlainDate/compare/use-internal-slots.js | 29 + .../Temporal/PlainDate/compare/year-zero.js | 24 + .../Temporal/PlainDate/constructor.js | 15 + .../PlainDate/from/argument-number.js | 15 + .../PlainDate/from/argument-object-invalid.js | 44 + .../PlainDate/from/argument-object-valid.js | 36 + .../PlainDate/from/argument-plaindate.js | 17 + .../PlainDate/from/argument-plaindatetime.js | 24 + .../PlainDate/from/argument-string-invalid.js | 63 + .../from/argument-string-trailing-junk.js | 14 + .../argument-string-with-utc-designator.js | 23 + .../PlainDate/from/argument-string.js | 43 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 21 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../Temporal/PlainDate/from/browser.js | 0 .../Temporal/PlainDate/from/builtin.js | 33 + .../from/calendar-fields-iterable.js | 33 + .../from/calendar-temporal-object.js | 29 + .../from/infinity-throws-rangeerror.js | 27 + .../Temporal/PlainDate/from/length.js | 28 + .../Temporal/PlainDate/from/limits.js | 31 + .../built-ins/Temporal/PlainDate/from/name.js | 26 + .../PlainDate/from/not-a-constructor.js | 23 + ...le-get-overflow-argument-string-invalid.js | 33 + ...observable-get-overflow-argument-string.js | 36 + .../PlainDate/from/options-invalid.js | 18 + .../PlainDate/from/options-undefined.js | 19 + .../PlainDate/from/order-of-operations.js | 51 + .../PlainDate/from/overflow-invalid-string.js | 50 + .../PlainDate/from/overflow-undefined.js | 48 + .../PlainDate/from/overflow-wrong-type.js | 37 + .../Temporal/PlainDate/from/prop-desc.js | 24 + .../Temporal/PlainDate/from/shell.js | 19 + .../PlainDate/from/subclassing-ignored.js | 19 + .../Temporal/PlainDate/from/year-zero.js | 20 + .../PlainDate/infinity-throws-rangeerror.js | 42 + .../built-ins/Temporal/PlainDate/length.js | 28 + .../built-ins/Temporal/PlainDate/limits.js | 19 + .../Temporal/PlainDate/missing-arguments.js | 25 + .../built-ins/Temporal/PlainDate/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 42 + .../built-ins/Temporal/PlainDate/prop-desc.js | 24 + .../add/argument-invalid-duration.js | 19 + .../add/argument-missing-properties.js | 21 + .../prototype/add/argument-not-object.js | 20 + .../prototype/add/argument-singular-units.js | 16 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/add/argument-string.js | 16 + .../add/balance-smaller-units-basic.js | 32 + .../prototype/add/balance-smaller-units.js | 54 + .../Temporal/PlainDate/prototype/add/basic.js | 32 + .../PlainDate/prototype/add/builtin.js | 36 + .../add/infinity-throws-rangeerror.js | 38 + .../PlainDate/prototype/add/length.js | 28 + .../PlainDate/prototype/add/limits.js | 18 + .../Temporal/PlainDate/prototype/add/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 38 + .../add/non-integer-throws-rangeerror.js | 29 + .../prototype/add/not-a-constructor.js | 24 + .../prototype/add/options-invalid.js | 19 + .../prototype/add/options-undefined.js | 22 + .../prototype/add/order-of-operations.js | 77 + .../prototype/add/overflow-constrain.js | 18 + .../prototype/add/overflow-invalid-string.js | 32 + .../prototype/add/overflow-reject.js | 14 + .../prototype/add/overflow-undefined.js | 31 + .../prototype/add/overflow-wrong-type.js | 28 + .../PlainDate/prototype/add/prop-desc.js | 24 + .../Temporal/PlainDate/prototype/add/shell.js | 19 + .../prototype/add/subclassing-ignored.js | 20 + .../PlainDate/prototype/calendar/prop-desc.js | 17 + .../day/calendar-returns-infinity.js | 30 + .../PlainDate/prototype/day/prop-desc.js | 17 + .../PlainDate/prototype/dayOfWeek/basic.js | 16 + .../prototype/dayOfWeek/prop-desc.js | 17 + .../PlainDate/prototype/dayOfYear/basic.js | 16 + .../prototype/dayOfYear/prop-desc.js | 17 + .../prototype/daysInMonth/prop-desc.js | 17 + .../PlainDate/prototype/daysInWeek/basic.js | 14 + .../prototype/daysInWeek/prop-desc.js | 17 + .../prototype/daysInYear/prop-desc.js | 17 + .../equals/argument-object-invalid.js | 23 + .../prototype/equals/argument-object-valid.js | 19 + .../equals/argument-plaindatetime.js | 23 + .../equals/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + .../prototype/equals/argument-string.js | 18 + .../prototype/equals/argument-wrong-type.js | 20 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../PlainDate/prototype/equals/basic.js | 18 + .../PlainDate/prototype/equals/builtin.js | 36 + .../equals/calendar-call-different.js | 33 + .../prototype/equals/calendar-call-same.js | 33 + ...romfields-called-with-options-undefined.js | 19 + .../equals/calendar-fields-iterable.js | 36 + .../prototype/equals/calendar-no-call.js | 33 + .../equals/calendar-temporal-object.js | 29 + .../equals/infinity-throws-rangeerror.js | 26 + .../PlainDate/prototype/equals/length.js | 28 + .../PlainDate/prototype/equals/name.js | 26 + .../prototype/equals/not-a-constructor.js | 24 + .../PlainDate/prototype/equals/prop-desc.js | 24 + .../PlainDate/prototype/equals/shell.js | 19 + .../PlainDate/prototype/equals/year-zero.js | 20 + .../prototype/getISOFields/builtin.js | 36 + .../prototype/getISOFields/field-names.js | 19 + .../prototype/getISOFields/field-prop-desc.js | 30 + .../getISOFields/field-traversal-order.js | 24 + .../prototype/getISOFields/length.js | 28 + .../PlainDate/prototype/getISOFields/name.js | 26 + .../getISOFields/not-a-constructor.js | 24 + .../prototype/getISOFields/prop-desc.js | 24 + .../PlainDate/prototype/getISOFields/shell.js | 19 + .../prototype/inLeapYear/prop-desc.js | 17 + .../month/calendar-returns-infinity.js | 30 + .../PlainDate/prototype/month/prop-desc.js | 17 + .../prototype/monthCode/prop-desc.js | 17 + .../PlainDate/prototype/monthsInYear/basic.js | 14 + .../prototype/monthsInYear/prop-desc.js | 17 + .../Temporal/PlainDate/prototype/prop-desc.js | 21 + .../prototype/since/argument-plaindatetime.js | 24 + .../since/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../PlainDate/prototype/since/basic.js | 24 + .../PlainDate/prototype/since/builtin.js | 36 + ...-dateadd-called-with-plaindate-instance.js | 20 + ...romfields-called-with-options-undefined.js | 19 + ...euntil-called-with-singular-largestunit.js | 30 + .../since/calendar-fields-iterable.js | 36 + .../prototype/since/calendar-id-match.js | 33 + .../prototype/since/calendar-mismatch.js | 18 + .../since/calendar-temporal-object.js | 29 + .../prototype/since/days-in-month.js | 22 + .../PlainDate/prototype/since/days-in-year.js | 24 + .../since/infinity-throws-rangeerror.js | 26 + .../prototype/since/largestunit-default.js | 22 + .../since/largestunit-higher-units.js | 29 + .../since/largestunit-invalid-string.js | 18 + .../since/largestunit-plurals-accepted.js | 22 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/since/largestunit-undefined.js | 20 + .../prototype/since/largestunit-wrong-type.js | 19 + .../PlainDate/prototype/since/largestunit.js | 17 + .../PlainDate/prototype/since/length.js | 28 + .../PlainDate/prototype/since/name.js | 26 + .../prototype/since/not-a-constructor.js | 24 + .../prototype/since/options-invalid.js | 18 + .../PlainDate/prototype/since/prop-desc.js | 24 + .../prototype/since/rounding-relative.js | 37 + .../prototype/since/roundingincrement-nan.js | 22 + .../since/roundingincrement-non-integer.js | 20 + .../since/roundingincrement-out-of-range.js | 21 + .../since/roundingincrement-undefined.js | 27 + .../since/roundingincrement-wrong-type.js | 28 + .../prototype/since/roundingincrement.js | 31 + .../prototype/since/roundingmode-ceil.js | 43 + .../prototype/since/roundingmode-floor.js | 43 + .../since/roundingmode-halfExpand.js | 43 + .../since/roundingmode-invalid-string.js | 17 + .../prototype/since/roundingmode-trunc.js | 43 + .../prototype/since/roundingmode-undefined.js | 26 + .../since/roundingmode-wrong-type.js | 19 + .../PlainDate/prototype/since/shell.js | 19 + .../since/smallestunit-higher-units.js | 27 + .../since/smallestunit-invalid-string.js | 18 + .../since/smallestunit-plurals-accepted.js | 22 + .../prototype/since/smallestunit-undefined.js | 20 + .../since/smallestunit-wrong-type.js | 19 + .../PlainDate/prototype/since/weeks-months.js | 19 + .../PlainDate/prototype/since/year-zero.js | 20 + .../subtract/argument-invalid-duration.js | 19 + .../subtract/argument-missing-properties.js | 21 + .../prototype/subtract/argument-not-object.js | 20 + .../subtract/argument-singular-units.js | 16 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/subtract/argument-string.js | 16 + .../subtract/balance-smaller-units-basic.js | 32 + .../subtract/balance-smaller-units.js | 56 + .../PlainDate/prototype/subtract/basic.js | 32 + .../PlainDate/prototype/subtract/builtin.js | 36 + .../subtract/infinity-throws-rangeerror.js | 38 + .../PlainDate/prototype/subtract/length.js | 28 + .../PlainDate/prototype/subtract/limits.js | 18 + .../PlainDate/prototype/subtract/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 38 + .../subtract/non-integer-throws-rangeerror.js | 29 + .../prototype/subtract/not-a-constructor.js | 24 + .../prototype/subtract/options-invalid.js | 19 + .../prototype/subtract/options-undefined.js | 22 + .../prototype/subtract/order-of-operations.js | 77 + .../prototype/subtract/overflow-constrain.js | 18 + .../subtract/overflow-invalid-string.js | 32 + .../prototype/subtract/overflow-reject.js | 14 + .../prototype/subtract/overflow-undefined.js | 31 + .../prototype/subtract/overflow-wrong-type.js | 28 + .../PlainDate/prototype/subtract/prop-desc.js | 24 + .../PlainDate/prototype/subtract/shell.js | 19 + .../prototype/subtract/subclassing-ignored.js | 20 + .../PlainDate/prototype/toJSON/builtin.js | 36 + .../PlainDate/prototype/toJSON/length.js | 28 + .../PlainDate/prototype/toJSON/name.js | 26 + .../prototype/toJSON/not-a-constructor.js | 24 + .../PlainDate/prototype/toJSON/prop-desc.js | 24 + .../PlainDate/prototype/toJSON/shell.js | 19 + .../PlainDate/prototype/toJSON/year-format.js | 50 + .../prototype/toLocaleString/builtin.js | 36 + .../prototype/toLocaleString/length.js | 28 + .../prototype/toLocaleString/name.js | 26 + .../toLocaleString/not-a-constructor.js | 24 + .../prototype/toLocaleString/prop-desc.js | 24 + .../prototype/toLocaleString/return-string.js | 16 + .../prototype/toLocaleString/shell.js | 19 + .../argument-string-no-implicit-midnight.js | 19 + ...-designator-required-for-disambiguation.js | 56 + .../argument-string-with-time-designator.js | 32 + .../argument-string-with-utc-designator.js | 24 + ...neddatetime-balance-negative-time-units.js | 47 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/toPlainDateTime/basic.js | 29 + .../prototype/toPlainDateTime/builtin.js | 36 + .../calendar-temporal-object.js | 28 + .../prototype/toPlainDateTime/length.js | 28 + .../prototype/toPlainDateTime/name.js | 26 + .../toPlainDateTime/not-a-constructor.js | 24 + .../plaintime-propertybag-no-time-units.js | 21 + .../prototype/toPlainDateTime/prop-desc.js | 24 + .../prototype/toPlainDateTime/shell.js | 19 + .../prototype/toPlainDateTime/time-invalid.js | 15 + .../toPlainDateTime/time-undefined.js | 20 + .../prototype/toPlainDateTime/year-zero.js | 24 + .../prototype/toPlainMonthDay/builtin.js | 36 + .../toPlainMonthDay/calendar-arguments.js | 32 + .../calendar-fields-iterable.js | 30 + ...romfields-called-with-options-undefined.js | 19 + .../prototype/toPlainMonthDay/length.js | 28 + .../prototype/toPlainMonthDay/name.js | 26 + .../toPlainMonthDay/not-a-constructor.js | 24 + .../prototype/toPlainMonthDay/prop-desc.js | 24 + .../prototype/toPlainMonthDay/shell.js | 19 + .../prototype/toPlainYearMonth/builtin.js | 36 + .../toPlainYearMonth/calendar-arguments.js | 32 + .../calendar-fields-iterable.js | 30 + ...romfields-called-with-options-undefined.js | 19 + .../prototype/toPlainYearMonth/length.js | 28 + .../prototype/toPlainYearMonth/limits.js | 20 + .../prototype/toPlainYearMonth/name.js | 26 + .../toPlainYearMonth/not-a-constructor.js | 24 + .../prototype/toPlainYearMonth/prop-desc.js | 24 + .../prototype/toPlainYearMonth/shell.js | 19 + .../PlainDate/prototype/toString/basic.js | 20 + .../PlainDate/prototype/toString/builtin.js | 36 + .../prototype/toString/calendarname-always.js | 25 + .../prototype/toString/calendarname-auto.js | 25 + .../toString/calendarname-invalid-string.js | 25 + .../prototype/toString/calendarname-never.js | 25 + .../toString/calendarname-undefined.js | 35 + .../toString/calendarname-wrong-type.js | 29 + .../PlainDate/prototype/toString/length.js | 28 + .../PlainDate/prototype/toString/name.js | 26 + .../prototype/toString/not-a-constructor.js | 24 + .../prototype/toString/options-undefined.js | 28 + .../PlainDate/prototype/toString/prop-desc.js | 24 + .../PlainDate/prototype/toString/shell.js | 19 + .../prototype/toString/year-format.js | 50 + .../argument-string-no-implicit-midnight.js | 19 + ...-designator-required-for-disambiguation.js | 56 + .../argument-string-with-time-designator.js | 31 + .../argument-string-with-utc-designator.js | 24 + ...zoneddatetime-negative-epochnanoseconds.js | 25 + .../prototype/toZonedDateTime/basic.js | 33 + .../prototype/toZonedDateTime/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 20 + .../calendar-temporal-object.js | 28 + .../prototype/toZonedDateTime/length.js | 28 + .../prototype/toZonedDateTime/name.js | 26 + .../toZonedDateTime/not-a-constructor.js | 24 + ...neddatetime-balance-negative-time-units.js | 48 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../plaintime-propertybag-no-time-units.js | 20 + .../prototype/toZonedDateTime/prop-desc.js | 24 + .../prototype/toZonedDateTime/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 26 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + ...imezone-getpossibleinstantsfor-iterable.js | 45 + .../timezone-string-datetime.js | 47 + .../timezone-string-multiple-offsets.js | 19 + .../prototype/toZonedDateTime/year-zero.js | 24 + .../prototype/until/argument-plaindatetime.js | 24 + .../until/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../PlainDate/prototype/until/basic.js | 23 + .../PlainDate/prototype/until/builtin.js | 36 + ...-dateadd-called-with-plaindate-instance.js | 20 + ...romfields-called-with-options-undefined.js | 19 + ...euntil-called-with-singular-largestunit.js | 30 + .../until/calendar-fields-iterable.js | 36 + .../prototype/until/calendar-id-match.js | 33 + .../prototype/until/calendar-mismatch.js | 18 + .../until/calendar-temporal-object.js | 29 + .../prototype/until/days-in-month.js | 22 + .../PlainDate/prototype/until/days-in-year.js | 24 + .../until/infinity-throws-rangeerror.js | 26 + .../prototype/until/largestunit-default.js | 22 + .../until/largestunit-higher-units.js | 29 + .../until/largestunit-invalid-string.js | 18 + .../until/largestunit-plurals-accepted.js | 22 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/until/largestunit-undefined.js | 20 + .../prototype/until/largestunit-wrong-type.js | 19 + .../PlainDate/prototype/until/length.js | 28 + .../PlainDate/prototype/until/name.js | 26 + .../prototype/until/not-a-constructor.js | 24 + .../prototype/until/options-invalid.js | 18 + .../PlainDate/prototype/until/prop-desc.js | 24 + .../prototype/until/rounding-relative.js | 37 + .../prototype/until/roundingincrement-nan.js | 22 + .../until/roundingincrement-non-integer.js | 20 + .../until/roundingincrement-out-of-range.js | 21 + .../until/roundingincrement-undefined.js | 27 + .../until/roundingincrement-wrong-type.js | 28 + .../prototype/until/roundingincrement.js | 31 + .../prototype/until/roundingmode-ceil.js | 43 + .../prototype/until/roundingmode-floor.js | 43 + .../until/roundingmode-halfExpand.js | 43 + .../until/roundingmode-invalid-string.js | 17 + .../prototype/until/roundingmode-trunc.js | 43 + .../prototype/until/roundingmode-undefined.js | 26 + .../until/roundingmode-wrong-type.js | 19 + .../PlainDate/prototype/until/shell.js | 19 + .../until/smallestunit-higher-units.js | 27 + .../until/smallestunit-invalid-string.js | 18 + .../until/smallestunit-plurals-accepted.js | 22 + .../prototype/until/smallestunit-undefined.js | 20 + .../until/smallestunit-wrong-type.js | 19 + .../PlainDate/prototype/until/weeks-months.js | 19 + .../PlainDate/prototype/until/year-zero.js | 20 + .../PlainDate/prototype/valueOf/basic.js | 24 + .../PlainDate/prototype/valueOf/builtin.js | 36 + .../PlainDate/prototype/valueOf/length.js | 28 + .../PlainDate/prototype/valueOf/name.js | 26 + .../prototype/valueOf/not-a-constructor.js | 24 + .../PlainDate/prototype/valueOf/prop-desc.js | 24 + .../PlainDate/prototype/valueOf/shell.js | 19 + .../PlainDate/prototype/weekOfYear/basic.js | 37 + .../prototype/weekOfYear/prop-desc.js | 17 + .../PlainDate/prototype/with/basic.js | 31 + .../PlainDate/prototype/with/builtin.js | 36 + .../with/calendar-fields-iterable.js | 32 + ...calendar-merge-fields-returns-primitive.js | 21 + .../with/copies-merge-fields-object.js | 38 + .../with/copy-properties-not-undefined.js | 25 + .../with/infinity-throws-rangeerror.js | 27 + .../PlainDate/prototype/with/length.js | 28 + .../Temporal/PlainDate/prototype/with/name.js | 26 + .../prototype/with/not-a-constructor.js | 24 + .../prototype/with/options-invalid.js | 16 + .../prototype/with/options-undefined.js | 22 + .../prototype/with/order-of-operations.js | 55 + .../prototype/with/overflow-invalid-string.js | 31 + .../prototype/with/overflow-undefined.js | 29 + .../prototype/with/overflow-wrong-type.js | 27 + .../prototype/with/plaindatelike-invalid.js | 51 + .../PlainDate/prototype/with/prop-desc.js | 24 + .../PlainDate/prototype/with/shell.js | 19 + .../prototype/with/subclassing-ignored.js | 20 + .../PlainDate/prototype/withCalendar/basic.js | 23 + .../prototype/withCalendar/builtin.js | 36 + .../withCalendar/calendar-temporal-object.js | 24 + .../prototype/withCalendar/length.js | 28 + .../withCalendar/missing-argument.js | 15 + .../PlainDate/prototype/withCalendar/name.js | 26 + .../withCalendar/not-a-constructor.js | 24 + .../prototype/withCalendar/prop-desc.js | 24 + .../PlainDate/prototype/withCalendar/shell.js | 19 + .../withCalendar/subclassing-ignored.js | 33 + .../year/calendar-returns-infinity.js | 30 + .../PlainDate/prototype/year/prop-desc.js | 17 + .../built-ins/Temporal/PlainDate/shell.js | 1498 ++++++ .../Temporal/PlainDateTime/builtin.js | 30 + .../PlainDateTime/calendar-temporal-object.js | 25 + .../PlainDateTime/calendar-undefined.js | 25 + .../argument-object-insufficient-data.js | 26 + .../compare/argument-plaindate.js | 31 + .../argument-string-with-utc-designator.js | 29 + ...zoneddatetime-negative-epochnanoseconds.js | 28 + ...one-getoffsetnanosecondsfor-non-integer.js | 21 + ...ne-getoffsetnanosecondsfor-not-callable.js | 28 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 21 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 30 + .../Temporal/PlainDateTime/compare/basic.js | 32 + .../Temporal/PlainDateTime/compare/browser.js | 0 .../Temporal/PlainDateTime/compare/builtin.js | 33 + .../compare/calendar-fields-iterable.js | 47 + .../compare/calendar-temporal-object.js | 32 + .../Temporal/PlainDateTime/compare/cast.js | 38 + .../compare/infinity-throws-rangeerror.js | 33 + .../Temporal/PlainDateTime/compare/length.js | 28 + .../Temporal/PlainDateTime/compare/name.js | 26 + .../compare/not-a-constructor.js | 23 + .../PlainDateTime/compare/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 30 + .../Temporal/PlainDateTime/compare/shell.js | 19 + .../compare/use-internal-slots.js | 47 + .../PlainDateTime/compare/year-zero.js | 24 + .../PlainDateTime/constructor-full.js | 26 + .../Temporal/PlainDateTime/constructor.js | 15 + .../Temporal/PlainDateTime/datetime-math.js | 50 + .../PlainDateTime/from/argument-plaindate.js | 24 + .../argument-string-with-utc-designator.js | 23 + ...neddatetime-balance-negative-time-units.js | 46 + ...zoneddatetime-negative-epochnanoseconds.js | 25 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 21 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../Temporal/PlainDateTime/from/browser.js | 0 .../Temporal/PlainDateTime/from/builtin.js | 33 + .../from/calendar-fields-iterable.js | 39 + .../from/calendar-temporal-object.js | 29 + .../from/infinity-throws-rangeerror.js | 27 + .../Temporal/PlainDateTime/from/length.js | 28 + .../Temporal/PlainDateTime/from/name.js | 26 + .../PlainDateTime/from/not-a-constructor.js | 23 + .../PlainDateTime/from/options-undefined.js | 19 + .../PlainDateTime/from/order-of-operations.js | 75 + .../from/overflow-invalid-string.js | 47 + .../PlainDateTime/from/overflow-undefined.js | 48 + .../PlainDateTime/from/overflow-wrong-type.js | 66 + .../Temporal/PlainDateTime/from/parser.js | 15 + .../Temporal/PlainDateTime/from/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 30 + .../Temporal/PlainDateTime/from/shell.js | 19 + .../PlainDateTime/from/subclassing-ignored.js | 19 + .../Temporal/PlainDateTime/from/year-zero.js | 23 + .../Temporal/PlainDateTime/hour-undefined.js | 26 + .../infinity-throws-rangeerror.js | 165 + .../Temporal/PlainDateTime/length.js | 28 + .../PlainDateTime/microsecond-undefined.js | 27 + .../PlainDateTime/millisecond-undefined.js | 26 + .../PlainDateTime/minute-undefined.js | 26 + .../PlainDateTime/missing-arguments.js | 25 + .../built-ins/Temporal/PlainDateTime/name.js | 26 + .../PlainDateTime/nanosecond-undefined.js | 26 + .../negative-infinity-throws-rangeerror.js | 165 + .../PlainDateTime/order-of-operations.js | 42 + .../Temporal/PlainDateTime/prop-desc.js | 24 + .../prototype/add/ambiguous-date.js | 32 + .../prototype/add/argument-duration.js | 20 + .../prototype/add/argument-not-object.js | 20 + .../add/argument-object-insufficient-data.js | 38 + .../add/argument-plain-object-mixed-signs.js | 21 + ...t-string-fractional-units-rounding-mode.js | 19 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/add/argument-string.js | 16 + .../add/balance-negative-time-units.js | 52 + .../PlainDateTime/prototype/add/builtin.js | 36 + .../prototype/add/hour-overflow.js | 28 + .../add/infinity-throws-rangeerror.js | 38 + .../PlainDateTime/prototype/add/length.js | 28 + .../PlainDateTime/prototype/add/name.js | 26 + .../prototype/add/negative-duration.js | 26 + .../negative-infinity-throws-rangeerror.js | 38 + .../add/non-integer-throws-rangeerror.js | 29 + .../prototype/add/not-a-constructor.js | 24 + .../prototype/add/options-empty.js | 26 + .../prototype/add/options-invalid.js | 23 + .../prototype/add/options-undefined.js | 22 + .../prototype/add/order-of-operations.js | 77 + .../prototype/add/overflow-invalid-string.js | 35 + .../prototype/add/overflow-undefined.js | 31 + .../prototype/add/overflow-wrong-type.js | 30 + .../PlainDateTime/prototype/add/prop-desc.js | 24 + .../PlainDateTime/prototype/add/shell.js | 19 + .../prototype/add/subclassing-ignored.js | 20 + .../prototype/calendar/prop-desc.js | 17 + .../day/calendar-returns-infinity.js | 30 + .../PlainDateTime/prototype/day/prop-desc.js | 17 + .../prototype/dayOfWeek/basic.js | 15 + .../prototype/dayOfWeek/prop-desc.js | 17 + .../prototype/dayOfYear/basic.js | 15 + .../prototype/dayOfYear/prop-desc.js | 17 + .../prototype/daysInMonth/basic.js | 15 + .../prototype/daysInMonth/prop-desc.js | 17 + .../prototype/daysInWeek/basic.js | 15 + .../prototype/daysInWeek/prop-desc.js | 17 + .../prototype/daysInYear/basic.js | 15 + .../prototype/daysInYear/prop-desc.js | 17 + .../argument-object-insufficient-data.js | 19 + .../prototype/equals/argument-plaindate.js | 23 + .../argument-string-with-utc-designator.js | 24 + .../prototype/equals/argument-wrong-type.js | 23 + ...neddatetime-balance-negative-time-units.js | 43 + ...zoneddatetime-negative-epochnanoseconds.js | 25 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../PlainDateTime/prototype/equals/basic.js | 17 + .../PlainDateTime/prototype/equals/builtin.js | 36 + .../equals/calendar-fields-iterable.js | 42 + .../equals/calendar-temporal-object.js | 29 + .../PlainDateTime/prototype/equals/cast.js | 49 + .../equals/infinity-throws-rangeerror.js | 26 + .../PlainDateTime/prototype/equals/length.js | 28 + .../PlainDateTime/prototype/equals/name.js | 26 + .../prototype/equals/not-a-constructor.js | 24 + .../prototype/equals/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 26 + .../PlainDateTime/prototype/equals/shell.js | 19 + .../prototype/equals/year-zero.js | 24 + .../prototype/getISOFields/builtin.js | 36 + .../prototype/getISOFields/field-names.js | 25 + .../prototype/getISOFields/field-prop-desc.js | 36 + .../getISOFields/field-traversal-order.js | 30 + .../prototype/getISOFields/length.js | 28 + .../prototype/getISOFields/name.js | 26 + .../getISOFields/not-a-constructor.js | 24 + .../prototype/getISOFields/prop-desc.js | 24 + .../prototype/getISOFields/shell.js | 19 + .../PlainDateTime/prototype/hour/prop-desc.js | 17 + .../prototype/inLeapYear/prop-desc.js | 17 + .../prototype/microsecond/prop-desc.js | 17 + .../prototype/millisecond/prop-desc.js | 17 + .../prototype/minute/prop-desc.js | 17 + .../month/calendar-returns-infinity.js | 30 + .../prototype/month/prop-desc.js | 17 + .../prototype/monthCode/prop-desc.js | 17 + .../prototype/monthsInYear/basic.js | 15 + .../prototype/monthsInYear/prop-desc.js | 17 + .../prototype/nanosecond/prop-desc.js | 17 + .../PlainDateTime/prototype/prop-desc.js | 21 + .../PlainDateTime/prototype/round/builtin.js | 36 + .../PlainDateTime/prototype/round/length.js | 28 + .../PlainDateTime/prototype/round/name.js | 26 + .../prototype/round/not-a-constructor.js | 24 + .../prototype/round/prop-desc.js | 24 + .../prototype/round/roundingincrement-nan.js | 23 + .../round/roundingincrement-non-integer.js | 19 + .../round/roundingincrement-out-of-range.js | 20 + .../round/roundingincrement-undefined.js | 29 + .../round/roundingincrement-wrong-type.js | 29 + .../round/roundingmode-invalid-string.js | 16 + .../prototype/round/roundingmode-undefined.js | 29 + .../round/roundingmode-wrong-type.js | 18 + .../PlainDateTime/prototype/round/shell.js | 19 + .../round/smallestunit-disallowed-units.js | 35 + .../round/smallestunit-invalid-string.js | 14 + .../round/smallestunit-plurals-accepted.js | 25 + .../round/smallestunit-string-shorthand.js | 28 + .../round/smallestunit-wrong-type.js | 18 + .../prototype/round/subclassing-ignored.js | 20 + .../prototype/second/prop-desc.js | 17 + .../prototype/since/argument-plaindate.js | 24 + .../argument-string-with-utc-designator.js | 24 + ...neddatetime-balance-negative-time-units.js | 46 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../since/balance-negative-duration.js | 37 + .../since/balance-negative-time-units.js | 53 + .../PlainDateTime/prototype/since/builtin.js | 36 + ...-dateadd-called-with-plaindate-instance.js | 19 + ...r-dateuntil-called-with-copy-of-options.js | 35 + ...ateuntil-called-with-plaindate-calendar.js | 34 + ...euntil-called-with-singular-largestunit.js | 39 + .../since/calendar-fields-iterable.js | 42 + .../since/calendar-temporal-object.js | 29 + .../since/infinity-throws-rangeerror.js | 26 + .../since/largestunit-invalid-string.js | 18 + .../since/largestunit-plurals-accepted.js | 28 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/since/largestunit-undefined.js | 20 + .../prototype/since/largestunit-wrong-type.js | 19 + .../prototype/since/largestunit.js | 17 + .../PlainDateTime/prototype/since/length.js | 28 + .../PlainDateTime/prototype/since/name.js | 26 + .../prototype/since/not-a-constructor.js | 24 + .../prototype/since/options-undefined.js | 28 + .../prototype/since/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 26 + .../since/round-negative-duration.js | 27 + .../prototype/since/roundingincrement-nan.js | 22 + .../since/roundingincrement-non-integer.js | 20 + .../since/roundingincrement-out-of-range.js | 21 + .../since/roundingincrement-undefined.js | 28 + .../since/roundingincrement-wrong-type.js | 28 + .../since/roundingmode-invalid-string.js | 17 + .../prototype/since/roundingmode-undefined.js | 30 + .../since/roundingmode-wrong-type.js | 19 + .../PlainDateTime/prototype/since/shell.js | 19 + .../since/smallestunit-invalid-string.js | 18 + .../since/smallestunit-plurals-accepted.js | 28 + .../prototype/since/smallestunit-undefined.js | 20 + .../since/smallestunit-wrong-type.js | 19 + .../prototype/since/year-zero.js | 24 + .../prototype/subtract/ambiguous-date.js | 32 + .../prototype/subtract/argument-duration.js | 21 + .../prototype/subtract/argument-not-object.js | 20 + .../argument-object-insufficient-data.js | 38 + .../argument-plain-object-mixed-signs.js | 21 + ...t-string-fractional-units-rounding-mode.js | 19 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/subtract/argument-string.js | 16 + .../subtract/balance-negative-time-units.js | 52 + .../prototype/subtract/builtin.js | 36 + .../prototype/subtract/hour-overflow.js | 33 + .../subtract/infinity-throws-rangeerror.js | 38 + .../prototype/subtract/length.js | 28 + .../PlainDateTime/prototype/subtract/name.js | 26 + .../prototype/subtract/negative-duration.js | 26 + .../negative-infinity-throws-rangeerror.js | 38 + .../subtract/non-integer-throws-rangeerror.js | 29 + .../prototype/subtract/not-a-constructor.js | 24 + .../prototype/subtract/options-empty.js | 26 + .../prototype/subtract/options-invalid.js | 23 + .../prototype/subtract/options-undefined.js | 22 + .../prototype/subtract/order-of-operations.js | 77 + .../subtract/overflow-invalid-string.js | 33 + .../prototype/subtract/overflow-undefined.js | 31 + .../prototype/subtract/overflow-wrong-type.js | 30 + .../prototype/subtract/prop-desc.js | 24 + .../PlainDateTime/prototype/subtract/shell.js | 19 + .../prototype/subtract/subclassing-ignored.js | 20 + .../PlainDateTime/prototype/toJSON/builtin.js | 36 + .../PlainDateTime/prototype/toJSON/length.js | 28 + .../PlainDateTime/prototype/toJSON/name.js | 26 + .../prototype/toJSON/not-a-constructor.js | 24 + .../prototype/toJSON/prop-desc.js | 24 + .../PlainDateTime/prototype/toJSON/shell.js | 19 + .../prototype/toJSON/year-format.js | 50 + .../prototype/toLocaleString/builtin.js | 36 + .../prototype/toLocaleString/length.js | 28 + .../prototype/toLocaleString/name.js | 26 + .../toLocaleString/not-a-constructor.js | 24 + .../prototype/toLocaleString/prop-desc.js | 24 + .../prototype/toLocaleString/return-string.js | 17 + .../prototype/toLocaleString/shell.js | 19 + .../prototype/toPlainDate/builtin.js | 36 + .../prototype/toPlainDate/length.js | 28 + .../prototype/toPlainDate/limits.js | 21 + .../prototype/toPlainDate/name.js | 26 + .../toPlainDate/not-a-constructor.js | 24 + .../prototype/toPlainDate/prop-desc.js | 24 + .../prototype/toPlainDate/shell.js | 19 + .../prototype/toPlainMonthDay/builtin.js | 36 + .../toPlainMonthDay/calendar-arguments.js | 32 + .../calendar-fields-iterable.js | 30 + ...romfields-called-with-options-undefined.js | 19 + .../prototype/toPlainMonthDay/length.js | 28 + .../prototype/toPlainMonthDay/name.js | 26 + .../toPlainMonthDay/not-a-constructor.js | 24 + .../prototype/toPlainMonthDay/prop-desc.js | 24 + .../prototype/toPlainMonthDay/shell.js | 19 + .../prototype/toPlainTime/basic.js | 15 + .../prototype/toPlainTime/builtin.js | 36 + .../prototype/toPlainTime/length.js | 28 + .../prototype/toPlainTime/name.js | 26 + .../toPlainTime/not-a-constructor.js | 24 + .../prototype/toPlainTime/prop-desc.js | 24 + .../prototype/toPlainTime/shell.js | 19 + .../prototype/toPlainYearMonth/builtin.js | 36 + .../toPlainYearMonth/calendar-arguments.js | 32 + .../calendar-fields-iterable.js | 30 + ...romfields-called-with-options-undefined.js | 19 + .../prototype/toPlainYearMonth/length.js | 28 + .../prototype/toPlainYearMonth/name.js | 26 + .../toPlainYearMonth/not-a-constructor.js | 24 + .../prototype/toPlainYearMonth/prop-desc.js | 24 + .../prototype/toPlainYearMonth/shell.js | 19 + .../PlainDateTime/prototype/toString/basic.js | 16 + .../prototype/toString/builtin.js | 36 + .../toString/calendarname-invalid-string.js | 21 + .../toString/calendarname-undefined.js | 34 + .../toString/calendarname-wrong-type.js | 29 + .../fractionalseconddigits-invalid-string.js | 22 + .../toString/fractionalseconddigits-nan.js | 23 + .../fractionalseconddigits-non-integer.js | 23 + .../fractionalseconddigits-out-of-range.js | 23 + .../fractionalseconddigits-undefined.js | 27 + .../fractionalseconddigits-wrong-type.js | 28 + .../prototype/toString/length.js | 28 + .../PlainDateTime/prototype/toString/name.js | 26 + .../prototype/toString/not-a-constructor.js | 24 + .../prototype/toString/options-undefined.js | 31 + .../prototype/toString/prop-desc.js | 24 + .../toString/roundingmode-invalid-string.js | 16 + .../toString/roundingmode-undefined.js | 28 + .../toString/roundingmode-wrong-type.js | 18 + .../PlainDateTime/prototype/toString/shell.js | 19 + .../toString/smallestunit-invalid-string.js | 14 + .../toString/smallestunit-plurals-accepted.js | 22 + .../toString/smallestunit-undefined.js | 23 + .../toString/smallestunit-valid-units.js | 31 + .../toString/smallestunit-wrong-type.js | 18 + .../prototype/toString/year-format.js | 50 + .../balance-negative-time-units.js | 48 + .../prototype/toZonedDateTime/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 25 + .../disambiguation-invalid-string.js | 22 + .../disambiguation-undefined.js | 33 + .../disambiguation-wrong-type.js | 26 + .../prototype/toZonedDateTime/length.js | 28 + .../prototype/toZonedDateTime/name.js | 26 + .../toZonedDateTime/not-a-constructor.js | 24 + .../toZonedDateTime/options-undefined.js | 27 + .../toZonedDateTime/plain-custom-timezone.js | 69 + .../prototype/toZonedDateTime/prop-desc.js | 24 + .../prototype/toZonedDateTime/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 25 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + ...imezone-getpossibleinstantsfor-iterable.js | 45 + .../timezone-string-datetime.js | 47 + .../timezone-string-multiple-offsets.js | 19 + .../prototype/until/argument-plaindate.js | 24 + .../argument-string-with-utc-designator.js | 24 + ...neddatetime-balance-negative-time-units.js | 46 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../until/balance-negative-duration.js | 37 + .../until/balance-negative-time-units.js | 53 + .../PlainDateTime/prototype/until/balance.js | 28 + .../PlainDateTime/prototype/until/builtin.js | 36 + ...-dateadd-called-with-plaindate-instance.js | 19 + ...r-dateuntil-called-with-copy-of-options.js | 35 + ...ateuntil-called-with-plaindate-calendar.js | 34 + ...euntil-called-with-singular-largestunit.js | 39 + .../until/calendar-fields-iterable.js | 42 + .../until/calendar-temporal-object.js | 29 + .../prototype/until/casts-argument.js | 26 + .../until/different-calendars-throws.js | 25 + .../until/infinity-throws-rangeerror.js | 26 + .../PlainDateTime/prototype/until/inverse.js | 17 + .../until/largestunit-invalid-string.js | 18 + .../until/largestunit-plurals-accepted.js | 28 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/until/largestunit-undefined.js | 20 + .../prototype/until/largestunit-wrong-type.js | 19 + .../PlainDateTime/prototype/until/length.js | 28 + .../PlainDateTime/prototype/until/name.js | 26 + .../prototype/until/no-unnecessary-units.js | 27 + .../prototype/until/not-a-constructor.js | 24 + .../prototype/until/options-undefined.js | 28 + .../prototype/until/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 26 + .../prototype/until/returns-days.js | 41 + .../until/round-negative-duration.js | 27 + .../prototype/until/roundingincrement-nan.js | 22 + .../until/roundingincrement-non-integer.js | 20 + .../until/roundingincrement-out-of-range.js | 21 + .../until/roundingincrement-undefined.js | 28 + .../until/roundingincrement-wrong-type.js | 28 + .../until/roundingmode-invalid-string.js | 17 + .../prototype/until/roundingmode-undefined.js | 30 + .../until/roundingmode-wrong-type.js | 19 + .../PlainDateTime/prototype/until/shell.js | 19 + .../until/smallestunit-invalid-string.js | 18 + .../until/smallestunit-plurals-accepted.js | 28 + .../prototype/until/smallestunit-undefined.js | 20 + .../until/smallestunit-wrong-type.js | 19 + .../prototype/until/subseconds.js | 39 + .../prototype/until/units-changed.js | 69 + .../until/weeks-months-mutually-exclusive.js | 27 + .../prototype/until/year-zero.js | 24 + .../PlainDateTime/prototype/valueOf/basic.js | 26 + .../prototype/valueOf/builtin.js | 36 + .../PlainDateTime/prototype/valueOf/length.js | 28 + .../PlainDateTime/prototype/valueOf/name.js | 26 + .../prototype/valueOf/not-a-constructor.js | 24 + .../prototype/valueOf/prop-desc.js | 24 + .../PlainDateTime/prototype/valueOf/shell.js | 19 + .../prototype/weekOfYear/basic.js | 15 + .../prototype/weekOfYear/prop-desc.js | 17 + .../with/argument-object-insufficient-data.js | 45 + .../PlainDateTime/prototype/with/basic.js | 80 + .../PlainDateTime/prototype/with/builtin.js | 36 + .../with/calendar-fields-iterable.js | 38 + ...calendar-merge-fields-returns-primitive.js | 21 + .../prototype/with/calendar-throws.js | 19 + .../with/copies-merge-fields-object.js | 58 + .../with/copy-properties-not-undefined.js | 25 + .../with/infinity-throws-rangeerror.js | 27 + .../PlainDateTime/prototype/with/length.js | 28 + .../with/month-and-monthcode-must-agree.js | 19 + ...ultiple-unrecognized-properties-ignored.js | 26 + .../PlainDateTime/prototype/with/name.js | 26 + .../prototype/with/not-a-constructor.js | 24 + .../prototype/with/options-empty.js | 26 + .../prototype/with/options-invalid.js | 23 + .../prototype/with/options-undefined.js | 22 + .../prototype/with/order-of-operations.js | 79 + .../prototype/with/overflow-invalid-string.js | 32 + .../prototype/with/overflow-undefined.js | 28 + .../prototype/with/overflow-wrong-type.js | 49 + .../PlainDateTime/prototype/with/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 29 + .../PlainDateTime/prototype/with/shell.js | 19 + .../prototype/with/string-throws.js | 23 + .../prototype/with/subclassing-ignored.js | 20 + .../prototype/with/timezone-throws.js | 19 + .../prototype/withCalendar/builtin.js | 36 + .../withCalendar/calendar-temporal-object.js | 24 + .../prototype/withCalendar/length.js | 28 + .../withCalendar/missing-argument.js | 15 + .../prototype/withCalendar/name.js | 26 + .../withCalendar/not-a-constructor.js | 24 + .../prototype/withCalendar/prop-desc.js | 24 + .../prototype/withCalendar/shell.js | 19 + .../withCalendar/subclassing-ignored.js | 33 + .../argument-object-insuffcient-data.js | 38 + .../withPlainDate/argument-object.js | 20 + .../withPlainDate/argument-plaindate.js | 21 + .../withPlainDate/argument-plaindatetime.js | 24 + .../withPlainDate/argument-string-invalid.js | 64 + .../argument-string-iso-calendar.js | 39 + .../argument-string-with-utc-designator.js | 24 + .../withPlainDate/argument-string.js | 20 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/withPlainDate/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 19 + .../withPlainDate/calendar-fields-iterable.js | 36 + .../withPlainDate/calendar-temporal-object.js | 31 + .../infinity-throws-rangeerror.js | 26 + .../prototype/withPlainDate/length.js | 28 + .../prototype/withPlainDate/name.js | 26 + .../non-compatible-calendars-throw.js | 31 + .../withPlainDate/not-a-constructor.js | 24 + .../prototype/withPlainDate/prop-desc.js | 24 + .../prototype/withPlainDate/shell.js | 19 + .../withPlainDate/subclassing-ignored.js | 20 + .../prototype/withPlainDate/year-zero.js | 20 + .../argument-object-insufficient-data.js | 38 + .../argument-string-no-implicit-midnight.js | 19 + ...-designator-required-for-disambiguation.js | 56 + .../argument-string-with-time-designator.js | 32 + .../argument-string-with-utc-designator.js | 24 + ...argument-string-without-time-designator.js | 20 + .../prototype/withPlainTime/argument-time.js | 32 + ...neddatetime-balance-negative-time-units.js | 47 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/withPlainTime/builtin.js | 36 + .../withPlainTime/calendar-temporal-object.js | 28 + .../prototype/withPlainTime/length.js | 28 + .../prototype/withPlainTime/name.js | 26 + .../no-argument-default-to-midnight.js | 20 + .../withPlainTime/not-a-constructor.js | 24 + .../plaintime-propertybag-no-time-units.js | 21 + .../prototype/withPlainTime/prop-desc.js | 24 + .../prototype/withPlainTime/shell.js | 19 + .../withPlainTime/subclassing-ignored.js | 20 + .../prototype/withPlainTime/time-undefined.js | 29 + .../prototype/withPlainTime/year-zero.js | 24 + .../year/calendar-returns-infinity.js | 30 + .../PlainDateTime/prototype/year/prop-desc.js | 17 + .../PlainDateTime/second-undefined.js | 26 + .../built-ins/Temporal/PlainDateTime/shell.js | 1498 ++++++ .../built-ins/Temporal/PlainMonthDay/basic.js | 24 + .../Temporal/PlainMonthDay/builtin.js | 30 + .../Temporal/PlainMonthDay/calendar-always.js | 27 + .../PlainMonthDay/calendar-invalid.js | 23 + .../PlainMonthDay/calendar-temporal-object.js | 25 + .../PlainMonthDay/calendar-undefined.js | 25 + .../Temporal/PlainMonthDay/constructor.js | 15 + .../argument-string-with-utc-designator.js | 23 + .../Temporal/PlainMonthDay/from/browser.js | 0 .../Temporal/PlainMonthDay/from/builtin.js | 33 + .../from/calendar-fields-iterable.js | 33 + ...romfields-called-with-options-undefined.js | 26 + .../from/calendar-temporal-object.js | 29 + .../PlainMonthDay/from/fields-leap-day.js | 42 + .../from/fields-missing-properties.js | 18 + .../PlainMonthDay/from/fields-object.js | 29 + .../from/fields-plainmonthday.js | 30 + .../PlainMonthDay/from/fields-string.js | 49 + .../from/infinity-throws-rangeerror.js | 27 + .../Temporal/PlainMonthDay/from/length.js | 28 + .../Temporal/PlainMonthDay/from/name.js | 26 + .../PlainMonthDay/from/not-a-constructor.js | 23 + .../PlainMonthDay/from/options-invalid.js | 18 + .../PlainMonthDay/from/options-undefined.js | 20 + .../PlainMonthDay/from/order-of-operations.js | 51 + .../from/overflow-invalid-string.js | 43 + .../PlainMonthDay/from/overflow-undefined.js | 48 + .../PlainMonthDay/from/overflow-wrong-type.js | 37 + .../Temporal/PlainMonthDay/from/overflow.js | 41 + .../Temporal/PlainMonthDay/from/prop-desc.js | 24 + .../Temporal/PlainMonthDay/from/shell.js | 19 + .../PlainMonthDay/from/subclassing-ignored.js | 19 + .../Temporal/PlainMonthDay/from/year-zero.js | 25 + .../infinity-throws-rangeerror.js | 44 + .../Temporal/PlainMonthDay/length.js | 28 + .../PlainMonthDay/missing-arguments.js | 24 + .../built-ins/Temporal/PlainMonthDay/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 44 + .../Temporal/PlainMonthDay/prop-desc.js | 24 + .../prototype/calendar/prop-desc.js | 17 + .../PlainMonthDay/prototype/day/basic.js | 14 + .../day/calendar-returns-infinity.js | 30 + .../PlainMonthDay/prototype/day/prop-desc.js | 17 + .../argument-string-with-utc-designator.js | 24 + .../prototype/equals/argument-wrong-type.js | 23 + .../PlainMonthDay/prototype/equals/basic.js | 28 + .../PlainMonthDay/prototype/equals/builtin.js | 36 + .../equals/calendar-fields-iterable.js | 36 + ...romfields-called-with-options-undefined.js | 36 + .../equals/calendar-temporal-object.js | 29 + .../prototype/equals/calendars.js | 33 + .../equals/infinity-throws-rangeerror.js | 26 + .../PlainMonthDay/prototype/equals/length.js | 28 + .../PlainMonthDay/prototype/equals/name.js | 26 + .../prototype/equals/not-a-constructor.js | 24 + .../prototype/equals/prop-desc.js | 24 + .../PlainMonthDay/prototype/equals/shell.js | 19 + .../prototype/equals/year-zero.js | 26 + .../prototype/getISOFields/builtin.js | 36 + .../prototype/getISOFields/field-names.js | 19 + .../prototype/getISOFields/field-prop-desc.js | 30 + .../getISOFields/field-traversal-order.js | 24 + .../prototype/getISOFields/length.js | 28 + .../prototype/getISOFields/name.js | 26 + .../getISOFields/not-a-constructor.js | 24 + .../prototype/getISOFields/prop-desc.js | 24 + .../prototype/getISOFields/shell.js | 19 + .../PlainMonthDay/prototype/month/browser.js | 0 .../PlainMonthDay/prototype/month/shell.js | 0 .../prototype/month/unsupported.js | 15 + .../prototype/monthCode/basic.js | 14 + .../prototype/monthCode/prop-desc.js | 17 + .../PlainMonthDay/prototype/prop-desc.js | 21 + .../PlainMonthDay/prototype/toJSON/builtin.js | 36 + .../prototype/toJSON/calendarname.js | 31 + .../PlainMonthDay/prototype/toJSON/length.js | 28 + .../PlainMonthDay/prototype/toJSON/name.js | 26 + .../prototype/toJSON/not-a-constructor.js | 24 + .../prototype/toJSON/prop-desc.js | 24 + .../PlainMonthDay/prototype/toJSON/shell.js | 19 + .../prototype/toJSON/year-format.js | 58 + .../prototype/toLocaleString/builtin.js | 36 + .../prototype/toLocaleString/length.js | 28 + .../prototype/toLocaleString/name.js | 26 + .../toLocaleString/not-a-constructor.js | 24 + .../prototype/toLocaleString/prop-desc.js | 24 + .../prototype/toLocaleString/shell.js | 19 + .../toPlainDate/argument-not-object.js | 18 + .../prototype/toPlainDate/basic.js | 30 + .../prototype/toPlainDate/builtin.js | 36 + .../toPlainDate/calendar-fields-iterable.js | 37 + ...calendar-merge-fields-returns-primitive.js | 21 + .../toPlainDate/copies-merge-fields-object.js | 34 + .../toPlainDate/infinity-throws-rangeerror.js | 23 + .../prototype/toPlainDate/length.js | 28 + .../prototype/toPlainDate/limits.js | 33 + .../prototype/toPlainDate/name.js | 26 + .../toPlainDate/not-a-constructor.js | 24 + .../prototype/toPlainDate/prop-desc.js | 24 + .../prototype/toPlainDate/shell.js | 19 + .../prototype/toString/builtin.js | 36 + .../prototype/toString/calendarname-always.js | 25 + .../prototype/toString/calendarname-auto.js | 25 + .../toString/calendarname-invalid-string.js | 23 + .../prototype/toString/calendarname-never.js | 25 + .../toString/calendarname-undefined.js | 35 + .../toString/calendarname-wrong-type.js | 29 + .../prototype/toString/length.js | 28 + .../PlainMonthDay/prototype/toString/name.js | 26 + .../prototype/toString/not-a-constructor.js | 24 + .../prototype/toString/options-undefined.js | 28 + .../prototype/toString/prop-desc.js | 24 + .../PlainMonthDay/prototype/toString/shell.js | 19 + .../prototype/toString/year-format.js | 58 + .../PlainMonthDay/prototype/valueOf/basic.js | 24 + .../prototype/valueOf/builtin.js | 36 + .../PlainMonthDay/prototype/valueOf/length.js | 28 + .../PlainMonthDay/prototype/valueOf/name.js | 26 + .../prototype/valueOf/not-a-constructor.js | 24 + .../prototype/valueOf/prop-desc.js | 24 + .../PlainMonthDay/prototype/valueOf/shell.js | 19 + .../PlainMonthDay/prototype/with/basic.js | 43 + .../PlainMonthDay/prototype/with/builtin.js | 36 + .../prototype/with/calendar-arguments.js | 32 + .../with/calendar-fields-iterable.js | 32 + ...calendar-merge-fields-returns-primitive.js | 21 + .../with/copies-merge-fields-object.js | 34 + .../with/copy-properties-not-undefined.js | 25 + .../with/infinity-throws-rangeerror.js | 25 + .../PlainMonthDay/prototype/with/length.js | 28 + .../PlainMonthDay/prototype/with/name.js | 26 + .../prototype/with/not-a-constructor.js | 24 + .../prototype/with/options-invalid.js | 16 + .../prototype/with/options-undefined.js | 20 + .../prototype/with/order-of-operations.js | 54 + .../prototype/with/overflow-invalid-string.js | 31 + .../prototype/with/overflow-undefined.js | 29 + .../prototype/with/overflow-wrong-type.js | 27 + .../PlainMonthDay/prototype/with/prop-desc.js | 24 + .../PlainMonthDay/prototype/with/shell.js | 19 + .../prototype/with/subclassing-ignored.js | 20 + .../PlainMonthDay/refisoyear-undefined.js | 20 + .../built-ins/Temporal/PlainMonthDay/shell.js | 1498 ++++++ .../built-ins/Temporal/PlainTime/basic.js | 17 + .../built-ins/Temporal/PlainTime/builtin.js | 30 + .../PlainTime/compare/argument-cast.js | 22 + .../argument-string-no-implicit-midnight.js | 24 + ...-designator-required-for-disambiguation.js | 70 + .../argument-string-with-time-designator.js | 31 + .../argument-string-with-utc-designator.js | 29 + ...zoneddatetime-negative-epochnanoseconds.js | 28 + ...one-getoffsetnanosecondsfor-non-integer.js | 21 + ...ne-getoffsetnanosecondsfor-not-callable.js | 28 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 21 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 30 + .../Temporal/PlainTime/compare/basic.js | 20 + .../Temporal/PlainTime/compare/browser.js | 0 .../Temporal/PlainTime/compare/builtin.js | 33 + .../compare/calendar-temporal-object.js | 30 + .../Temporal/PlainTime/compare/length.js | 28 + .../Temporal/PlainTime/compare/name.js | 26 + .../PlainTime/compare/not-a-constructor.js | 23 + .../plaintime-propertybag-no-time-units.js | 18 + .../Temporal/PlainTime/compare/prop-desc.js | 24 + .../Temporal/PlainTime/compare/shell.js | 19 + .../PlainTime/compare/use-internal-slots.js | 38 + .../Temporal/PlainTime/compare/year-zero.js | 26 + .../Temporal/PlainTime/constructor.js | 15 + .../PlainTime/from/argument-number.js | 15 + .../from/argument-object-leap-second.js | 26 + .../PlainTime/from/argument-object.js | 24 + .../PlainTime/from/argument-plaindatetime.js | 17 + .../PlainTime/from/argument-plaintime.js | 17 + .../from/argument-string-leap-second.js | 21 + .../argument-string-no-implicit-midnight.js | 18 + ...-designator-required-for-disambiguation.js | 54 + .../from/argument-string-trailing-junk.js | 14 + .../from/argument-string-with-calendar.js | 38 + .../argument-string-with-time-designator.js | 31 + .../argument-string-with-utc-designator.js | 23 + .../PlainTime/from/argument-string.js | 60 + ...neddatetime-balance-negative-time-units.js | 46 + ...zoneddatetime-negative-epochnanoseconds.js | 25 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 21 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../Temporal/PlainTime/from/browser.js | 0 .../Temporal/PlainTime/from/builtin.js | 33 + .../from/calendar-temporal-object.js | 27 + .../from/infinity-throws-rangeerror.js | 27 + .../Temporal/PlainTime/from/length.js | 28 + .../built-ins/Temporal/PlainTime/from/name.js | 26 + .../PlainTime/from/not-a-constructor.js | 23 + ...le-get-overflow-argument-string-invalid.js | 29 + .../PlainTime/from/options-invalid.js | 17 + .../PlainTime/from/options-undefined.js | 19 + .../PlainTime/from/order-of-operations.js | 59 + .../PlainTime/from/overflow-constrain.js | 17 + .../PlainTime/from/overflow-invalid-string.js | 35 + .../PlainTime/from/overflow-reject.js | 16 + .../PlainTime/from/overflow-undefined.js | 40 + .../PlainTime/from/overflow-wrong-type.js | 29 + .../plaintime-propertybag-no-time-units.js | 19 + .../Temporal/PlainTime/from/prop-desc.js | 24 + .../Temporal/PlainTime/from/shell.js | 19 + .../PlainTime/from/subclassing-ignored.js | 19 + .../Temporal/PlainTime/from/year-zero.js | 23 + .../Temporal/PlainTime/hour-undefined.js | 18 + .../PlainTime/infinity-throws-rangeerror.js | 60 + .../built-ins/Temporal/PlainTime/length.js | 28 + .../PlainTime/microsecond-undefined.js | 20 + .../PlainTime/millisecond-undefined.js | 20 + .../Temporal/PlainTime/minute-undefined.js | 20 + .../built-ins/Temporal/PlainTime/name.js | 26 + .../PlainTime/nanosecond-undefined.js | 20 + .../negative-infinity-throws-rangeerror.js | 60 + .../Temporal/PlainTime/negative-zero.js | 15 + .../built-ins/Temporal/PlainTime/prop-desc.js | 24 + .../prototype/add/argument-duration.js | 17 + .../prototype/add/argument-higher-units.js | 32 + .../prototype/add/argument-not-object.js | 20 + .../prototype/add/argument-object-invalid.js | 16 + .../prototype/add/argument-object.js | 40 + ...t-string-fractional-units-rounding-mode.js | 19 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/add/argument-string.js | 16 + .../add/balance-negative-time-units.js | 50 + .../PlainTime/prototype/add/builtin.js | 36 + .../add/infinity-throws-rangeerror.js | 38 + .../PlainTime/prototype/add/length.js | 28 + .../Temporal/PlainTime/prototype/add/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 38 + .../add/non-integer-throws-rangeerror.js | 29 + .../prototype/add/not-a-constructor.js | 24 + .../prototype/add/options-ignored.js | 32 + .../prototype/add/order-of-operations.js | 77 + .../PlainTime/prototype/add/prop-desc.js | 24 + .../Temporal/PlainTime/prototype/add/shell.js | 19 + .../prototype/add/subclassing-ignored.js | 20 + .../PlainTime/prototype/calendar/prop-desc.js | 17 + .../prototype/equals/argument-cast.js | 20 + .../argument-string-no-implicit-midnight.js | 19 + ...-designator-required-for-disambiguation.js | 56 + .../argument-string-with-time-designator.js | 31 + .../argument-string-with-utc-designator.js | 24 + .../prototype/equals/argument-wrong-type.js | 23 + ...neddatetime-balance-negative-time-units.js | 43 + ...zoneddatetime-negative-epochnanoseconds.js | 25 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../PlainTime/prototype/equals/basic.js | 18 + .../PlainTime/prototype/equals/builtin.js | 36 + .../equals/calendar-temporal-object.js | 28 + .../PlainTime/prototype/equals/length.js | 28 + .../PlainTime/prototype/equals/name.js | 26 + .../prototype/equals/not-a-constructor.js | 24 + .../plaintime-propertybag-no-time-units.js | 20 + .../PlainTime/prototype/equals/prop-desc.js | 24 + .../PlainTime/prototype/equals/shell.js | 19 + .../PlainTime/prototype/equals/year-zero.js | 24 + .../prototype/getISOFields/builtin.js | 36 + .../prototype/getISOFields/field-names.js | 22 + .../prototype/getISOFields/field-prop-desc.js | 33 + .../getISOFields/field-traversal-order.js | 27 + .../prototype/getISOFields/length.js | 28 + .../PlainTime/prototype/getISOFields/name.js | 26 + .../getISOFields/not-a-constructor.js | 24 + .../prototype/getISOFields/prop-desc.js | 24 + .../PlainTime/prototype/getISOFields/shell.js | 19 + .../PlainTime/prototype/hour/prop-desc.js | 17 + .../prototype/microsecond/prop-desc.js | 17 + .../prototype/millisecond/prop-desc.js | 17 + .../PlainTime/prototype/minute/prop-desc.js | 17 + .../prototype/nanosecond/prop-desc.js | 17 + .../Temporal/PlainTime/prototype/prop-desc.js | 21 + .../PlainTime/prototype/round/builtin.js | 36 + .../PlainTime/prototype/round/length.js | 28 + .../PlainTime/prototype/round/name.js | 26 + .../prototype/round/not-a-constructor.js | 24 + .../PlainTime/prototype/round/prop-desc.js | 24 + .../round/rounding-cross-midnight.js | 17 + .../round/roundingincrement-hours.js | 36 + .../round/roundingincrement-invalid.js | 26 + .../round/roundingincrement-microseconds.js | 60 + .../round/roundingincrement-milliseconds.js | 60 + .../round/roundingincrement-minutes.js | 48 + .../prototype/round/roundingincrement-nan.js | 21 + .../round/roundingincrement-nanoseconds.js | 60 + .../round/roundingincrement-non-integer.js | 19 + .../round/roundingincrement-out-of-range.js | 20 + .../round/roundingincrement-seconds.js | 48 + .../round/roundingincrement-undefined.js | 27 + .../round/roundingincrement-wrong-type.js | 27 + .../prototype/round/roundingmode-ceil.js | 39 + .../prototype/round/roundingmode-floor.js | 38 + .../round/roundingmode-halfExpand.js | 38 + .../round/roundingmode-invalid-string.js | 16 + .../prototype/round/roundingmode-trunc.js | 38 + .../prototype/round/roundingmode-undefined.js | 56 + .../round/roundingmode-wrong-type.js | 18 + .../PlainTime/prototype/round/shell.js | 19 + .../round/smallestunit-disallowed-units.js | 37 + .../round/smallestunit-invalid-string.js | 17 + .../prototype/round/smallestunit-missing.js | 16 + .../round/smallestunit-plurals-accepted.js | 24 + .../round/smallestunit-string-shorthand.js | 27 + .../round/smallestunit-wrong-type.js | 18 + .../prototype/round/subclassing-ignored.js | 20 + .../PlainTime/prototype/second/prop-desc.js | 17 + .../prototype/since/argument-cast.js | 21 + .../argument-string-no-implicit-midnight.js | 19 + ...-designator-required-for-disambiguation.js | 56 + .../argument-string-with-time-designator.js | 32 + .../argument-string-with-utc-designator.js | 24 + ...neddatetime-balance-negative-time-units.js | 46 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../since/balance-negative-time-units.js | 51 + .../PlainTime/prototype/since/basic.js | 25 + .../PlainTime/prototype/since/builtin.js | 36 + .../since/calendar-temporal-object.js | 28 + .../since/largestunit-invalid-string.js | 18 + .../since/largestunit-plurals-accepted.js | 24 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/since/largestunit-undefined.js | 20 + .../prototype/since/largestunit-wrong-type.js | 19 + .../PlainTime/prototype/since/largestunit.js | 19 + .../PlainTime/prototype/since/length.js | 28 + .../PlainTime/prototype/since/name.js | 26 + .../prototype/since/not-a-constructor.js | 24 + .../prototype/since/options-invalid.js | 19 + .../prototype/since/options-undefined.js | 22 + .../PlainTime/prototype/since/prop-desc.js | 24 + .../prototype/since/result-sub-second.js | 24 + .../since/roundingincrement-hours.js | 37 + .../since/roundingincrement-invalid.js | 27 + .../since/roundingincrement-microseconds.js | 61 + .../since/roundingincrement-milliseconds.js | 61 + .../since/roundingincrement-minutes.js | 49 + .../prototype/since/roundingincrement-nan.js | 22 + .../since/roundingincrement-nanoseconds.js | 61 + .../since/roundingincrement-non-integer.js | 20 + .../since/roundingincrement-out-of-range.js | 21 + .../since/roundingincrement-seconds.js | 49 + .../since/roundingincrement-undefined.js | 28 + .../since/roundingincrement-wrong-type.js | 28 + .../prototype/since/roundingmode-ceil.js | 57 + .../prototype/since/roundingmode-floor.js | 58 + .../since/roundingmode-halfExpand.js | 57 + .../since/roundingmode-invalid-string.js | 17 + .../prototype/since/roundingmode-trunc.js | 57 + .../prototype/since/roundingmode-undefined.js | 93 + .../since/roundingmode-wrong-type.js | 19 + .../PlainTime/prototype/since/shell.js | 19 + .../since/smallestunit-invalid-string.js | 18 + .../since/smallestunit-plurals-accepted.js | 24 + .../prototype/since/smallestunit-undefined.js | 22 + .../since/smallestunit-wrong-type.js | 19 + .../PlainTime/prototype/since/year-zero.js | 24 + .../prototype/subtract/argument-duration.js | 17 + .../subtract/argument-higher-units.js | 32 + .../prototype/subtract/argument-not-object.js | 20 + .../subtract/argument-object-invalid.js | 16 + .../prototype/subtract/argument-object.js | 40 + ...t-string-fractional-units-rounding-mode.js | 19 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/subtract/argument-string.js | 16 + .../subtract/balance-negative-time-units.js | 50 + .../PlainTime/prototype/subtract/builtin.js | 36 + .../subtract/infinity-throws-rangeerror.js | 38 + .../PlainTime/prototype/subtract/length.js | 28 + .../PlainTime/prototype/subtract/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 38 + .../subtract/non-integer-throws-rangeerror.js | 29 + .../prototype/subtract/not-a-constructor.js | 24 + .../prototype/subtract/options-ignored.js | 32 + .../prototype/subtract/order-of-operations.js | 77 + .../PlainTime/prototype/subtract/prop-desc.js | 24 + .../PlainTime/prototype/subtract/shell.js | 19 + .../prototype/subtract/subclassing-ignored.js | 20 + .../PlainTime/prototype/toJSON/builtin.js | 36 + .../PlainTime/prototype/toJSON/length.js | 28 + .../PlainTime/prototype/toJSON/name.js | 26 + .../prototype/toJSON/not-a-constructor.js | 24 + .../PlainTime/prototype/toJSON/prop-desc.js | 24 + .../PlainTime/prototype/toJSON/shell.js | 19 + .../prototype/toLocaleString/builtin.js | 36 + .../prototype/toLocaleString/length.js | 28 + .../prototype/toLocaleString/name.js | 26 + .../toLocaleString/not-a-constructor.js | 24 + .../prototype/toLocaleString/prop-desc.js | 24 + .../prototype/toLocaleString/return-string.js | 16 + .../prototype/toLocaleString/shell.js | 19 + .../toPlainDateTime/argument-plaindatetime.js | 24 + .../argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/toPlainDateTime/basic.js | 25 + .../prototype/toPlainDateTime/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 19 + .../calendar-fields-iterable.js | 34 + .../calendar-temporal-object.js | 30 + .../infinity-throws-rangeerror.js | 26 + .../prototype/toPlainDateTime/length.js | 28 + .../prototype/toPlainDateTime/name.js | 26 + .../toPlainDateTime/not-a-constructor.js | 24 + .../prototype/toPlainDateTime/prop-desc.js | 24 + .../prototype/toPlainDateTime/shell.js | 19 + .../prototype/toPlainDateTime/year-zero.js | 20 + .../PlainTime/prototype/toString/basic.js | 18 + .../PlainTime/prototype/toString/builtin.js | 36 + .../toString/fractionalseconddigits-auto.js | 22 + .../fractionalseconddigits-invalid-string.js | 24 + .../toString/fractionalseconddigits-nan.js | 23 + .../fractionalseconddigits-non-integer.js | 23 + .../toString/fractionalseconddigits-number.js | 25 + .../fractionalseconddigits-out-of-range.js | 25 + .../fractionalseconddigits-undefined.js | 39 + .../fractionalseconddigits-wrong-type.js | 28 + .../PlainTime/prototype/toString/length.js | 28 + .../PlainTime/prototype/toString/name.js | 26 + .../prototype/toString/not-a-constructor.js | 24 + .../prototype/toString/options-invalid.js | 18 + .../prototype/toString/options-undefined.js | 27 + .../PlainTime/prototype/toString/prop-desc.js | 24 + .../toString/rounding-cross-midnight.js | 16 + .../prototype/toString/roundingmode-ceil.js | 22 + .../prototype/toString/roundingmode-floor.js | 22 + .../toString/roundingmode-halfExpand.js | 22 + .../toString/roundingmode-invalid-string.js | 16 + .../prototype/toString/roundingmode-trunc.js | 22 + .../toString/roundingmode-undefined.js | 28 + .../toString/roundingmode-wrong-type.js | 18 + .../PlainTime/prototype/toString/shell.js | 19 + .../smallestunit-fractionalseconddigits.js | 34 + .../toString/smallestunit-invalid-string.js | 16 + .../toString/smallestunit-plurals-accepted.js | 22 + .../toString/smallestunit-undefined.js | 23 + .../toString/smallestunit-valid-units.js | 37 + .../toString/smallestunit-wrong-type.js | 18 + .../toZonedDateTime/argument-plaindatetime.js | 32 + .../toZonedDateTime/argument-primitive.js | 26 + .../argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/toZonedDateTime/basic.js | 27 + .../prototype/toZonedDateTime/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 20 + ...romfields-called-with-options-undefined.js | 19 + .../calendar-fields-iterable.js | 34 + .../calendar-temporal-object.js | 30 + .../infinity-throws-rangeerror.js | 26 + .../prototype/toZonedDateTime/length.js | 28 + .../prototype/toZonedDateTime/name.js | 26 + .../toZonedDateTime/not-a-constructor.js | 24 + .../plaindate-infinity-throws-rangeerror.js | 26 + .../prototype/toZonedDateTime/prop-desc.js | 24 + .../prototype/toZonedDateTime/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 26 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + ...imezone-getpossibleinstantsfor-iterable.js | 45 + .../timezone-string-datetime.js | 47 + .../timezone-string-multiple-offsets.js | 19 + .../prototype/toZonedDateTime/year-zero.js | 20 + .../prototype/until/argument-cast.js | 21 + .../argument-string-no-implicit-midnight.js | 19 + ...-designator-required-for-disambiguation.js | 56 + .../argument-string-with-time-designator.js | 32 + .../argument-string-with-utc-designator.js | 24 + ...neddatetime-balance-negative-time-units.js | 46 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../until/balance-negative-time-units.js | 51 + .../PlainTime/prototype/until/basic.js | 25 + .../PlainTime/prototype/until/builtin.js | 36 + .../until/calendar-temporal-object.js | 28 + .../until/largestunit-invalid-string.js | 18 + .../until/largestunit-plurals-accepted.js | 24 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/until/largestunit-undefined.js | 20 + .../prototype/until/largestunit-wrong-type.js | 19 + .../PlainTime/prototype/until/largestunit.js | 19 + .../PlainTime/prototype/until/length.js | 28 + .../PlainTime/prototype/until/name.js | 26 + .../prototype/until/not-a-constructor.js | 24 + .../prototype/until/options-invalid.js | 19 + .../prototype/until/options-undefined.js | 22 + .../PlainTime/prototype/until/prop-desc.js | 24 + .../prototype/until/result-sub-second.js | 24 + .../until/roundingincrement-hours.js | 37 + .../until/roundingincrement-invalid.js | 27 + .../until/roundingincrement-microseconds.js | 61 + .../until/roundingincrement-milliseconds.js | 61 + .../until/roundingincrement-minutes.js | 49 + .../prototype/until/roundingincrement-nan.js | 22 + .../until/roundingincrement-nanoseconds.js | 61 + .../until/roundingincrement-non-integer.js | 20 + .../until/roundingincrement-out-of-range.js | 21 + .../until/roundingincrement-seconds.js | 49 + .../until/roundingincrement-undefined.js | 28 + .../until/roundingincrement-wrong-type.js | 28 + .../prototype/until/roundingmode-ceil.js | 57 + .../prototype/until/roundingmode-floor.js | 57 + .../until/roundingmode-halfExpand.js | 57 + .../until/roundingmode-invalid-string.js | 17 + .../prototype/until/roundingmode-trunc.js | 57 + .../prototype/until/roundingmode-undefined.js | 93 + .../until/roundingmode-wrong-type.js | 19 + .../PlainTime/prototype/until/shell.js | 19 + .../until/smallestunit-invalid-string.js | 18 + .../until/smallestunit-plurals-accepted.js | 24 + .../prototype/until/smallestunit-undefined.js | 22 + .../until/smallestunit-wrong-type.js | 19 + .../PlainTime/prototype/until/year-zero.js | 24 + .../PlainTime/prototype/valueOf/basic.js | 24 + .../PlainTime/prototype/valueOf/builtin.js | 36 + .../PlainTime/prototype/valueOf/length.js | 28 + .../PlainTime/prototype/valueOf/name.js | 26 + .../prototype/valueOf/not-a-constructor.js | 24 + .../PlainTime/prototype/valueOf/prop-desc.js | 24 + .../PlainTime/prototype/valueOf/shell.js | 19 + .../prototype/with/argument-not-object.js | 37 + .../PlainTime/prototype/with/basic.js | 39 + .../PlainTime/prototype/with/builtin.js | 36 + .../with/copy-properties-not-undefined.js | 25 + .../with/infinity-throws-rangeerror.js | 27 + .../PlainTime/prototype/with/length.js | 28 + .../Temporal/PlainTime/prototype/with/name.js | 26 + .../prototype/with/not-a-constructor.js | 24 + .../prototype/with/options-invalid.js | 16 + .../prototype/with/options-undefined.js | 24 + .../prototype/with/order-of-operations.js | 63 + .../prototype/with/overflow-invalid-string.js | 30 + .../prototype/with/overflow-undefined.js | 25 + .../prototype/with/overflow-wrong-type.js | 25 + .../prototype/with/plaintimelike-invalid.js | 50 + .../PlainTime/prototype/with/prop-desc.js | 24 + .../PlainTime/prototype/with/shell.js | 19 + .../prototype/with/subclassing-ignored.js | 20 + .../Temporal/PlainTime/second-undefined.js | 20 + .../built-ins/Temporal/PlainTime/shell.js | 1498 ++++++ .../Temporal/PlainYearMonth/basic.js | 16 + .../Temporal/PlainYearMonth/builtin.js | 30 + .../PlainYearMonth/calendar-always.js | 27 + .../PlainYearMonth/calendar-invalid.js | 23 + .../calendar-temporal-object.js | 25 + .../PlainYearMonth/calendar-undefined.js | 25 + .../PlainYearMonth/compare/argument-cast.js | 22 + .../argument-string-with-utc-designator.js | 29 + .../Temporal/PlainYearMonth/compare/basic.js | 19 + .../PlainYearMonth/compare/browser.js | 0 .../PlainYearMonth/compare/builtin.js | 33 + .../compare/calendar-fields-iterable.js | 40 + .../compare/calendar-temporal-object.js | 32 + ...romfields-called-with-options-undefined.js | 35 + .../compare/compare-calendar.js | 25 + .../compare/compare-reference-day.js | 16 + .../compare/infinity-throws-rangeerror.js | 33 + .../Temporal/PlainYearMonth/compare/length.js | 28 + .../Temporal/PlainYearMonth/compare/name.js | 26 + .../compare/not-a-constructor.js | 23 + .../PlainYearMonth/compare/prop-desc.js | 24 + .../Temporal/PlainYearMonth/compare/shell.js | 19 + .../compare/use-internal-slots.js | 26 + .../PlainYearMonth/compare/year-zero.js | 26 + .../Temporal/PlainYearMonth/constructor.js | 15 + .../PlainYearMonth/from/argument-number.js | 20 + .../PlainYearMonth/from/argument-object.js | 50 + .../PlainYearMonth/from/argument-plaindate.js | 21 + .../from/argument-plainyearmonth.js | 25 + .../from/argument-string-invalid.js | 14 + .../from/argument-string-trailing-junk.js | 13 + .../argument-string-with-utc-designator.js | 23 + .../PlainYearMonth/from/argument-string.js | 58 + .../Temporal/PlainYearMonth/from/browser.js | 0 .../Temporal/PlainYearMonth/from/builtin.js | 33 + .../from/calendar-fields-iterable.js | 32 + .../from/calendar-temporal-object.js | 29 + ...romfields-called-with-options-undefined.js | 26 + .../from/infinity-throws-rangeerror.js | 27 + .../Temporal/PlainYearMonth/from/length.js | 28 + .../Temporal/PlainYearMonth/from/limits.js | 28 + .../Temporal/PlainYearMonth/from/name.js | 26 + .../PlainYearMonth/from/not-a-constructor.js | 23 + .../PlainYearMonth/from/options-invalid.js | 24 + .../PlainYearMonth/from/options-undefined.js | 19 + .../from/order-of-operations.js | 47 + .../PlainYearMonth/from/overflow-constrain.js | 17 + .../from/overflow-invalid-string.js | 43 + .../PlainYearMonth/from/overflow-reject.js | 14 + .../PlainYearMonth/from/overflow-undefined.js | 48 + .../from/overflow-wrong-type.js | 37 + .../Temporal/PlainYearMonth/from/prop-desc.js | 24 + .../Temporal/PlainYearMonth/from/shell.js | 19 + .../from/subclassing-ignored.js | 19 + .../Temporal/PlainYearMonth/from/year-zero.js | 25 + .../infinity-throws-rangeerror.js | 44 + .../Temporal/PlainYearMonth/length.js | 28 + .../Temporal/PlainYearMonth/limits.js | 23 + .../PlainYearMonth/missing-arguments.js | 23 + .../built-ins/Temporal/PlainYearMonth/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 44 + .../Temporal/PlainYearMonth/prop-desc.js | 24 + .../prototype/add/argument-duration-object.js | 16 + .../prototype/add/argument-lower-units.js | 41 + .../prototype/add/argument-not-object.js | 20 + .../prototype/add/argument-object-invalid.js | 19 + .../prototype/add/argument-object-plural.js | 15 + .../prototype/add/argument-object.js | 27 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/add/argument-string.js | 16 + .../PlainYearMonth/prototype/add/builtin.js | 36 + .../add/calendar-arguments-extra-options.js | 57 + .../prototype/add/calendar-arguments.js | 62 + .../add/calendar-datefromfields-called.js | 150 + .../add/calendar-daysinmonth-wrong-value.js | 45 + .../prototype/add/calendar-fields-iterable.js | 30 + .../add/infinity-throws-rangeerror.js | 38 + .../PlainYearMonth/prototype/add/length.js | 28 + .../PlainYearMonth/prototype/add/limits.js | 16 + .../prototype/add/month-length.js | 31 + .../PlainYearMonth/prototype/add/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 38 + .../add/non-integer-throws-rangeerror.js | 29 + .../prototype/add/not-a-constructor.js | 24 + .../prototype/add/options-invalid.js | 17 + .../prototype/add/options-undefined.js | 33 + .../prototype/add/order-of-operations.js | 77 + .../prototype/add/overflow-invalid-string.js | 34 + .../prototype/add/overflow-undefined.js | 36 + .../prototype/add/overflow-wrong-type.js | 51 + .../PlainYearMonth/prototype/add/prop-desc.js | 24 + .../PlainYearMonth/prototype/add/shell.js | 348 ++ .../prototype/add/subclassing-ignored.js | 20 + .../prototype/calendar/prop-desc.js | 17 + .../prototype/daysInMonth/basic.js | 14 + .../prototype/daysInMonth/prop-desc.js | 17 + .../prototype/daysInYear/basic.js | 14 + .../prototype/daysInYear/prop-desc.js | 17 + .../prototype/equals/argument-cast.js | 19 + .../argument-string-with-utc-designator.js | 24 + .../prototype/equals/argument-wrong-type.js | 23 + .../PlainYearMonth/prototype/equals/basic.js | 18 + .../prototype/equals/builtin.js | 36 + .../equals/calendar-fields-iterable.js | 35 + .../equals/calendar-temporal-object.js | 29 + ...romfields-called-with-options-undefined.js | 38 + .../prototype/equals/compare-calendar.js | 46 + .../prototype/equals/compare-reference-day.js | 16 + .../equals/infinity-throws-rangeerror.js | 26 + .../PlainYearMonth/prototype/equals/length.js | 28 + .../PlainYearMonth/prototype/equals/name.js | 26 + .../prototype/equals/not-a-constructor.js | 24 + .../prototype/equals/prop-desc.js | 24 + .../PlainYearMonth/prototype/equals/shell.js | 19 + .../prototype/equals/use-internal-slots.js | 26 + .../prototype/equals/year-zero.js | 26 + .../prototype/getISOFields/builtin.js | 36 + .../prototype/getISOFields/field-names.js | 19 + .../prototype/getISOFields/field-prop-desc.js | 30 + .../getISOFields/field-traversal-order.js | 24 + .../prototype/getISOFields/length.js | 28 + .../prototype/getISOFields/name.js | 26 + .../getISOFields/not-a-constructor.js | 24 + .../prototype/getISOFields/prop-desc.js | 24 + .../prototype/getISOFields/shell.js | 19 + .../prototype/inLeapYear/prop-desc.js | 17 + .../month/calendar-returns-infinity.js | 30 + .../prototype/month/prop-desc.js | 17 + .../prototype/monthCode/prop-desc.js | 17 + .../prototype/monthsInYear/basic.js | 14 + .../prototype/monthsInYear/prop-desc.js | 17 + .../PlainYearMonth/prototype/prop-desc.js | 21 + .../prototype/since/argument-casting.js | 19 + .../argument-string-with-utc-designator.js | 24 + .../since/arguments-missing-throws.js | 16 + .../PlainYearMonth/prototype/since/builtin.js | 36 + ...-dateadd-called-with-plaindate-instance.js | 19 + ...romfields-called-with-options-undefined.js | 19 + ...euntil-called-with-singular-largestunit.js | 28 + .../since/calendar-fields-iterable.js | 43 + .../since/calendar-temporal-object.js | 29 + ...romfields-called-with-options-undefined.js | 38 + .../since/infinity-throws-rangeerror.js | 26 + .../prototype/since/largestunit-auto.js | 20 + .../since/largestunit-disallowed-units.js | 27 + .../since/largestunit-invalid-string.js | 18 + .../prototype/since/largestunit-months.js | 20 + .../since/largestunit-plurals-accepted.js | 20 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/since/largestunit-undefined.js | 30 + .../prototype/since/largestunit-wrong-type.js | 19 + .../prototype/since/largestunit-years.js | 20 + .../PlainYearMonth/prototype/since/length.js | 28 + .../prototype/since/mixed-calendar-invalid.js | 26 + .../PlainYearMonth/prototype/since/name.js | 26 + .../prototype/since/not-a-constructor.js | 24 + .../prototype/since/options-invalid.js | 25 + .../prototype/since/options-undefined.js | 25 + .../prototype/since/prop-desc.js | 24 + .../since/roundingincrement-as-expected.js | 27 + .../prototype/since/roundingincrement-nan.js | 22 + .../since/roundingincrement-non-integer.js | 20 + .../since/roundingincrement-out-of-range.js | 21 + .../since/roundingincrement-undefined.js | 28 + .../since/roundingincrement-wrong-type.js | 28 + .../prototype/since/roundingmode-ceil.js | 29 + .../prototype/since/roundingmode-floor.js | 29 + .../since/roundingmode-halfExpand.js | 29 + .../since/roundingmode-invalid-string.js | 17 + .../prototype/since/roundingmode-trunc.js | 29 + .../prototype/since/roundingmode-undefined.js | 26 + .../since/roundingmode-wrong-type.js | 19 + .../PlainYearMonth/prototype/since/shell.js | 19 + .../since/smallestunit-invalid-string.js | 18 + .../since/smallestunit-plurals-accepted.js | 20 + .../prototype/since/smallestunit-undefined.js | 20 + .../since/smallestunit-wrong-type.js | 19 + .../prototype/since/symmetry.js | 18 + .../prototype/since/year-zero.js | 26 + .../subtract/argument-duration-object.js | 16 + .../subtract/argument-lower-units.js | 40 + .../prototype/subtract/argument-not-object.js | 20 + .../subtract/argument-object-invalid.js | 19 + .../subtract/argument-object-plural.js | 15 + .../prototype/subtract/argument-object.js | 27 + ...gument-string-negative-fractional-units.js | 20 + .../prototype/subtract/argument-string.js | 16 + .../prototype/subtract/builtin.js | 36 + .../calendar-arguments-extra-options.js | 57 + .../prototype/subtract/calendar-arguments.js | 61 + .../calendar-datefromfields-called.js | 150 + .../calendar-daysinmonth-wrong-value.js | 45 + .../subtract/calendar-fields-iterable.js | 30 + .../subtract/infinity-throws-rangeerror.js | 37 + .../prototype/subtract/length.js | 28 + .../prototype/subtract/limits.js | 16 + .../prototype/subtract/month-length.js | 31 + .../PlainYearMonth/prototype/subtract/name.js | 26 + .../negative-infinity-throws-rangeerror.js | 38 + .../subtract/non-integer-throws-rangeerror.js | 29 + .../prototype/subtract/not-a-constructor.js | 24 + .../prototype/subtract/options-invalid.js | 17 + .../prototype/subtract/options-undefined.js | 33 + .../prototype/subtract/order-of-operations.js | 77 + .../subtract/overflow-invalid-string.js | 34 + .../prototype/subtract/overflow-undefined.js | 36 + .../prototype/subtract/overflow-wrong-type.js | 51 + .../prototype/subtract/prop-desc.js | 24 + .../prototype/subtract/shell.js | 348 ++ .../prototype/subtract/subclassing-ignored.js | 20 + .../prototype/toJSON/builtin.js | 36 + .../PlainYearMonth/prototype/toJSON/length.js | 28 + .../PlainYearMonth/prototype/toJSON/name.js | 26 + .../prototype/toJSON/not-a-constructor.js | 24 + .../prototype/toJSON/prop-desc.js | 24 + .../PlainYearMonth/prototype/toJSON/shell.js | 19 + .../prototype/toJSON/year-format.js | 50 + .../prototype/toLocaleString/builtin.js | 36 + .../prototype/toLocaleString/length.js | 28 + .../prototype/toLocaleString/name.js | 26 + .../toLocaleString/not-a-constructor.js | 24 + .../prototype/toLocaleString/prop-desc.js | 24 + .../prototype/toLocaleString/shell.js | 19 + .../toPlainDate/argument-not-object.js | 18 + .../prototype/toPlainDate/basic.js | 16 + .../prototype/toPlainDate/builtin.js | 36 + .../toPlainDate/calendar-fields-iterable.js | 37 + ...calendar-merge-fields-returns-primitive.js | 21 + .../toPlainDate/copies-merge-fields-object.js | 34 + .../toPlainDate/infinity-throws-rangeerror.js | 23 + .../prototype/toPlainDate/length.js | 28 + .../prototype/toPlainDate/limits.js | 22 + .../prototype/toPlainDate/name.js | 26 + .../toPlainDate/not-a-constructor.js | 24 + .../prototype/toPlainDate/prop-desc.js | 24 + .../prototype/toPlainDate/shell.js | 19 + .../prototype/toString/builtin.js | 36 + .../prototype/toString/calendarname-always.js | 25 + .../prototype/toString/calendarname-auto.js | 25 + .../toString/calendarname-invalid-string.js | 23 + .../prototype/toString/calendarname-never.js | 25 + .../toString/calendarname-undefined.js | 35 + .../toString/calendarname-wrong-type.js | 29 + .../prototype/toString/length.js | 28 + .../PlainYearMonth/prototype/toString/name.js | 26 + .../prototype/toString/not-a-constructor.js | 24 + .../prototype/toString/options-undefined.js | 28 + .../prototype/toString/prop-desc.js | 24 + .../prototype/toString/shell.js | 19 + .../prototype/toString/year-format.js | 50 + .../prototype/until/argument-casting.js | 19 + .../argument-string-with-utc-designator.js | 24 + .../until/arguments-missing-throws.js | 16 + .../PlainYearMonth/prototype/until/builtin.js | 36 + ...-dateadd-called-with-plaindate-instance.js | 19 + ...romfields-called-with-options-undefined.js | 19 + ...euntil-called-with-singular-largestunit.js | 28 + .../until/calendar-fields-iterable.js | 43 + .../until/calendar-temporal-object.js | 29 + ...romfields-called-with-options-undefined.js | 38 + .../until/infinity-throws-rangeerror.js | 26 + .../prototype/until/largestunit-auto.js | 20 + .../until/largestunit-disallowed-units.js | 28 + .../until/largestunit-invalid-string.js | 18 + .../prototype/until/largestunit-months.js | 20 + .../until/largestunit-plurals-accepted.js | 20 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/until/largestunit-undefined.js | 30 + .../prototype/until/largestunit-wrong-type.js | 19 + .../prototype/until/largestunit-years.js | 20 + .../PlainYearMonth/prototype/until/length.js | 28 + .../prototype/until/mixed-calendar-invalid.js | 26 + .../PlainYearMonth/prototype/until/name.js | 26 + .../prototype/until/not-a-constructor.js | 24 + .../prototype/until/options-invalid.js | 25 + .../prototype/until/options-undefined.js | 25 + .../prototype/until/prop-desc.js | 24 + .../until/roundingincrement-as-expected.js | 27 + .../prototype/until/roundingincrement-nan.js | 22 + .../until/roundingincrement-non-integer.js | 20 + .../until/roundingincrement-out-of-range.js | 21 + .../until/roundingincrement-undefined.js | 28 + .../until/roundingincrement-wrong-type.js | 28 + .../prototype/until/roundingmode-ceil.js | 29 + .../prototype/until/roundingmode-floor.js | 29 + .../until/roundingmode-halfExpand.js | 29 + .../until/roundingmode-invalid-string.js | 17 + .../prototype/until/roundingmode-trunc.js | 29 + .../prototype/until/roundingmode-undefined.js | 26 + .../until/roundingmode-wrong-type.js | 19 + .../PlainYearMonth/prototype/until/shell.js | 19 + .../until/smallestunit-invalid-string.js | 18 + .../until/smallestunit-plurals-accepted.js | 20 + .../prototype/until/smallestunit-undefined.js | 20 + .../until/smallestunit-wrong-type.js | 19 + .../prototype/until/year-zero.js | 26 + .../PlainYearMonth/prototype/valueOf/basic.js | 24 + .../prototype/valueOf/builtin.js | 36 + .../prototype/valueOf/length.js | 28 + .../PlainYearMonth/prototype/valueOf/name.js | 26 + .../prototype/valueOf/not-a-constructor.js | 24 + .../prototype/valueOf/prop-desc.js | 24 + .../PlainYearMonth/prototype/valueOf/shell.js | 19 + .../prototype/with/argument-calendar-field.js | 14 + .../prototype/with/argument-missing-fields.js | 15 + .../prototype/with/argument-timezone-field.js | 14 + .../PlainYearMonth/prototype/with/basic.js | 26 + .../PlainYearMonth/prototype/with/builtin.js | 36 + .../prototype/with/calendar-arguments.js | 32 + .../with/calendar-fields-iterable.js | 31 + ...calendar-merge-fields-returns-primitive.js | 21 + .../with/copies-merge-fields-object.js | 35 + .../with/copy-properties-not-undefined.js | 25 + .../with/infinity-throws-rangeerror.js | 27 + .../PlainYearMonth/prototype/with/length.js | 28 + .../PlainYearMonth/prototype/with/name.js | 26 + .../prototype/with/not-a-constructor.js | 24 + .../prototype/with/options-undefined.js | 20 + .../prototype/with/options-wrong-type.js | 25 + .../prototype/with/order-of-operations.js | 51 + .../prototype/with/overflow-invalid-string.js | 31 + .../prototype/with/overflow-undefined.js | 29 + .../prototype/with/overflow-wrong-type.js | 27 + .../prototype/with/prop-desc.js | 24 + .../PlainYearMonth/prototype/with/shell.js | 19 + .../prototype/with/subclassing-ignored.js | 20 + .../year/calendar-returns-infinity.js | 30 + .../prototype/year/prop-desc.js | 17 + .../PlainYearMonth/refisoday-undefined.js | 20 + .../Temporal/PlainYearMonth/shell.js | 1498 ++++++ .../built-ins/Temporal/TimeZone/basic.js | 37 + .../built-ins/Temporal/TimeZone/builtin.js | 30 + .../Temporal/TimeZone/constructor.js | 15 + .../TimeZone/from/argument-object-invalid.js | 14 + .../Temporal/TimeZone/from/argument-object.js | 51 + .../TimeZone/from/argument-primitive.js | 48 + .../Temporal/TimeZone/from/argument-valid.js | 37 + .../Temporal/TimeZone/from/browser.js | 0 .../Temporal/TimeZone/from/builtin.js | 33 + .../Temporal/TimeZone/from/length.js | 28 + .../built-ins/Temporal/TimeZone/from/name.js | 26 + .../TimeZone/from/not-a-constructor.js | 23 + .../Temporal/TimeZone/from/prop-desc.js | 24 + .../built-ins/Temporal/TimeZone/from/shell.js | 1517 ++++++ .../TimeZone/from/subclassing-ignored.js | 22 + .../TimeZone/from/timezone-string-datetime.js | 45 + .../from/timezone-string-multiple-offsets.js | 18 + .../built-ins/Temporal/TimeZone/length.js | 28 + .../Temporal/TimeZone/missing-arguments.js | 14 + .../built-ins/Temporal/TimeZone/name.js | 26 + .../built-ins/Temporal/TimeZone/prop-desc.js | 24 + .../getInstantFor/argument-not-datetime.js | 21 + .../getInstantFor/argument-plaindate.js | 24 + .../argument-string-with-utc-designator.js | 24 + ...neddatetime-balance-negative-time-units.js | 46 + ...zoneddatetime-negative-epochnanoseconds.js | 25 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../balance-negative-time-units.js | 48 + .../prototype/getInstantFor/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 25 + .../getInstantFor/calendar-fields-iterable.js | 40 + .../getInstantFor/calendar-temporal-object.js | 29 + .../disambiguation-invalid-string.js | 22 + .../getInstantFor/disambiguation-undefined.js | 35 + .../disambiguation-wrong-type.js | 26 + .../infinity-throws-rangeerror.js | 26 + .../prototype/getInstantFor/length.js | 28 + .../TimeZone/prototype/getInstantFor/name.js | 26 + .../getInstantFor/not-a-constructor.js | 24 + .../getInstantFor/options-undefined.js | 27 + .../prototype/getInstantFor/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 26 + .../TimeZone/prototype/getInstantFor/shell.js | 1517 ++++++ .../prototype/getInstantFor/year-zero.js | 24 + .../argument-zoneddatetime.js | 24 + .../prototype/getNextTransition/builtin.js | 36 + .../getNextTransition/instant-string.js | 31 + .../prototype/getNextTransition/length.js | 28 + .../prototype/getNextTransition/name.js | 26 + .../getNextTransition/not-a-constructor.js | 24 + .../prototype/getNextTransition/prop-desc.js | 24 + .../prototype/getNextTransition/shell.js | 1517 ++++++ .../prototype/getNextTransition/year-zero.js | 16 + .../argument-not-absolute.js | 21 + .../argument-zoneddatetime.js | 24 + .../getOffsetNanosecondsFor/builtin.js | 36 + .../getOffsetNanosecondsFor/instant-string.js | 31 + .../getOffsetNanosecondsFor/length.js | 28 + .../prototype/getOffsetNanosecondsFor/name.js | 26 + .../not-a-constructor.js | 24 + .../getOffsetNanosecondsFor/prop-desc.js | 24 + .../getOffsetNanosecondsFor/shell.js | 1517 ++++++ .../getOffsetNanosecondsFor/year-zero.js | 16 + ...solute-getOffsetNanosecondsFor-override.js | 24 + .../argument-not-absolute.js | 21 + .../argument-zoneddatetime.js | 24 + .../prototype/getOffsetStringFor/basic.js | 23 + .../prototype/getOffsetStringFor/builtin.js | 36 + .../getOffsetStringFor/instant-string.js | 31 + .../prototype/getOffsetStringFor/length.js | 28 + .../prototype/getOffsetStringFor/name.js | 26 + .../getOffsetStringFor/not-a-constructor.js | 24 + .../prototype/getOffsetStringFor/prop-desc.js | 24 + .../prototype/getOffsetStringFor/shell.js | 1517 ++++++ ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/getOffsetStringFor/year-zero.js | 16 + .../argument-negative-epochnanoseconds.js | 26 + ...solute-getOffsetNanosecondsFor-override.js | 24 + .../argument-not-absolute.js | 21 + .../argument-zoneddatetime.js | 24 + .../balance-negative-time-units.js | 42 + .../prototype/getPlainDateTimeFor/branding.js | 25 + .../prototype/getPlainDateTimeFor/browser.js | 0 .../prototype/getPlainDateTimeFor/builtin.js | 36 + .../calendar-temporal-object.js | 25 + .../getPlainDateTimeFor/calendar-undefined.js | 26 + .../getPlainDateTimeFor/custom-timezone.js | 30 + .../instant-string-multiple-offsets.js | 18 + .../getPlainDateTimeFor/instant-string.js | 35 + .../prototype/getPlainDateTimeFor/length.js | 28 + .../prototype/getPlainDateTimeFor/name.js | 26 + .../getPlainDateTimeFor/not-a-constructor.js | 24 + .../getPlainDateTimeFor/pre-epoch.js | 18 + .../getPlainDateTimeFor/prop-desc.js | 24 + .../prototype/getPlainDateTimeFor/shell.js | 1517 ++++++ ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../getPlainDateTimeFor/year-zero.js | 25 + .../argument-not-datetime.js | 21 + .../argument-plaindate.js | 25 + .../argument-string-with-utc-designator.js | 24 + ...neddatetime-balance-negative-time-units.js | 47 + ...zoneddatetime-negative-epochnanoseconds.js | 26 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../getPossibleInstantsFor/builtin.js | 36 + .../calendar-fields-iterable.js | 40 + .../calendar-temporal-object.js | 29 + .../infinity-throws-rangeerror.js | 26 + .../getPossibleInstantsFor/length.js | 28 + .../prototype/getPossibleInstantsFor/name.js | 26 + .../not-a-constructor.js | 24 + .../getPossibleInstantsFor/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 27 + .../prototype/getPossibleInstantsFor/shell.js | 1517 ++++++ .../getPossibleInstantsFor/year-zero.js | 24 + .../argument-zoneddatetime.js | 24 + .../getPreviousTransition/builtin.js | 36 + .../getPreviousTransition/instant-string.js | 31 + .../prototype/getPreviousTransition/length.js | 28 + .../prototype/getPreviousTransition/name.js | 26 + .../not-a-constructor.js | 24 + .../getPreviousTransition/prop-desc.js | 24 + .../prototype/getPreviousTransition/shell.js | 1517 ++++++ .../getPreviousTransition/year-zero.js | 16 + .../Temporal/TimeZone/prototype/prop-desc.js | 21 + .../TimeZone/prototype/toJSON/branding.js | 25 + .../TimeZone/prototype/toJSON/browser.js | 0 .../TimeZone/prototype/toJSON/builtin.js | 36 + .../TimeZone/prototype/toJSON/length.js | 28 + .../TimeZone/prototype/toJSON/name.js | 26 + .../prototype/toJSON/not-a-constructor.js | 24 + .../TimeZone/prototype/toJSON/prop-desc.js | 24 + .../TimeZone/prototype/toJSON/shell.js | 1517 ++++++ .../prototype/toJSON/tostring-call.js | 30 + .../toJSON/tostring-undefined-custom.js | 27 + .../prototype/toJSON/tostring-undefined.js | 16 + .../TimeZone/prototype/toString/builtin.js | 36 + .../TimeZone/prototype/toString/length.js | 28 + .../TimeZone/prototype/toString/name.js | 26 + .../prototype/toString/not-a-constructor.js | 24 + .../TimeZone/prototype/toString/prop-desc.js | 24 + .../TimeZone/prototype/toString/shell.js | 19 + .../Temporal/ZonedDateTime/builtin.js | 30 + .../ZonedDateTime/calendar-temporal-object.js | 25 + .../ZonedDateTime/calendar-undefined.js | 25 + ...tybag-offset-not-agreeing-with-timezone.js | 18 + ...one-getoffsetnanosecondsfor-non-integer.js | 20 + ...ne-getoffsetnanosecondsfor-not-callable.js | 31 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 20 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 29 + .../Temporal/ZonedDateTime/compare/browser.js | 0 .../Temporal/ZonedDateTime/compare/builtin.js | 33 + .../compare/calendar-fields-iterable.js | 47 + .../compare/calendar-temporal-object.js | 32 + .../compare/infinity-throws-rangeerror.js | 33 + .../Temporal/ZonedDateTime/compare/length.js | 28 + .../Temporal/ZonedDateTime/compare/name.js | 26 + .../compare/not-a-constructor.js | 23 + .../ZonedDateTime/compare/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 30 + .../Temporal/ZonedDateTime/compare/shell.js | 19 + ...imezone-getpossibleinstantsfor-iterable.js | 46 + .../compare/timezone-string-datetime.js | 34 + .../ZonedDateTime/compare/year-zero.js | 23 + .../zoneddatetime-string-multiple-offsets.js | 17 + .../compare/zoneddatetime-string.js | 46 + .../Temporal/ZonedDateTime/constructor.js | 15 + ...tybag-offset-not-agreeing-with-timezone.js | 16 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 35 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../from/balance-negative-time-units.js | 91 + .../Temporal/ZonedDateTime/from/browser.js | 0 .../Temporal/ZonedDateTime/from/builtin.js | 33 + .../from/calendar-fields-iterable.js | 39 + .../from/calendar-temporal-object.js | 29 + .../from/disambiguation-invalid-string.js | 32 + .../from/disambiguation-undefined.js | 38 + .../from/disambiguation-wrong-type.js | 39 + .../from/infinity-throws-rangeerror.js | 27 + .../Temporal/ZonedDateTime/from/length.js | 28 + .../Temporal/ZonedDateTime/from/name.js | 26 + .../ZonedDateTime/from/not-a-constructor.js | 23 + .../from/offset-invalid-string.js | 31 + .../ZonedDateTime/from/offset-undefined.js | 30 + .../ZonedDateTime/from/offset-wrong-type.js | 38 + .../ZonedDateTime/from/options-undefined.js | 46 + .../from/overflow-invalid-string.js | 48 + .../ZonedDateTime/from/overflow-undefined.js | 48 + .../ZonedDateTime/from/overflow-wrong-type.js | 67 + .../Temporal/ZonedDateTime/from/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 30 + .../Temporal/ZonedDateTime/from/shell.js | 19 + .../ZonedDateTime/from/subclassing-ignored.js | 30 + ...imezone-getpossibleinstantsfor-iterable.js | 29 + .../from/timezone-string-datetime.js | 45 + .../from/timezone-string-multiple-offsets.js | 18 + .../Temporal/ZonedDateTime/from/year-zero.js | 15 + .../zoneddatetime-string-multiple-offsets.js | 16 + .../from/zoneddatetime-string.js | 40 + .../from/zoneddatetime-sub-minute-offset.js | 46 + .../Temporal/ZonedDateTime/length.js | 28 + .../ZonedDateTime/missing-arguments.js | 13 + .../built-ins/Temporal/ZonedDateTime/name.js | 26 + .../Temporal/ZonedDateTime/prop-desc.js | 24 + ...t-string-fractional-units-rounding-mode.js | 18 + ...gument-string-negative-fractional-units.js | 19 + .../ZonedDateTime/prototype/add/builtin.js | 36 + .../ZonedDateTime/prototype/add/length.js | 28 + .../ZonedDateTime/prototype/add/name.js | 26 + .../add/negative-epochnanoseconds.js | 24 + .../add/non-integer-throws-rangeerror.js | 29 + .../prototype/add/not-a-constructor.js | 24 + .../prototype/add/options-undefined.js | 22 + .../prototype/add/overflow-invalid-string.js | 33 + .../prototype/add/overflow-undefined.js | 30 + .../prototype/add/overflow-wrong-type.js | 30 + .../ZonedDateTime/prototype/add/prop-desc.js | 24 + .../ZonedDateTime/prototype/add/shell.js | 19 + .../prototype/add/subclassing-ignored.js | 31 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/calendar/prop-desc.js | 17 + .../day/balance-negative-time-units.js | 45 + .../day/calendar-returns-infinity.js | 30 + .../ZonedDateTime/prototype/day/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/dayOfWeek/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/dayOfYear/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/daysInMonth/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/daysInWeek/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/daysInYear/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/epochMicroseconds/basic.js | 19 + .../prototype/epochMicroseconds/prop-desc.js | 17 + .../prototype/epochMilliseconds/basic.js | 19 + .../prototype/epochMilliseconds/prop-desc.js | 17 + .../prototype/epochNanoseconds/basic.js | 19 + .../prototype/epochNanoseconds/prop-desc.js | 17 + .../prototype/epochSeconds/basic.js | 19 + .../prototype/epochSeconds/prop-desc.js | 17 + ...tybag-offset-not-agreeing-with-timezone.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 25 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../ZonedDateTime/prototype/equals/builtin.js | 36 + .../equals/calendar-fields-iterable.js | 42 + .../equals/calendar-temporal-object.js | 29 + .../equals/infinity-throws-rangeerror.js | 26 + .../ZonedDateTime/prototype/equals/length.js | 28 + .../ZonedDateTime/prototype/equals/name.js | 26 + .../prototype/equals/not-a-constructor.js | 24 + .../prototype/equals/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 26 + .../ZonedDateTime/prototype/equals/shell.js | 19 + .../prototype/equals/sub-minute-offset.js | 22 + ...imezone-getpossibleinstantsfor-iterable.js | 41 + .../equals/timezone-string-datetime.js | 45 + .../timezone-string-multiple-offsets.js | 23 + .../prototype/equals/year-zero.js | 17 + .../zoneddatetime-string-multiple-offsets.js | 18 + .../prototype/equals/zoneddatetime-string.js | 36 + .../balance-negative-time-units.js | 42 + .../prototype/getISOFields/builtin.js | 36 + .../prototype/getISOFields/field-names.js | 27 + .../prototype/getISOFields/field-prop-desc.js | 38 + .../getISOFields/field-traversal-order.js | 32 + .../prototype/getISOFields/length.js | 28 + .../prototype/getISOFields/name.js | 26 + .../getISOFields/negative-epochnanoseconds.js | 40 + .../getISOFields/not-a-constructor.js | 24 + .../prototype/getISOFields/offset.js | 23 + .../prototype/getISOFields/prop-desc.js | 24 + .../prototype/getISOFields/shell.js | 348 ++ ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../hour/balance-negative-time-units.js | 42 + .../ZonedDateTime/prototype/hour/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/hoursInDay/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + ...imezone-getpossibleinstantsfor-iterable.js | 48 + .../prototype/inLeapYear/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../balance-negative-time-units.js | 30 + .../microsecond/negative-epochnanoseconds.js | 23 + .../prototype/microsecond/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../balance-negative-time-units.js | 33 + .../millisecond/negative-epochnanoseconds.js | 23 + .../prototype/millisecond/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../minute/balance-negative-time-units.js | 41 + .../prototype/minute/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../month/calendar-returns-infinity.js | 30 + .../prototype/month/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/monthCode/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/monthsInYear/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../nanosecond/negative-epochnanoseconds.js | 23 + .../prototype/nanosecond/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../ZonedDateTime/prototype/offset/basic.js | 22 + .../prototype/offset/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/offsetNanoseconds/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../ZonedDateTime/prototype/prop-desc.js | 21 + .../ZonedDateTime/prototype/round/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 20 + .../prototype/round/dateadd-options.js | 34 + .../ZonedDateTime/prototype/round/div-zero.js | 27 + .../ZonedDateTime/prototype/round/length.js | 28 + .../ZonedDateTime/prototype/round/name.js | 26 + .../round/negative-epochnanoseconds.js | 24 + .../prototype/round/not-a-constructor.js | 24 + .../prototype/round/prop-desc.js | 24 + .../prototype/round/roundingincrement-nan.js | 23 + .../round/roundingincrement-non-integer.js | 18 + .../round/roundingincrement-out-of-range.js | 20 + .../round/roundingincrement-undefined.js | 28 + .../round/roundingincrement-wrong-type.js | 29 + .../round/roundingmode-invalid-string.js | 16 + .../prototype/round/roundingmode-undefined.js | 28 + .../round/roundingmode-wrong-type.js | 18 + .../ZonedDateTime/prototype/round/shell.js | 19 + .../round/smallestunit-disallowed-units.js | 35 + .../round/smallestunit-invalid-string.js | 14 + .../round/smallestunit-plurals-accepted.js | 25 + .../round/smallestunit-string-shorthand.js | 28 + .../round/smallestunit-wrong-type.js | 18 + .../prototype/round/subclassing-ignored.js | 31 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + ...imezone-getpossibleinstantsfor-iterable.js | 36 + .../second/balance-negative-time-units.js | 36 + .../prototype/second/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + ...tybag-offset-not-agreeing-with-timezone.js | 17 + ...ne-getoffsetnanosecondsfor-not-callable.js | 26 + .../since/balance-negative-time-units.js | 57 + .../ZonedDateTime/prototype/since/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 71 + ...r-dateuntil-called-with-copy-of-options.js | 36 + ...euntil-called-with-singular-largestunit.js | 117 + .../since/calendar-fields-iterable.js | 42 + .../since/calendar-temporal-object.js | 29 + .../since/infinity-throws-rangeerror.js | 26 + .../since/largestunit-invalid-string.js | 18 + .../since/largestunit-plurals-accepted.js | 28 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/since/largestunit-undefined.js | 20 + .../prototype/since/largestunit-wrong-type.js | 19 + .../prototype/since/largestunit.js | 25 + .../ZonedDateTime/prototype/since/length.js | 28 + .../ZonedDateTime/prototype/since/name.js | 26 + .../since/negative-epochnanoseconds.js | 25 + .../prototype/since/not-a-constructor.js | 24 + .../prototype/since/options-undefined.js | 30 + .../prototype/since/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 26 + .../prototype/since/roundingincrement-nan.js | 22 + .../since/roundingincrement-non-integer.js | 20 + .../since/roundingincrement-out-of-range.js | 21 + .../since/roundingincrement-undefined.js | 28 + .../since/roundingincrement-wrong-type.js | 28 + .../since/roundingmode-invalid-string.js | 17 + .../prototype/since/roundingmode-undefined.js | 30 + .../since/roundingmode-wrong-type.js | 19 + .../ZonedDateTime/prototype/since/shell.js | 19 + .../since/smallestunit-invalid-string.js | 18 + .../since/smallestunit-plurals-accepted.js | 28 + .../prototype/since/smallestunit-undefined.js | 20 + .../since/smallestunit-wrong-type.js | 19 + .../prototype/since/sub-minute-offset.js | 23 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + ...imezone-getpossibleinstantsfor-iterable.js | 41 + .../since/timezone-string-datetime.js | 46 + .../since/timezone-string-multiple-offsets.js | 22 + .../prototype/since/year-zero.js | 17 + .../zoneddatetime-string-multiple-offsets.js | 19 + .../prototype/since/zoneddatetime-string.js | 37 + .../prototype/startOfDay/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 20 + .../prototype/startOfDay/length.js | 28 + .../prototype/startOfDay/name.js | 26 + .../prototype/startOfDay/not-a-constructor.js | 24 + .../prototype/startOfDay/prop-desc.js | 24 + .../prototype/startOfDay/shell.js | 19 + .../startOfDay/subclassing-ignored.js | 31 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + ...t-string-fractional-units-rounding-mode.js | 18 + ...gument-string-negative-fractional-units.js | 19 + .../prototype/subtract/builtin.js | 36 + .../prototype/subtract/length.js | 28 + .../ZonedDateTime/prototype/subtract/name.js | 26 + .../subtract/negative-epochnanoseconds.js | 24 + .../subtract/non-integer-throws-rangeerror.js | 29 + .../prototype/subtract/not-a-constructor.js | 24 + .../prototype/subtract/options-undefined.js | 22 + .../subtract/overflow-invalid-string.js | 33 + .../prototype/subtract/overflow-undefined.js | 30 + .../prototype/subtract/overflow-wrong-type.js | 30 + .../prototype/subtract/prop-desc.js | 24 + .../ZonedDateTime/prototype/subtract/shell.js | 19 + .../prototype/subtract/subclassing-ignored.js | 31 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/timeZone/prop-desc.js | 17 + .../prototype/toInstant/builtin.js | 36 + .../prototype/toInstant/length.js | 28 + .../ZonedDateTime/prototype/toInstant/name.js | 26 + .../prototype/toInstant/not-a-constructor.js | 24 + .../prototype/toInstant/prop-desc.js | 24 + .../prototype/toInstant/shell.js | 19 + .../toJSON/balance-negative-time-units.js | 43 + .../ZonedDateTime/prototype/toJSON/builtin.js | 36 + .../ZonedDateTime/prototype/toJSON/length.js | 28 + .../ZonedDateTime/prototype/toJSON/name.js | 26 + .../toJSON/negative-epochnanoseconds.js | 24 + .../prototype/toJSON/not-a-constructor.js | 24 + .../ZonedDateTime/prototype/toJSON/offset.js | 23 + .../prototype/toJSON/prop-desc.js | 24 + .../ZonedDateTime/prototype/toJSON/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/toJSON/year-format.js | 58 + .../prototype/toLocaleString/builtin.js | 36 + .../prototype/toLocaleString/length.js | 28 + .../prototype/toLocaleString/name.js | 26 + .../toLocaleString/not-a-constructor.js | 24 + .../prototype/toLocaleString/prop-desc.js | 24 + .../prototype/toLocaleString/return-string.js | 17 + .../prototype/toLocaleString/shell.js | 19 + .../prototype/toPlainDate/builtin.js | 36 + .../prototype/toPlainDate/length.js | 28 + .../prototype/toPlainDate/name.js | 26 + .../toPlainDate/not-a-constructor.js | 24 + .../prototype/toPlainDate/prop-desc.js | 24 + .../prototype/toPlainDate/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../balance-negative-time-units.js | 42 + .../prototype/toPlainDateTime/builtin.js | 36 + .../prototype/toPlainDateTime/length.js | 28 + .../prototype/toPlainDateTime/name.js | 26 + .../negative-epochnanoseconds.js | 25 + .../toPlainDateTime/not-a-constructor.js | 24 + .../toPlainDateTime/plain-custom-timezone.js | 44 + .../prototype/toPlainDateTime/prop-desc.js | 24 + .../prototype/toPlainDateTime/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/toPlainMonthDay/builtin.js | 36 + .../toPlainMonthDay/calendar-arguments.js | 32 + .../calendar-fields-iterable.js | 30 + ...romfields-called-with-options-undefined.js | 19 + .../toPlainMonthDay/calendar-result.js | 26 + .../prototype/toPlainMonthDay/length.js | 28 + .../prototype/toPlainMonthDay/name.js | 26 + .../toPlainMonthDay/not-a-constructor.js | 24 + .../prototype/toPlainMonthDay/prop-desc.js | 24 + .../prototype/toPlainMonthDay/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../balance-negative-time-units.js | 42 + .../prototype/toPlainTime/builtin.js | 36 + .../prototype/toPlainTime/length.js | 28 + .../prototype/toPlainTime/name.js | 26 + .../toPlainTime/negative-epochnanoseconds.js | 25 + .../toPlainTime/not-a-constructor.js | 24 + .../prototype/toPlainTime/prop-desc.js | 24 + .../prototype/toPlainTime/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/toPlainYearMonth/builtin.js | 36 + .../toPlainYearMonth/calendar-arguments.js | 32 + .../calendar-fields-iterable.js | 30 + .../toPlainYearMonth/calendar-result.js | 26 + ...romfields-called-with-options-undefined.js | 19 + .../prototype/toPlainYearMonth/length.js | 28 + .../prototype/toPlainYearMonth/name.js | 26 + .../toPlainYearMonth/not-a-constructor.js | 24 + .../prototype/toPlainYearMonth/prop-desc.js | 24 + .../prototype/toPlainYearMonth/shell.js | 19 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../toString/balance-negative-time-units.js | 43 + .../prototype/toString/builtin.js | 36 + .../toString/calendarname-invalid-string.js | 21 + .../toString/calendarname-undefined.js | 35 + .../toString/calendarname-wrong-type.js | 29 + .../fractionalseconddigits-invalid-string.js | 22 + .../toString/fractionalseconddigits-nan.js | 23 + .../fractionalseconddigits-non-integer.js | 23 + .../fractionalseconddigits-out-of-range.js | 23 + .../fractionalseconddigits-undefined.js | 27 + .../fractionalseconddigits-wrong-type.js | 28 + .../prototype/toString/length.js | 28 + .../ZonedDateTime/prototype/toString/name.js | 26 + .../toString/negative-epochnanoseconds.js | 24 + .../prototype/toString/not-a-constructor.js | 24 + .../toString/offset-invalid-string.js | 21 + .../prototype/toString/offset-undefined.js | 25 + .../prototype/toString/offset-wrong-type.js | 26 + .../prototype/toString/offset.js | 23 + .../prototype/toString/options-undefined.js | 31 + .../prototype/toString/prop-desc.js | 24 + .../toString/roundingmode-invalid-string.js | 16 + .../toString/roundingmode-undefined.js | 28 + .../toString/roundingmode-wrong-type.js | 18 + .../ZonedDateTime/prototype/toString/shell.js | 19 + .../toString/smallestunit-invalid-string.js | 14 + .../toString/smallestunit-plurals-accepted.js | 22 + .../toString/smallestunit-undefined.js | 23 + .../toString/smallestunit-valid-units.js | 31 + .../toString/smallestunit-wrong-type.js | 18 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../toString/timezonename-invalid-string.js | 21 + .../toString/timezonename-undefined.js | 25 + .../toString/timezonename-wrong-type.js | 26 + .../prototype/toString/year-format.js | 58 + ...tybag-offset-not-agreeing-with-timezone.js | 17 + ...ne-getoffsetnanosecondsfor-not-callable.js | 26 + .../until/balance-negative-time-units.js | 57 + .../ZonedDateTime/prototype/until/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 72 + ...r-dateuntil-called-with-copy-of-options.js | 36 + ...euntil-called-with-singular-largestunit.js | 117 + .../until/calendar-fields-iterable.js | 42 + .../until/calendar-temporal-object.js | 29 + .../until/infinity-throws-rangeerror.js | 26 + .../until/largestunit-invalid-string.js | 18 + .../until/largestunit-plurals-accepted.js | 28 + .../largestunit-smallestunit-mismatch.js | 22 + .../prototype/until/largestunit-undefined.js | 20 + .../prototype/until/largestunit-wrong-type.js | 19 + .../ZonedDateTime/prototype/until/length.js | 28 + .../ZonedDateTime/prototype/until/name.js | 26 + .../until/negative-epochnanoseconds.js | 25 + .../prototype/until/not-a-constructor.js | 24 + .../prototype/until/options-undefined.js | 30 + .../prototype/until/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 26 + .../prototype/until/roundingincrement-nan.js | 22 + .../until/roundingincrement-non-integer.js | 20 + .../until/roundingincrement-out-of-range.js | 21 + .../until/roundingincrement-undefined.js | 28 + .../until/roundingincrement-wrong-type.js | 28 + .../until/roundingmode-invalid-string.js | 17 + .../prototype/until/roundingmode-undefined.js | 30 + .../until/roundingmode-wrong-type.js | 19 + .../ZonedDateTime/prototype/until/shell.js | 19 + .../until/smallestunit-invalid-string.js | 18 + .../until/smallestunit-plurals-accepted.js | 28 + .../prototype/until/smallestunit-undefined.js | 20 + .../until/smallestunit-wrong-type.js | 19 + .../prototype/until/sub-minute-offset.js | 23 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + ...imezone-getpossibleinstantsfor-iterable.js | 41 + .../until/timezone-string-datetime.js | 46 + .../until/timezone-string-multiple-offsets.js | 22 + .../prototype/until/year-zero.js | 17 + .../zoneddatetime-string-multiple-offsets.js | 19 + .../prototype/until/zoneddatetime-string.js | 37 + .../prototype/valueOf/builtin.js | 36 + .../ZonedDateTime/prototype/valueOf/length.js | 28 + .../ZonedDateTime/prototype/valueOf/name.js | 26 + .../prototype/valueOf/not-a-constructor.js | 24 + .../prototype/valueOf/prop-desc.js | 24 + .../ZonedDateTime/prototype/valueOf/shell.js | 19 + .../prototype/weekOfYear/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../with/balance-negative-time-units.js | 65 + .../ZonedDateTime/prototype/with/builtin.js | 36 + .../with/calendar-fields-iterable.js | 38 + ...calendar-merge-fields-returns-primitive.js | 21 + .../with/copies-merge-fields-object.js | 62 + .../with/copy-properties-not-undefined.js | 52 + .../with/disambiguation-invalid-string.js | 21 + .../with/disambiguation-undefined.js | 34 + .../with/disambiguation-wrong-type.js | 25 + .../with/infinity-throws-rangeerror.js | 27 + .../ZonedDateTime/prototype/with/length.js | 28 + .../ZonedDateTime/prototype/with/name.js | 26 + .../prototype/with/not-a-constructor.js | 24 + .../prototype/with/offset-invalid-string.js | 21 + .../with/offset-property-sub-minute.js | 31 + .../prototype/with/offset-undefined.js | 26 + .../prototype/with/offset-wrong-type.js | 25 + .../prototype/with/options-undefined.js | 22 + .../prototype/with/overflow-invalid-string.js | 31 + .../prototype/with/overflow-undefined.js | 27 + .../prototype/with/overflow-wrong-type.js | 49 + .../ZonedDateTime/prototype/with/prop-desc.js | 24 + .../read-time-fields-before-datefromfields.js | 29 + .../prototype/with/receiver-offset-broken.js | 79 + .../ZonedDateTime/prototype/with/shell.js | 19 + .../prototype/with/subclassing-ignored.js | 31 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 38 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + ...imezone-getpossibleinstantsfor-iterable.js | 28 + .../prototype/withCalendar/builtin.js | 36 + .../withCalendar/calendar-temporal-object.js | 24 + .../prototype/withCalendar/length.js | 28 + .../withCalendar/missing-argument.js | 15 + .../prototype/withCalendar/name.js | 26 + .../withCalendar/not-a-constructor.js | 24 + .../prototype/withCalendar/prop-desc.js | 24 + .../prototype/withCalendar/shell.js | 19 + .../withCalendar/subclassing-ignored.js | 39 + .../withPlainDate/argument-plaindatetime.js | 32 + .../withPlainDate/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/withPlainDate/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 20 + ...romfields-called-with-options-undefined.js | 19 + .../withPlainDate/calendar-fields-iterable.js | 36 + .../withPlainDate/calendar-temporal-object.js | 31 + .../infinity-throws-rangeerror.js | 26 + .../prototype/withPlainDate/length.js | 28 + .../prototype/withPlainDate/name.js | 26 + .../negative-epochnanoseconds.js | 24 + .../withPlainDate/not-a-constructor.js | 24 + .../prototype/withPlainDate/prop-desc.js | 24 + .../prototype/withPlainDate/shell.js | 19 + .../withPlainDate/subclassing-ignored.js | 31 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/withPlainDate/year-zero.js | 20 + .../argument-string-no-implicit-midnight.js | 19 + ...-designator-required-for-disambiguation.js | 56 + .../argument-string-with-time-designator.js | 31 + .../argument-string-with-utc-designator.js | 24 + ...neddatetime-balance-negative-time-units.js | 48 + ...zoneddatetime-negative-epochnanoseconds.js | 25 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/withPlainTime/builtin.js | 36 + ...r-dateadd-called-with-options-undefined.js | 20 + .../withPlainTime/calendar-temporal-object.js | 28 + .../prototype/withPlainTime/length.js | 28 + .../prototype/withPlainTime/name.js | 26 + .../withPlainTime/not-a-constructor.js | 24 + .../plaintime-propertybag-no-time-units.js | 20 + .../prototype/withPlainTime/prop-desc.js | 24 + .../prototype/withPlainTime/shell.js | 19 + .../withPlainTime/subclassing-ignored.js | 31 + .../prototype/withPlainTime/time-undefined.js | 29 + ...one-getoffsetnanosecondsfor-non-integer.js | 19 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 19 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 28 + .../prototype/withPlainTime/year-zero.js | 24 + .../prototype/withTimeZone/builtin.js | 36 + .../prototype/withTimeZone/length.js | 28 + .../prototype/withTimeZone/name.js | 26 + .../withTimeZone/not-a-constructor.js | 24 + .../prototype/withTimeZone/prop-desc.js | 24 + .../prototype/withTimeZone/shell.js | 19 + .../withTimeZone/subclassing-ignored.js | 31 + .../withTimeZone/timezone-string-datetime.js | 47 + .../timezone-string-multiple-offsets.js | 19 + .../year/calendar-returns-infinity.js | 30 + .../ZonedDateTime/prototype/year/prop-desc.js | 17 + ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../built-ins/Temporal/ZonedDateTime/shell.js | 1498 ++++++ .../ZonedDateTime/timezone-string-datetime.js | 45 + .../built-ins/Temporal/getOwnPropertyNames.js | 25 + .../tests/test262/built-ins/Temporal/keys.js | 15 + .../test262/built-ins/Temporal/prop-desc.js | 19 + .../built-ins/Temporal/toStringTag/browser.js | 0 .../Temporal/toStringTag/prop-desc.js | 19 + .../built-ins/Temporal/toStringTag/shell.js | 0 .../built-ins/Temporal/toStringTag/string.js | 13 + .../TypedArray/prototype/at/BigInt/browser.js | 0 .../return-abrupt-from-this-out-of-bounds.js | 62 + .../TypedArray/prototype/at/BigInt/shell.js | 42 + .../BigInt/resizable-array-buffer-auto.js | 56 + .../BigInt/resizable-array-buffer-fixed.js | 49 + .../byteLength/resizable-array-buffer-auto.js | 7 + .../BigInt/resizable-array-buffer-auto.js | 53 + .../BigInt/resizable-array-buffer-fixed.js | 49 + .../byteOffset/resizable-array-buffer-auto.js | 12 +- .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/copyWithin/byteoffset.js | 35 + .../copyWithin/coerced-values-target.js | 8 + .../return-abrupt-from-this-out-of-bounds.js | 6 +- .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/every/callbackfn-resize.js | 76 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/filter/callbackfn-resize.js | 79 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/find/callbackfn-resize.js | 76 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/findIndex/callbackfn-resize.js | 76 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/findLast/callbackfn-resize.js | 76 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../findLastIndex/callbackfn-resize.js | 76 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/forEach/callbackfn-resize.js | 74 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 2 +- .../BigInt/resizable-array-buffer-auto.js | 56 + .../BigInt/resizable-array-buffer-fixed.js | 49 + .../length/resizable-array-buffer-auto.js | 7 + .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/map/callbackfn-resize.js | 81 + .../return-abrupt-from-this-out-of-bounds.js | 2 +- .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/reduce/callbackfn-resize.js | 78 + .../return-abrupt-from-this-out-of-bounds.js | 2 +- .../return-abrupt-from-this-out-of-bounds.js | 62 + .../reduceRight/callbackfn-resize.js | 78 + .../return-abrupt-from-this-out-of-bounds.js | 2 +- .../return-abrupt-from-this-out-of-bounds.js | 62 + ...et-values-same-buffer-same-type-resized.js | 48 + .../typedarray-arg-target-out-of-bounds.js | 46 + ...ffer-detached-on-get-src-value-no-throw.js | 38 + ...buffer-detached-on-get-src-value-throws.js | 47 - .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 2 +- .../return-abrupt-from-this-out-of-bounds.js | 62 + .../prototype/some/callbackfn-resize.js | 76 + .../return-abrupt-from-this-out-of-bounds.js | 2 +- .../sort/BigInt/detached-buffer-comparefn.js | 40 - .../return-abrupt-from-this-out-of-bounds.js | 62 + .../sort/detached-buffer-comparefn-coerce.js | 46 - .../sort/detached-buffer-comparefn.js | 40 - .../return-abrupt-from-this-out-of-bounds.js | 2 +- .../prototype/sort/sort-tonumber.js | 16 +- .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 2 +- .../return-abrupt-from-this-out-of-bounds.js | 62 + .../return-abrupt-from-this-out-of-bounds.js | 2 +- ...d-when-species-retrieved-different-type.js | 63 - ...tached-when-species-retrieved-same-type.js | 66 - .../other-ctor-buffer-ctor-access-throws.js | 43 - ...or-custom-species-proto-from-ctor-realm.js | 60 - .../other-ctor-buffer-ctor-custom-species.js | 54 - ...ther-ctor-buffer-ctor-not-object-throws.js | 63 - ...-ctor-buffer-ctor-species-access-throws.js | 47 - ...tor-buffer-ctor-species-not-ctor-throws.js | 49 - ...or-buffer-ctor-species-prototype-throws.js | 61 - .../same-ctor-buffer-ctor-access-throws.js | 48 - ...or-species-custom-proto-from-ctor-realm.js | 70 - .../same-ctor-buffer-ctor-species-custom.js | 62 - .../same-ctor-buffer-ctor-species-not-ctor.js | 51 - ...or-buffer-ctor-species-prototype-throws.js | 64 - .../same-ctor-buffer-ctor-species-throws.js | 51 - ...e-ctor-buffer-ctor-value-not-obj-throws.js | 67 - .../ctors-bigint/typedarray-arg/shell.js | 18 - .../ctors/no-species.js | 32 + ...d-when-species-retrieved-different-type.js | 63 - ...tached-when-species-retrieved-same-type.js | 66 - .../other-ctor-buffer-ctor-access-throws.js | 43 - ...or-custom-species-proto-from-ctor-realm.js | 61 - .../other-ctor-buffer-ctor-custom-species.js | 54 - ...ther-ctor-buffer-ctor-not-object-throws.js | 63 - ...-ctor-buffer-ctor-species-access-throws.js | 47 - ...tor-buffer-ctor-species-not-ctor-throws.js | 49 - .../other-ctor-buffer-ctor-species-null.js | 46 - ...or-buffer-ctor-species-prototype-throws.js | 61 - ...ther-ctor-buffer-ctor-species-undefined.js | 45 - ...s-when-species-retrieved-different-type.js | 83 - ...bounds-when-species-retrieved-same-type.js | 83 - .../same-ctor-buffer-ctor-access-throws.js | 48 - ...or-species-custom-proto-from-ctor-realm.js | 70 - .../same-ctor-buffer-ctor-species-custom.js | 62 - .../same-ctor-buffer-ctor-species-not-ctor.js | 51 - ...or-buffer-ctor-species-prototype-throws.js | 64 - .../same-ctor-buffer-ctor-species-throws.js | 51 - ...e-ctor-buffer-ctor-value-not-obj-throws.js | 67 - .../ctors/typedarray-arg/shell.js | 18 - .../resizable-array-buffer-auto.js | 7 + ...ger-indexes-resizable-array-buffer-auto.js | 9 + .../gc-cleanup-not-prevented-with-wr-deref.js | 2 +- .../WeakRef/prototype/deref/shell.js | 2 +- .../built-ins/decodeURI/S15.1.3.1_A2.1_T1.js | 20 +- .../decodeURIComponent/S15.1.3.2_A2.1_T1.js | 20 +- .../built-ins/encodeURI/S15.1.3.3_A1.1_T1.js | 1 - .../built-ins/encodeURI/S15.1.3.3_A1.1_T2.js | 1 - .../built-ins/encodeURI/S15.1.3.3_A1.2_T1.js | 1 - .../built-ins/encodeURI/S15.1.3.3_A1.2_T2.js | 1 - .../built-ins/encodeURI/S15.1.3.3_A1.3_T1.js | 1 - .../encodeURIComponent/S15.1.3.4_A1.1_T1.js | 1 - .../encodeURIComponent/S15.1.3.4_A1.1_T2.js | 1 - .../encodeURIComponent/S15.1.3.4_A1.2_T1.js | 1 - .../encodeURIComponent/S15.1.3.4_A1.2_T2.js | 1 - .../encodeURIComponent/S15.1.3.4_A1.3_T1.js | 1 - .../built-ins/isFinite/S15.1.2.5_A2.6.js | 6 +- .../built-ins/isFinite/S15.1.2.5_A2.7.js | 11 +- .../test262/built-ins/isNaN/S15.1.2.4_A2.6.js | 6 +- .../test262/built-ins/isNaN/S15.1.2.4_A2.7.js | 11 +- .../built-ins/parseFloat/S15.1.2.3_A2_T10.js | 15 - .../built-ins/parseFloat/S15.1.2.3_A6.js | 1 - .../built-ins/parseInt/S15.1.2.2_A8.js | 1 - js/src/tests/test262/harness/arrayContains.js | 26 - .../harness/assert-throws-custom-typeerror.js | 60 + .../harness/assert-throws-same-realm.js | 32 + .../harness/compare-array-arguments.js | 40 + .../harness/compare-array-arraylike.js | 36 + .../compare-array-different-elements.js | 6 +- .../harness/compare-array-different-length.js | 13 +- .../test262/harness/compare-array-empty.js | 4 +- .../test262/harness/compare-array-message.js | 25 + ...are-array-same-elements-different-order.js | 6 +- .../compare-array-same-elements-same-order.js | 4 +- .../harness/compare-array-samevalue.js | 6 +- .../test262/harness/compare-array-sparse.js | 31 +- .../test262/harness/compare-array-symbol.js | 2 +- js/src/tests/test262/harness/shell.js | 1529 +++++- .../temporalHelpers-one-shift-time-zone.js | 83 + .../tests/test262/harness/testTypedArray.js | 32 +- .../prototype/resolvedOptions/basic.js | 26 +- .../prototype/resolvedOptions/order.js | 17 +- .../temporal-objects-resolved-time-zone.js | 40 + ...ne-getoffsetnanosecondsfor-not-callable.js | 52 + .../temporal-objects-resolved-time-zone.js | 39 + ...ne-getoffsetnanosecondsfor-not-callable.js | 57 + .../formatRangeToParts/pattern-on-calendar.js | 21 +- .../prototype/formatRangeToParts/shell.js | 329 ++ .../temporal-objects-resolved-time-zone.js | 106 + ...ne-getoffsetnanosecondsfor-not-callable.js | 57 + .../formatToParts/pattern-on-calendar.js | 21 +- .../prototype/formatToParts/shell.js | 329 ++ .../temporal-objects-resolved-time-zone.js | 99 + ...ne-getoffsetnanosecondsfor-not-callable.js | 52 + .../prototype/resolvedOptions/basic.js | 24 +- .../resolvedOptions/order-dayPeriod.js | 5 +- .../order-fractionalSecondDigits.js | 5 +- .../prototype/resolvedOptions/order-style.js | 5 +- .../prototype/resolvedOptions/order.js | 5 +- .../prototype/resolvedOptions/shell.js | 31 - .../prototype/of/type-calendar-invalid.js | 16 + .../prototype/of/type-calendar-valid.js | 5 - .../test262/intl402/DurationFormat/browser.js | 0 .../DurationFormat/instance/browser.js | 0 .../DurationFormat/instance/extensibility.js | 25 + .../intl402/DurationFormat/instance/length.js | 36 + .../intl402/DurationFormat/instance/name.js | 32 + .../DurationFormat/instance/prop-desc.js | 35 + .../DurationFormat/instance/prototype.js | 23 + .../intl402/DurationFormat/instance/shell.js | 0 .../DurationFormat/prototype/browser.js | 0 .../prototype/constructor/browser.js | 0 .../prototype/constructor/prop-desc.js | 33 + .../prototype/constructor/shell.js | 0 .../prototype/constructor/value.js | 15 + .../prototype/format/browser.js | 0 .../DurationFormat/prototype/format/length.js | 39 + .../DurationFormat/prototype/format/name.js | 29 + .../prototype/format/prop-desc.js | 24 + .../DurationFormat/prototype/format/shell.js | 0 .../prototype/format/throw-invoked-as-func.js | 24 + .../prototype/formatToParts/browser.js | 0 .../prototype/formatToParts/length.js | 39 + .../prototype/formatToParts/name.js | 29 + .../prototype/formatToParts/prop-desc.js | 24 + .../prototype/formatToParts/shell.js | 0 .../formatToParts/throw-invoked-as-func.js | 24 + .../prototype/prototype_attributes.js | 18 + .../prototype/resolvedOptions/browser.js | 0 .../prototype/resolvedOptions/length.js | 39 + .../prototype/resolvedOptions/name.js | 29 + .../prototype/resolvedOptions/prop-desc.js | 24 + .../prototype/resolvedOptions/shell.js | 0 .../resolvedOptions/throw-invoked-as-func.js | 24 + .../intl402/DurationFormat/prototype/shell.js | 0 .../prototype/toStringTag/browser.js | 0 .../prototype/toStringTag/shell.js | 0 .../prototype/toStringTag/toString.js | 20 + .../prototype/toStringTag/toStringTag.js | 28 + .../test262/intl402/DurationFormat/shell.js | 0 .../intl402/Intl/DateTimeFormat/browser.js | 0 .../Intl/DateTimeFormat/prototype/browser.js | 0 .../prototype/formatRange/browser.js | 0 .../fails-on-distinct-temporal-types.js | 36 + .../prototype/formatRange/shell.js | 0 .../prototype/formatRangeToParts/browser.js | 0 .../fails-on-distinct-temporal-types.js | 36 + .../prototype/formatRangeToParts/shell.js | 0 .../Intl/DateTimeFormat/prototype/shell.js | 0 .../intl402/Intl/DateTimeFormat/shell.js | 0 .../Intl/getCanonicalLocales/duplicates.js | 7 +- .../locales-is-not-a-string.js | 2 +- .../intl402/Intl/getCanonicalLocales/main.js | 2 +- .../overriden-arg-length.js | 28 +- .../getCanonicalLocales/overriden-push.js | 2 +- .../Intl/getCanonicalLocales/to-string.js | 2 +- .../Intl/getCanonicalLocales/weird-cases.js | 2 +- .../intl402/Intl/supportedValuesOf/browser.js | 0 .../intl402/Intl/supportedValuesOf/builtin.js | 44 + .../calendars-accepted-by-DateTimeFormat.js | 47 + .../calendars-accepted-by-DisplayNames.js | 47 + .../Intl/supportedValuesOf/calendars.js | 56 + .../supportedValuesOf/coerced-to-string.js | 38 + .../collations-accepted-by-Collator.js | 83 + .../Intl/supportedValuesOf/collations.js | 58 + .../currencies-accepted-by-DisplayNames.js | 53 + .../currencies-accepted-by-NumberFormat.js | 46 + .../Intl/supportedValuesOf/currencies.js | 50 + .../Intl/supportedValuesOf/invalid-key.js | 45 + .../intl402/Intl/supportedValuesOf/length.js | 32 + .../intl402/Intl/supportedValuesOf/name.js | 34 + ...eringSystems-accepted-by-DateTimeFormat.js | 50 + ...mberingSystems-accepted-by-NumberFormat.js | 50 + ...gSystems-accepted-by-RelativeTimeFormat.js | 50 + ...eringSystems-with-simple-digit-mappings.js | 38 + .../supportedValuesOf/numberingSystems.js | 57 + .../Intl/supportedValuesOf/prop-desc.js | 25 + .../intl402/Intl/supportedValuesOf/shell.js | 19 + .../timeZones-accepted-by-DateTimeFormat.js | 46 + .../Intl/supportedValuesOf/timeZones.js | 59 + .../units-accepted-by-NumberFormat.js | 47 + .../intl402/Intl/supportedValuesOf/units.js | 50 + .../formatToParts/iterable-undefined.js | 2 +- .../prototype/resolvedOptions/order.js | 11 +- .../prototype/weekInfo/output-object-keys.js | 21 +- ...onstructor-options-roundingMode-invalid.js | 36 + ...ons-throwing-getters-rounding-increment.js | 20 + ...-options-throwing-getters-rounding-mode.js | 20 + ...ions-throwing-getters-rounding-priority.js | 20 + ...-throwing-getters-trailing-zero-display.js | 20 + .../constructor-roundingIncrement-invalid.js | 47 + .../constructor-roundingIncrement.js | 52 + .../constructor-signDisplay-negative.js | 28 + ...constructor-trailingZeroDisplay-invalid.js | 34 + .../constructor-trailingZeroDisplay.js | 37 + .../intl402/NumberFormat/constructor-unit.js | 47 +- ...mat-max-min-fraction-significant-digits.js | 30 + .../format/format-rounding-increment-1.js | 42 + .../format/format-rounding-increment-10.js | 42 + .../format/format-rounding-increment-100.js | 42 + .../format/format-rounding-increment-1000.js | 42 + .../format/format-rounding-increment-2.js | 42 + .../format/format-rounding-increment-20.js | 42 + .../format/format-rounding-increment-200.js | 42 + .../format/format-rounding-increment-2000.js | 42 + .../format/format-rounding-increment-25.js | 42 + .../format/format-rounding-increment-250.js | 42 + .../format/format-rounding-increment-2500.js | 42 + .../format/format-rounding-increment-5.js | 42 + .../format/format-rounding-increment-50.js | 42 + .../format/format-rounding-increment-500.js | 42 + .../format/format-rounding-increment-5000.js | 42 + .../format/format-rounding-mode-ceil.js | 35 + .../format/format-rounding-mode-expand.js | 35 + .../format/format-rounding-mode-floor.js | 35 + .../format/format-rounding-mode-half-ceil.js | 36 + .../format/format-rounding-mode-half-even.js | 37 + .../format-rounding-mode-half-expand.js | 36 + .../format/format-rounding-mode-half-floor.js | 36 + .../format/format-rounding-mode-half-trunc.js | 36 + .../format/format-rounding-mode-trunc.js | 35 + .../format/format-rounding-priority-auto.js | 50 + ...format-rounding-priority-less-precision.js | 50 + ...format-rounding-priority-more-precision.js | 50 + .../prototype/format/numbering-systems.js | 84 +- .../format/signDisplay-currency-de-DE.js | 2 +- .../format/signDisplay-currency-en-US.js | 2 +- .../format/signDisplay-currency-ja-JP.js | 2 +- .../format/signDisplay-currency-ko-KR.js | 2 +- .../format/signDisplay-currency-zh-TW.js | 2 +- .../signDisplay-negative-currency-de-DE.js | 20 + .../signDisplay-negative-currency-en-US.js | 20 + .../signDisplay-negative-currency-ja-JP.js | 20 + .../signDisplay-negative-currency-ko-KR.js | 20 + .../signDisplay-negative-currency-zh-TW.js | 20 + .../format/signDisplay-negative-de-DE.js | 23 + .../format/signDisplay-negative-en-US.js | 23 + .../format/signDisplay-negative-ja-JP.js | 23 + .../format/signDisplay-negative-ko-KR.js | 23 + .../format/signDisplay-negative-zh-TW.js | 23 + .../NumberFormat/prototype/format/units.js | 47 +- .../prototype/format/useGrouping-de-DE.js | 33 + .../prototype/format/useGrouping-en-IN.js | 34 + .../prototype/format/useGrouping-en-US.js | 34 + .../format/useGrouping-extended-de-DE.js | 36 + .../format/useGrouping-extended-en-IN.js | 36 + .../format/useGrouping-extended-en-US.js | 36 + .../prototype/format/value-decimal-string.js | 27 + .../prototype/format/value-tonumber.js | 4 +- ...rgument-to-Intlmathematicalvalue-throws.js | 24 + .../prototype/formatRange/browser.js | 0 .../prototype/formatRange/builtin.js | 32 + .../prototype/formatRange/en-US.js | 40 + .../prototype/formatRange/invoked-as-func.js | 23 + .../prototype/formatRange/length.js | 17 + .../prototype/formatRange/name.js | 17 + .../formatRange/nan-arguments-throws.js | 32 + .../prototype/formatRange/prop-desc.js | 23 + .../prototype/formatRange/pt-PT.js | 40 + .../prototype/formatRange/shell.js | 19 + .../formatRange/undefined-arguments-throws.js | 23 + .../formatRange/x-greater-than-y-throws.js | 54 + ...rgument-to-Intlmathematicalvalue-throws.js | 24 + .../prototype/formatRangeToParts/browser.js | 0 .../prototype/formatRangeToParts/builtin.js | 32 + .../prototype/formatRangeToParts/en-US.js | 54 + .../formatRangeToParts/invoked-as-func.js | 23 + .../prototype/formatRangeToParts/length.js | 17 + .../prototype/formatRangeToParts/name.js | 17 + .../nan-arguments-throws.js | 32 + .../prototype/formatRangeToParts/prop-desc.js | 23 + .../prototype/formatRangeToParts/shell.js | 19 + .../undefined-arguments-throws.js | 23 + .../x-greater-than-y-throws.js | 54 + .../signDisplay-currency-de-DE.js | 14 +- .../signDisplay-currency-en-US.js | 14 +- .../signDisplay-currency-ja-JP.js | 14 +- .../signDisplay-currency-ko-KR.js | 14 +- .../signDisplay-currency-zh-TW.js | 14 +- .../signDisplay-negative-currency-de-DE.js | 56 + .../signDisplay-negative-currency-en-US.js | 56 + .../signDisplay-negative-currency-ja-JP.js | 56 + .../signDisplay-negative-currency-ko-KR.js | 56 + .../signDisplay-negative-currency-zh-TW.js | 56 + .../signDisplay-negative-de-DE.js | 36 + .../signDisplay-negative-en-US.js | 36 + .../signDisplay-negative-ja-JP.js | 36 + .../signDisplay-negative-ko-KR.js | 36 + .../signDisplay-negative-zh-TW.js | 36 + .../prototype/resolvedOptions/basic.js | 5 +- .../prototype/resolvedOptions/order.js | 11 +- .../prototype/resolvedOptions/roundingMode.js | 43 + .../test-option-roundingPriority.js | 19 + .../test-option-useGrouping-extended.js | 56 + .../NumberFormat/test-option-useGrouping.js | 30 +- .../prototype/resolvedOptions/order.js | 11 +- .../selectRange/argument-tonumber-throws.js | 27 + .../prototype/selectRange/browser.js | 0 .../prototype/selectRange/default-en-us.js | 17 + .../prototype/selectRange/invoked-as-func.js | 24 + .../prototype/selectRange/length.js | 19 + .../PluralRules/prototype/selectRange/name.js | 20 + .../selectRange/nan-arguments-throws.js | 24 + .../prototype/selectRange/prop-desc.js | 24 + .../prototype/selectRange/shell.js | 0 .../selectRange/undefined-arguments-throws.js | 23 + .../selectRange/x-greater-than-y-throws.js | 21 + .../prototype/resolvedOptions/order.js | 11 +- .../prototype/resolvedOptions/order.js | 11 +- .../intl402/Temporal/Calendar/browser.js | 0 .../intl402/Temporal/Calendar/from/basic.js | 21 + .../intl402/Temporal/Calendar/from/browser.js | 0 .../intl402/Temporal/Calendar/from/shell.js | 0 .../Temporal/Calendar/prototype/browser.js | 0 .../Calendar/prototype/dateAdd/browser.js | 0 .../date-infinity-throws-rangeerror.js | 26 + .../Calendar/prototype/dateAdd/shell.js | 1498 ++++++ .../prototype/dateFromFields/browser.js | 0 .../infinity-throws-rangeerror.js | 26 + .../prototype/dateFromFields/shell.js | 1498 ++++++ .../argument-infinity-throws-rangeerror.js | 32 + .../Calendar/prototype/dateUntil/browser.js | 0 .../Calendar/prototype/dateUntil/shell.js | 1498 ++++++ .../Calendar/prototype/day/browser.js | 0 .../day/infinity-throws-rangeerror.js | 24 + .../Temporal/Calendar/prototype/day/shell.js | 1498 ++++++ .../Calendar/prototype/dayOfWeek/browser.js | 0 .../dayOfWeek/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/dayOfWeek/shell.js | 1498 ++++++ .../Calendar/prototype/dayOfYear/browser.js | 0 .../dayOfYear/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/dayOfYear/shell.js | 1498 ++++++ .../Calendar/prototype/daysInMonth/browser.js | 0 .../daysInMonth/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/daysInMonth/shell.js | 1498 ++++++ .../Calendar/prototype/daysInWeek/browser.js | 0 .../daysInWeek/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/daysInWeek/shell.js | 1498 ++++++ .../Calendar/prototype/daysInYear/browser.js | 0 .../daysInYear/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/daysInYear/shell.js | 1498 ++++++ .../prototype/era/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + .../Calendar/prototype/era/branding.js | 0 .../Calendar/prototype/era/browser.js | 0 .../Calendar/prototype/era/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../era/infinity-throws-rangeerror.js | 24 + .../Temporal/Calendar/prototype/era/length.js | 28 + .../Temporal/Calendar/prototype/era/name.js | 26 + .../prototype/era/not-a-constructor.js | 24 + .../Calendar/prototype/era/prop-desc.js | 24 + .../Temporal/Calendar/prototype/era/shell.js | 1517 ++++++ .../Calendar/prototype/era/year-zero.js | 20 + .../eraYear/argument-string-invalid.js | 64 + .../argument-string-with-utc-designator.js | 24 + ...ne-getoffsetnanosecondsfor-not-callable.js | 23 + .../Calendar/prototype/eraYear/branding.js | 0 .../Calendar/prototype/eraYear/browser.js | 0 .../Calendar/prototype/eraYear/builtin.js | 36 + ...romfields-called-with-options-undefined.js | 18 + .../eraYear/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/eraYear/length.js | 28 + .../Calendar/prototype/eraYear/name.js | 26 + .../prototype/eraYear/not-a-constructor.js | 24 + .../Calendar/prototype/eraYear/prop-desc.js | 24 + .../Calendar/prototype/eraYear/shell.js | 1517 ++++++ .../Calendar/prototype/eraYear/year-zero.js | 20 + .../Calendar/prototype/inLeapYear/browser.js | 0 .../inLeapYear/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/inLeapYear/shell.js | 1498 ++++++ .../Calendar/prototype/month/browser.js | 0 .../month/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/month/shell.js | 1498 ++++++ .../Calendar/prototype/monthCode/browser.js | 0 .../monthCode/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/monthCode/shell.js | 1498 ++++++ .../prototype/monthDayFromFields/browser.js | 0 .../infinity-throws-rangeerror.js | 26 + .../prototype/monthDayFromFields/shell.js | 1498 ++++++ .../prototype/monthsInYear/browser.js | 0 .../infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/monthsInYear/shell.js | 1498 ++++++ .../Temporal/Calendar/prototype/shell.js | 0 .../Calendar/prototype/weekOfYear/browser.js | 0 .../weekOfYear/infinity-throws-rangeerror.js | 24 + .../Calendar/prototype/weekOfYear/shell.js | 1498 ++++++ .../Calendar/prototype/year/browser.js | 0 .../year/infinity-throws-rangeerror.js | 24 + .../Temporal/Calendar/prototype/year/shell.js | 1498 ++++++ .../prototype/yearMonthFromFields/browser.js | 0 .../infinity-throws-rangeerror.js | 26 + .../prototype/yearMonthFromFields/shell.js | 1498 ++++++ .../intl402/Temporal/Calendar/shell.js | 0 .../intl402/Temporal/Duration/browser.js | 0 .../Duration/prototype/add/browser.js | 0 .../relativeto-infinity-throws-rangeerror.js | 24 + .../add/relativeto-string-datetime.js | 31 + .../Temporal/Duration/prototype/add/shell.js | 1498 ++++++ .../Temporal/Duration/prototype/browser.js | 0 .../Duration/prototype/round/browser.js | 0 .../relativeto-infinity-throws-rangeerror.js | 24 + .../round/relativeto-string-datetime.js | 31 + .../Duration/prototype/round/shell.js | 1498 ++++++ .../Temporal/Duration/prototype/shell.js | 0 .../Duration/prototype/subtract/browser.js | 0 .../relativeto-infinity-throws-rangeerror.js | 24 + .../subtract/relativeto-string-datetime.js | 31 + .../Duration/prototype/subtract/shell.js | 1498 ++++++ .../Duration/prototype/total/browser.js | 0 .../relativeto-infinity-throws-rangeerror.js | 24 + .../total/relativeto-string-datetime.js | 30 + .../Duration/prototype/total/shell.js | 1498 ++++++ .../intl402/Temporal/Duration/shell.js | 0 .../intl402/Temporal/Instant/browser.js | 0 .../Temporal/Instant/prototype/browser.js | 0 .../Temporal/Instant/prototype/shell.js | 0 .../prototype/toLocaleString/browser.js | 0 .../toLocaleString/locales-undefined.js | 21 + .../toLocaleString/options-conflict.js | 50 + .../toLocaleString/options-undefined.js | 21 + .../Instant/prototype/toLocaleString/shell.js | 0 .../Instant/prototype/toString/browser.js | 0 .../Instant/prototype/toString/shell.js | 0 .../toString/timezone-string-datetime.js | 31 + .../prototype/toZonedDateTime/browser.js | 0 .../prototype/toZonedDateTime/shell.js | 0 .../timezone-string-datetime.js | 31 + .../prototype/toZonedDateTimeISO/browser.js | 0 .../prototype/toZonedDateTimeISO/shell.js | 0 .../timezone-string-datetime.js | 31 + .../test262/intl402/Temporal/Instant/shell.js | 0 .../test262/intl402/Temporal/Now/browser.js | 0 .../intl402/Temporal/Now/plainDate/browser.js | 0 .../Temporal/Now/plainDate/calendar-string.js | 15 + .../intl402/Temporal/Now/plainDate/shell.js | 0 .../Temporal/Now/plainDateTime/browser.js | 0 .../Now/plainDateTime/calendar-string.js | 15 + .../Temporal/Now/plainDateTime/shell.js | 0 .../Temporal/Now/plainDateTimeISO/browser.js | 0 .../Temporal/Now/plainDateTimeISO/shell.js | 0 .../timezone-string-datetime.js | 36 + .../test262/intl402/Temporal/Now/shell.js | 0 .../Temporal/Now/zonedDateTime/browser.js | 0 .../Now/zonedDateTime/calendar-string.js | 20 + .../zonedDateTime/calendar-timezone-string.js | 18 + .../Temporal/Now/zonedDateTime/shell.js | 0 .../zonedDateTime/timezone-string-datetime.js | 29 + .../Temporal/Now/zonedDateTimeISO/browser.js | 0 .../Temporal/Now/zonedDateTimeISO/shell.js | 0 .../timezone-string-datetime.js | 29 + .../Now/zonedDateTimeISO/timezone-string.js | 18 + .../intl402/Temporal/PlainDate/browser.js | 0 .../Temporal/PlainDate/compare/browser.js | 0 .../compare/infinity-throws-rangeerror.js | 31 + .../Temporal/PlainDate/compare/shell.js | 1498 ++++++ .../Temporal/PlainDate/from/browser.js | 0 .../from/infinity-throws-rangeerror.js | 25 + .../intl402/Temporal/PlainDate/from/shell.js | 1498 ++++++ .../Temporal/PlainDate/prototype/browser.js | 0 .../PlainDate/prototype/equals/browser.js | 0 .../equals/infinity-throws-rangeerror.js | 24 + .../PlainDate/prototype/equals/shell.js | 1498 ++++++ .../PlainDate/prototype/era/branding.js | 0 .../PlainDate/prototype/era/browser.js | 0 .../PlainDate/prototype/era/prop-desc.js | 17 + .../Temporal/PlainDate/prototype/era/shell.js | 0 .../PlainDate/prototype/eraYear/branding.js | 0 .../PlainDate/prototype/eraYear/browser.js | 0 .../eraYear/calendar-returns-infinity.js | 30 + .../PlainDate/prototype/eraYear/prop-desc.js | 17 + .../PlainDate/prototype/eraYear/shell.js | 0 .../Temporal/PlainDate/prototype/shell.js | 0 .../PlainDate/prototype/since/browser.js | 0 .../since/infinity-throws-rangeerror.js | 24 + .../PlainDate/prototype/since/shell.js | 1498 ++++++ .../prototype/toLocaleString/browser.js | 0 .../toLocaleString/locales-undefined.js | 21 + .../toLocaleString/options-conflict.js | 40 + .../toLocaleString/options-undefined.js | 21 + .../toLocaleString/resolved-time-zone.js | 16 + .../prototype/toLocaleString/shell.js | 0 ...ne-getoffsetnanosecondsfor-not-callable.js | 25 + .../prototype/toZonedDateTime/browser.js | 0 .../prototype/toZonedDateTime/shell.js | 0 .../timezone-string-datetime.js | 31 + .../PlainDate/prototype/until/browser.js | 0 .../until/infinity-throws-rangeerror.js | 24 + .../PlainDate/prototype/until/shell.js | 1498 ++++++ .../intl402/Temporal/PlainDate/shell.js | 0 .../intl402/Temporal/PlainDateTime/browser.js | 0 .../Temporal/PlainDateTime/compare/browser.js | 0 .../compare/infinity-throws-rangeerror.js | 31 + .../Temporal/PlainDateTime/compare/shell.js | 1498 ++++++ .../Temporal/PlainDateTime/from/browser.js | 0 .../from/infinity-throws-rangeerror.js | 25 + .../Temporal/PlainDateTime/from/shell.js | 1498 ++++++ .../PlainDateTime/prototype/browser.js | 0 .../PlainDateTime/prototype/equals/browser.js | 0 .../equals/infinity-throws-rangeerror.js | 24 + .../PlainDateTime/prototype/equals/shell.js | 1498 ++++++ .../PlainDateTime/prototype/era/branding.js | 0 .../PlainDateTime/prototype/era/browser.js | 0 .../PlainDateTime/prototype/era/prop-desc.js | 17 + .../PlainDateTime/prototype/era/shell.js | 0 .../prototype/eraYear/branding.js | 0 .../prototype/eraYear/browser.js | 0 .../eraYear/calendar-returns-infinity.js | 30 + .../prototype/eraYear/prop-desc.js | 17 + .../PlainDateTime/prototype/eraYear/shell.js | 0 .../Temporal/PlainDateTime/prototype/shell.js | 0 .../PlainDateTime/prototype/since/browser.js | 0 .../since/infinity-throws-rangeerror.js | 24 + .../PlainDateTime/prototype/since/shell.js | 1498 ++++++ .../prototype/toLocaleString/browser.js | 0 .../toLocaleString/locales-undefined.js | 21 + .../toLocaleString/options-conflict.js | 50 + .../toLocaleString/options-undefined.js | 21 + .../toLocaleString/resolved-time-zone.js | 20 + .../prototype/toLocaleString/shell.js | 0 ...ne-getoffsetnanosecondsfor-not-callable.js | 25 + .../prototype/toZonedDateTime/browser.js | 0 .../prototype/toZonedDateTime/shell.js | 0 .../timezone-string-datetime.js | 31 + .../PlainDateTime/prototype/until/browser.js | 0 .../until/infinity-throws-rangeerror.js | 24 + .../PlainDateTime/prototype/until/shell.js | 1498 ++++++ .../prototype/withPlainDate/browser.js | 0 .../infinity-throws-rangeerror.js | 24 + .../prototype/withPlainDate/shell.js | 1498 ++++++ .../intl402/Temporal/PlainDateTime/shell.js | 0 .../intl402/Temporal/PlainMonthDay/browser.js | 0 .../PlainMonthDay/prototype/browser.js | 0 .../PlainMonthDay/prototype/equals/browser.js | 0 .../equals/infinity-throws-rangeerror.js | 24 + .../PlainMonthDay/prototype/equals/shell.js | 1498 ++++++ .../Temporal/PlainMonthDay/prototype/shell.js | 0 .../prototype/toLocaleString/browser.js | 0 .../toLocaleString/locales-undefined.js | 22 + .../toLocaleString/options-undefined.js | 22 + .../toLocaleString/resolved-time-zone.js | 16 + .../prototype/toLocaleString/shell.js | 0 ...ne-getoffsetnanosecondsfor-not-callable.js | 25 + .../prototype/toPlainDate/browser.js | 0 .../toPlainDate/infinity-throws-rangeerror.js | 23 + .../prototype/toPlainDate/shell.js | 1498 ++++++ .../intl402/Temporal/PlainMonthDay/shell.js | 0 .../intl402/Temporal/PlainTime/browser.js | 0 .../Temporal/PlainTime/prototype/browser.js | 0 .../Temporal/PlainTime/prototype/shell.js | 0 .../prototype/toLocaleString/browser.js | 0 .../toLocaleString/locales-undefined.js | 21 + .../toLocaleString/options-conflict.js | 40 + .../toLocaleString/options-undefined.js | 21 + .../toLocaleString/resolved-time-zone.js | 20 + .../prototype/toLocaleString/shell.js | 0 ...ne-getoffsetnanosecondsfor-not-callable.js | 25 + .../prototype/toPlainDateTime/browser.js | 0 .../infinity-throws-rangeerror.js | 24 + .../prototype/toPlainDateTime/shell.js | 1498 ++++++ .../prototype/toZonedDateTime/browser.js | 0 .../plaindate-infinity-throws-rangeerror.js | 24 + .../prototype/toZonedDateTime/shell.js | 1498 ++++++ .../timezone-string-datetime.js | 31 + .../intl402/Temporal/PlainTime/shell.js | 0 .../Temporal/PlainYearMonth/browser.js | 0 .../PlainYearMonth/compare/browser.js | 0 .../compare/infinity-throws-rangeerror.js | 31 + .../Temporal/PlainYearMonth/compare/shell.js | 1498 ++++++ .../PlainYearMonth/from/argument-object.js | 20 + .../Temporal/PlainYearMonth/from/browser.js | 0 .../from/infinity-throws-rangeerror.js | 25 + .../Temporal/PlainYearMonth/from/shell.js | 1498 ++++++ .../PlainYearMonth/prototype/browser.js | 0 .../prototype/equals/browser.js | 0 .../equals/infinity-throws-rangeerror.js | 24 + .../PlainYearMonth/prototype/equals/shell.js | 1498 ++++++ .../PlainYearMonth/prototype/era/branding.js | 0 .../PlainYearMonth/prototype/era/browser.js | 0 .../PlainYearMonth/prototype/era/prop-desc.js | 17 + .../PlainYearMonth/prototype/era/shell.js | 0 .../prototype/eraYear/branding.js | 0 .../prototype/eraYear/browser.js | 0 .../eraYear/calendar-returns-infinity.js | 30 + .../prototype/eraYear/prop-desc.js | 17 + .../PlainYearMonth/prototype/eraYear/shell.js | 0 .../PlainYearMonth/prototype/shell.js | 0 .../PlainYearMonth/prototype/since/browser.js | 0 .../since/infinity-throws-rangeerror.js | 24 + .../PlainYearMonth/prototype/since/shell.js | 1498 ++++++ .../prototype/toLocaleString/browser.js | 0 .../toLocaleString/locales-undefined.js | 22 + .../toLocaleString/options-undefined.js | 22 + .../toLocaleString/resolved-time-zone.js | 16 + .../prototype/toLocaleString/shell.js | 0 ...ne-getoffsetnanosecondsfor-not-callable.js | 25 + .../PlainYearMonth/prototype/until/browser.js | 0 .../until/infinity-throws-rangeerror.js | 24 + .../PlainYearMonth/prototype/until/shell.js | 1498 ++++++ .../intl402/Temporal/PlainYearMonth/shell.js | 0 .../intl402/Temporal/TimeZone/basic.js | 29 + .../intl402/Temporal/TimeZone/browser.js | 0 .../intl402/Temporal/TimeZone/etc-timezone.js | 82 + .../Temporal/TimeZone/from/argument-object.js | 48 + .../Temporal/TimeZone/from/argument-valid.js | 33 + .../intl402/Temporal/TimeZone/from/browser.js | 0 .../intl402/Temporal/TimeZone/from/shell.js | 0 .../TimeZone/from/timezone-string-datetime.js | 29 + .../Temporal/TimeZone/prototype/browser.js | 0 .../prototype/getInstantFor/browser.js | 0 .../infinity-throws-rangeerror.js | 24 + .../TimeZone/prototype/getInstantFor/shell.js | 1498 ++++++ .../getOffsetNanosecondsFor/browser.js | 0 .../getOffsetNanosecondsFor/instant-string.js | 31 + .../getOffsetNanosecondsFor/shell.js | 0 .../prototype/getOffsetStringFor/browser.js | 0 .../getOffsetStringFor/instant-string.js | 31 + .../prototype/getOffsetStringFor/shell.js | 0 .../prototype/getPlainDateTimeFor/browser.js | 0 .../getPlainDateTimeFor/instant-string.js | 35 + .../prototype/getPlainDateTimeFor/shell.js | 1498 ++++++ .../getPossibleInstantsFor/browser.js | 0 .../infinity-throws-rangeerror.js | 24 + .../prototype/getPossibleInstantsFor/shell.js | 1498 ++++++ .../Temporal/TimeZone/prototype/shell.js | 0 .../intl402/Temporal/TimeZone/shell.js | 0 .../intl402/Temporal/ZonedDateTime/browser.js | 0 .../Temporal/ZonedDateTime/compare/browser.js | 0 .../compare/infinity-throws-rangeerror.js | 31 + .../Temporal/ZonedDateTime/compare/shell.js | 1498 ++++++ .../Temporal/ZonedDateTime/from/browser.js | 0 .../from/infinity-throws-rangeerror.js | 25 + .../Temporal/ZonedDateTime/from/shell.js | 1498 ++++++ .../from/timezone-string-datetime.js | 29 + .../ZonedDateTime/prototype/browser.js | 0 .../ZonedDateTime/prototype/equals/browser.js | 0 .../equals/infinity-throws-rangeerror.js | 24 + .../ZonedDateTime/prototype/equals/shell.js | 1498 ++++++ .../equals/timezone-string-datetime.js | 25 + .../ZonedDateTime/prototype/era/branding.js | 0 .../ZonedDateTime/prototype/era/browser.js | 0 .../ZonedDateTime/prototype/era/prop-desc.js | 17 + .../ZonedDateTime/prototype/era/shell.js | 1498 ++++++ ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../prototype/eraYear/branding.js | 0 .../prototype/eraYear/browser.js | 0 .../eraYear/calendar-returns-infinity.js | 30 + .../prototype/eraYear/prop-desc.js | 17 + .../ZonedDateTime/prototype/eraYear/shell.js | 1498 ++++++ ...one-getoffsetnanosecondsfor-non-integer.js | 18 + ...ne-getoffsetnanosecondsfor-not-callable.js | 22 + ...ne-getoffsetnanosecondsfor-out-of-range.js | 18 + ...zone-getoffsetnanosecondsfor-wrong-type.js | 27 + .../Temporal/ZonedDateTime/prototype/shell.js | 0 .../ZonedDateTime/prototype/since/browser.js | 0 .../since/infinity-throws-rangeerror.js | 24 + .../ZonedDateTime/prototype/since/shell.js | 1498 ++++++ .../since/timezone-string-datetime.js | 25 + .../prototype/toLocaleString/browser.js | 0 .../toLocaleString/locales-undefined.js | 21 + .../toLocaleString/options-conflict.js | 51 + .../toLocaleString/options-undefined.js | 21 + .../prototype/toLocaleString/shell.js | 0 .../ZonedDateTime/prototype/until/browser.js | 0 .../until/infinity-throws-rangeerror.js | 24 + .../ZonedDateTime/prototype/until/shell.js | 1498 ++++++ .../until/timezone-string-datetime.js | 25 + .../prototype/withPlainDate/browser.js | 0 .../infinity-throws-rangeerror.js | 24 + .../prototype/withPlainDate/shell.js | 1498 ++++++ .../intl402/Temporal/ZonedDateTime/shell.js | 0 .../tests/test262/intl402/Temporal/browser.js | 0 .../tests/test262/intl402/Temporal/shell.js | 0 js/src/tests/test262/intl402/shell.js | 142 +- .../for-in/acquire-properties-from-array.js | 35 +- .../for-in/acquire-properties-from-object.js | 35 +- .../block-scope/syntax/for-in/shell.js | 31 - .../test262/language/comments/S7.4_A5.js | 11 - .../test262/language/comments/S7.4_A6.js | 43 +- .../tests/test262/language/comments/shell.js | 28 + .../computed-property-names/basics/number.js | 6 +- .../computed-property-names/basics/string.js | 6 +- .../computed-property-names/basics/symbol.js | 12 +- .../class/method/generator.js | 6 +- .../class/method/number.js | 6 +- .../class/method/string.js | 6 +- .../class/method/symbol.js | 12 +- .../object/method/generator.js | 6 +- .../object/method/number.js | 6 +- .../object/method/string.js | 6 +- .../object/method/symbol.js | 12 +- .../to-name-side-effects/numbers-object.js | 6 +- .../to-name-side-effects/object.js | 6 +- .../addition/coerce-bigint-to-string.js | 2 - .../array/spread-obj-spread-order.js | 2 +- .../dstr/array-rest-iter-rtrn-close-err.js | 1 - .../assignment/dstr/obj-rest-order.js | 2 +- ...ession-minus-multiplicativeexpression-0.js | 5 +- ...ession-minus-multiplicativeexpression-1.js | 5 +- ...ession-minus-multiplicativeexpression-2.js | 5 +- ...ression-plus-multiplicativeexpression-0.js | 5 +- ...ression-plus-multiplicativeexpression-1.js | 5 +- ...ression-plus-multiplicativeexpression-2.js | 5 +- .../direct-arrowfunction-0.js | 5 +- .../direct-arrowfunction-1.js | 5 +- .../direct-arrowfunction-2.js | 5 +- .../direct-arrowfunction-3.js | 5 +- .../direct-arrowfunction-4.js | 5 +- .../direct-arrowfunction-5.js | 5 +- .../direct-arrowfunction-6.js | 5 +- .../direct-asyncarrowfunction-0.js | 5 +- .../direct-asyncarrowfunction-1.js | 5 +- .../direct-asyncarrowfunction-2.js | 5 +- .../direct-asyncarrowfunction-3.js | 5 +- .../direct-asyncarrowfunction-4.js | 5 +- .../direct-asyncarrowfunction-5.js | 5 +- .../direct-asyncarrowfunction-6.js | 5 +- ...ession-bitwise-and-equalityexpression-0.js | 5 +- ...ession-bitwise-and-equalityexpression-1.js | 5 +- ...ession-bitwise-and-equalityexpression-2.js | 5 +- ...ssion-bitwise-or-bitwisexorexpression-0.js | 5 +- ...ssion-bitwise-or-bitwisexorexpression-1.js | 5 +- ...ssion-bitwise-or-bitwisexorexpression-2.js | 5 +- ...sion-bitwise-xor-bitwiseandexpression-0.js | 5 +- ...sion-bitwise-xor-bitwiseandexpression-1.js | 5 +- ...sion-bitwise-xor-bitwiseandexpression-2.js | 5 +- .../direct-callexpression-arguments.js | 5 +- .../direct-callexpression-templateliteral.js | 5 +- ...sionhead-coalesce-bitwiseorexpression-0.js | 5 +- ...sionhead-coalesce-bitwiseorexpression-1.js | 5 +- ...sionhead-coalesce-bitwiseorexpression-2.js | 5 +- ...n-abstract-equal-relationalexpression-0.js | 5 +- ...n-abstract-equal-relationalexpression-1.js | 5 +- ...n-abstract-equal-relationalexpression-2.js | 5 +- ...stract-not-equal-relationalexpression-0.js | 5 +- ...stract-not-equal-relationalexpression-1.js | 5 +- ...stract-not-equal-relationalexpression-2.js | 5 +- ...ion-strict-equal-relationalexpression-0.js | 5 +- ...ion-strict-equal-relationalexpression-1.js | 5 +- ...ion-strict-equal-relationalexpression-2.js | 5 +- ...strict-not-equal-relationalexpression-0.js | 5 +- ...strict-not-equal-relationalexpression-1.js | 5 +- ...strict-not-equal-relationalexpression-2.js | 5 +- ...expression-comma-assignmentexpression-0.js | 5 +- ...expression-comma-assignmentexpression-1.js | 5 +- ...expression-comma-assignmentexpression-2.js | 5 +- ...tifierreference-arguments-strict-strict.js | 5 +- ...-identifierreference-eval-strict-strict.js | 5 +- .../direct-import.meta.js | 5 +- .../assignmenttargettype/direct-importcall.js | 5 +- ...ssion-assignment-assignmentexpression-0.js | 5 +- ...ssion-assignment-assignmentexpression-1.js | 5 +- ...ssion-assignment-assignmentexpression-2.js | 5 +- ...lesce-assignment-assignmentexpression-0.js | 5 +- ...lesce-assignment-assignmentexpression-1.js | 5 +- ...lesce-assignment-assignmentexpression-2.js | 5 +- ...l-and-assignment-assignmentexpression-0.js | 5 +- ...l-and-assignment-assignmentexpression-1.js | 5 +- ...l-and-assignment-assignmentexpression-2.js | 5 +- ...al-or-assignment-assignmentexpression-0.js | 5 +- ...al-or-assignment-assignmentexpression-1.js | 5 +- ...al-or-assignment-assignmentexpression-2.js | 5 +- ...rect-lefthandsideexpression-minus-minus.js | 5 +- ...direct-lefthandsideexpression-plus-plus.js | 5 +- ...ssion-logical-and-bitwiseorexpression-0.js | 5 +- ...ssion-logical-and-bitwiseorexpression-1.js | 5 +- ...ssion-logical-and-bitwiseorexpression-2.js | 5 +- ...ssion-logical-or-logicalandexpression-0.js | 5 +- ...ssion-logical-or-logicalandexpression-1.js | 5 +- ...ssion-logical-or-logicalandexpression-2.js | 5 +- ...direct-memberexpression-templateliteral.js | 5 +- .../direct-minus-minus-unaryexpression.js | 5 +- ...tiveoperator-exponentiationexpression-0.js | 5 +- ...tiveoperator-exponentiationexpression-1.js | 5 +- ...tiveoperator-exponentiationexpression-2.js | 5 +- ...tiveoperator-exponentiationexpression-3.js | 5 +- ...tiveoperator-exponentiationexpression-4.js | 5 +- ...tiveoperator-exponentiationexpression-5.js | 5 +- .../direct-new-memberexpression-arguments.js | 5 +- .../direct-new-newexpression.js | 5 +- .../direct-optionalexpression.js | 5 +- .../direct-plus-plus-unaryexpression.js | 5 +- ...imaryexpression-asyncfunctionexpression.js | 5 +- ...maryexpression-asyncgeneratorexpression.js | 5 +- ...irect-primaryexpression-classexpression.js | 5 +- ...ct-primaryexpression-functionexpression.js | 5 +- ...t-primaryexpression-generatorexpression.js | 5 +- ...irect-primaryexpression-literal-boolean.js | 5 +- .../direct-primaryexpression-literal-null.js | 5 +- ...irect-primaryexpression-literal-numeric.js | 5 +- ...direct-primaryexpression-literal-string.js | 5 +- .../direct-primaryexpression-objectliteral.js | 5 +- ...maryexpression-regularexpressionliteral.js | 5 +- ...irect-primaryexpression-templateliteral.js | 5 +- .../direct-primaryexpression-this.js | 5 +- ...ater-than-or-equal-to-shiftexpression-0.js | 5 +- ...ater-than-or-equal-to-shiftexpression-1.js | 5 +- ...ater-than-or-equal-to-shiftexpression-2.js | 5 +- ...pression-greater-than-shiftexpression-0.js | 5 +- ...pression-greater-than-shiftexpression-1.js | 5 +- ...pression-greater-than-shiftexpression-2.js | 5 +- ...lationalexpression-in-shiftexpression-0.js | 5 +- ...lationalexpression-in-shiftexpression-1.js | 5 +- ...lationalexpression-in-shiftexpression-2.js | 5 +- ...expression-instanceof-shiftexpression-0.js | 5 +- ...expression-instanceof-shiftexpression-1.js | 5 +- ...expression-instanceof-shiftexpression-2.js | 5 +- ...less-than-or-equal-to-shiftexpression-0.js | 5 +- ...less-than-or-equal-to-shiftexpression-1.js | 5 +- ...less-than-or-equal-to-shiftexpression-2.js | 5 +- ...lexpression-less-than-shiftexpression-0.js | 5 +- ...lexpression-less-than-shiftexpression-1.js | 5 +- ...lexpression-less-than-shiftexpression-2.js | 5 +- ...ssion-bitwise-left-additiveexpression-0.js | 5 +- ...ssion-bitwise-left-additiveexpression-1.js | 5 +- ...ssion-bitwise-left-additiveexpression-2.js | 5 +- ...sion-bitwise-right-additiveexpression-0.js | 5 +- ...sion-bitwise-right-additiveexpression-1.js | 5 +- ...sion-bitwise-right-additiveexpression-2.js | 5 +- ...gned-bitwise-right-additiveexpression-0.js | 5 +- ...gned-bitwise-right-additiveexpression-1.js | 5 +- ...gned-bitwise-right-additiveexpression-2.js | 5 +- ...texpression-else-assignmentexpression-0.js | 5 +- ...texpression-else-assignmentexpression-1.js | 5 +- ...texpression-else-assignmentexpression-2.js | 5 +- ...-unaryexpression-delete-unaryexpression.js | 5 +- ...xpression-exclamation-unaryexpression-0.js | 5 +- ...xpression-exclamation-unaryexpression-1.js | 5 +- ...xpression-exclamation-unaryexpression-2.js | 5 +- ...unaryexpression-minus-unaryexpression-0.js | 5 +- ...unaryexpression-minus-unaryexpression-1.js | 5 +- ...unaryexpression-minus-unaryexpression-2.js | 5 +- ...-unaryexpression-plus-unaryexpression-0.js | 5 +- ...-unaryexpression-plus-unaryexpression-1.js | 5 +- ...-unaryexpression-plus-unaryexpression-2.js | 5 +- ...unaryexpression-tilde-unaryexpression-0.js | 5 +- ...unaryexpression-tilde-unaryexpression-1.js | 5 +- ...unaryexpression-tilde-unaryexpression-2.js | 5 +- ...naryexpression-typeof-unaryexpression-0.js | 5 +- ...naryexpression-typeof-unaryexpression-1.js | 5 +- ...naryexpression-typeof-unaryexpression-2.js | 5 +- ...-unaryexpression-void-unaryexpression-0.js | 5 +- ...-unaryexpression-void-unaryexpression-1.js | 5 +- ...-unaryexpression-void-unaryexpression-2.js | 5 +- ...on-star-star-exponentiationexpression-0.js | 5 +- ...on-star-star-exponentiationexpression-1.js | 5 +- ...on-star-star-exponentiationexpression-2.js | 5 +- .../direct-yieldexpression-0.js | 5 +- .../direct-yieldexpression-1.js | 5 +- ...ession-minus-multiplicativeexpression-0.js | 5 +- ...ession-minus-multiplicativeexpression-1.js | 5 +- ...ession-minus-multiplicativeexpression-2.js | 5 +- ...ression-plus-multiplicativeexpression-0.js | 5 +- ...ression-plus-multiplicativeexpression-1.js | 5 +- ...ression-plus-multiplicativeexpression-2.js | 5 +- .../parenthesized-arrowfunction-0.js | 5 +- .../parenthesized-arrowfunction-1.js | 5 +- .../parenthesized-arrowfunction-2.js | 5 +- .../parenthesized-arrowfunction-3.js | 5 +- .../parenthesized-arrowfunction-4.js | 5 +- .../parenthesized-arrowfunction-5.js | 5 +- .../parenthesized-arrowfunction-6.js | 5 +- .../parenthesized-asyncarrowfunction-0.js | 5 +- .../parenthesized-asyncarrowfunction-1.js | 5 +- .../parenthesized-asyncarrowfunction-2.js | 5 +- .../parenthesized-asyncarrowfunction-3.js | 5 +- .../parenthesized-asyncarrowfunction-4.js | 5 +- .../parenthesized-asyncarrowfunction-5.js | 5 +- .../parenthesized-asyncarrowfunction-6.js | 5 +- ...ession-bitwise-and-equalityexpression-0.js | 5 +- ...ession-bitwise-and-equalityexpression-1.js | 5 +- ...ession-bitwise-and-equalityexpression-2.js | 5 +- ...ssion-bitwise-or-bitwisexorexpression-0.js | 5 +- ...ssion-bitwise-or-bitwisexorexpression-1.js | 5 +- ...ssion-bitwise-or-bitwisexorexpression-2.js | 5 +- ...sion-bitwise-xor-bitwiseandexpression-0.js | 5 +- ...sion-bitwise-xor-bitwiseandexpression-1.js | 5 +- ...sion-bitwise-xor-bitwiseandexpression-2.js | 5 +- .../parenthesized-callexpression-arguments.js | 5 +- ...thesized-callexpression-templateliteral.js | 5 +- ...sionhead-coalesce-bitwiseorexpression-0.js | 5 +- ...sionhead-coalesce-bitwiseorexpression-1.js | 5 +- ...sionhead-coalesce-bitwiseorexpression-2.js | 5 +- ...n-abstract-equal-relationalexpression-0.js | 5 +- ...n-abstract-equal-relationalexpression-1.js | 5 +- ...n-abstract-equal-relationalexpression-2.js | 5 +- ...stract-not-equal-relationalexpression-0.js | 5 +- ...stract-not-equal-relationalexpression-1.js | 5 +- ...stract-not-equal-relationalexpression-2.js | 5 +- ...ion-strict-equal-relationalexpression-0.js | 5 +- ...ion-strict-equal-relationalexpression-1.js | 5 +- ...ion-strict-equal-relationalexpression-2.js | 5 +- ...strict-not-equal-relationalexpression-0.js | 5 +- ...strict-not-equal-relationalexpression-1.js | 5 +- ...strict-not-equal-relationalexpression-2.js | 5 +- ...expression-comma-assignmentexpression-0.js | 5 +- ...expression-comma-assignmentexpression-1.js | 5 +- ...expression-comma-assignmentexpression-2.js | 5 +- ...tifierreference-arguments-strict-strict.js | 5 +- ...-identifierreference-eval-strict-strict.js | 5 +- .../parenthesized-import.meta.js | 5 +- .../parenthesized-importcall.js | 5 +- ...ssion-assignment-assignmentexpression-0.js | 5 +- ...ssion-assignment-assignmentexpression-1.js | 5 +- ...ssion-assignment-assignmentexpression-2.js | 5 +- ...lesce-assignment-assignmentexpression-0.js | 5 +- ...lesce-assignment-assignmentexpression-1.js | 5 +- ...lesce-assignment-assignmentexpression-2.js | 5 +- ...l-and-assignment-assignmentexpression-0.js | 5 +- ...l-and-assignment-assignmentexpression-1.js | 5 +- ...l-and-assignment-assignmentexpression-2.js | 5 +- ...al-or-assignment-assignmentexpression-0.js | 5 +- ...al-or-assignment-assignmentexpression-1.js | 5 +- ...al-or-assignment-assignmentexpression-2.js | 5 +- ...ized-lefthandsideexpression-minus-minus.js | 5 +- ...esized-lefthandsideexpression-plus-plus.js | 5 +- ...ssion-logical-and-bitwiseorexpression-0.js | 5 +- ...ssion-logical-and-bitwiseorexpression-1.js | 5 +- ...ssion-logical-and-bitwiseorexpression-2.js | 5 +- ...ssion-logical-or-logicalandexpression-0.js | 5 +- ...ssion-logical-or-logicalandexpression-1.js | 5 +- ...ssion-logical-or-logicalandexpression-2.js | 5 +- ...esized-memberexpression-templateliteral.js | 5 +- ...renthesized-minus-minus-unaryexpression.js | 5 +- ...tiveoperator-exponentiationexpression-0.js | 5 +- ...tiveoperator-exponentiationexpression-1.js | 5 +- ...tiveoperator-exponentiationexpression-2.js | 5 +- ...tiveoperator-exponentiationexpression-3.js | 5 +- ...tiveoperator-exponentiationexpression-4.js | 5 +- ...tiveoperator-exponentiationexpression-5.js | 5 +- ...thesized-new-memberexpression-arguments.js | 5 +- .../parenthesized-new-newexpression.js | 5 +- .../parenthesized-optionalexpression.js | 5 +- ...parenthesized-plus-plus-unaryexpression.js | 5 +- ...imaryexpression-asyncfunctionexpression.js | 5 +- ...maryexpression-asyncgeneratorexpression.js | 5 +- ...sized-primaryexpression-classexpression.js | 5 +- ...ed-primaryexpression-functionexpression.js | 5 +- ...d-primaryexpression-generatorexpression.js | 5 +- ...sized-primaryexpression-literal-boolean.js | 5 +- ...thesized-primaryexpression-literal-null.js | 5 +- ...sized-primaryexpression-literal-numeric.js | 5 +- ...esized-primaryexpression-literal-string.js | 5 +- ...hesized-primaryexpression-objectliteral.js | 5 +- ...maryexpression-regularexpressionliteral.js | 5 +- ...sized-primaryexpression-templateliteral.js | 5 +- .../parenthesized-primaryexpression-this.js | 5 +- ...ater-than-or-equal-to-shiftexpression-0.js | 5 +- ...ater-than-or-equal-to-shiftexpression-1.js | 5 +- ...ater-than-or-equal-to-shiftexpression-2.js | 5 +- ...pression-greater-than-shiftexpression-0.js | 5 +- ...pression-greater-than-shiftexpression-1.js | 5 +- ...pression-greater-than-shiftexpression-2.js | 5 +- ...lationalexpression-in-shiftexpression-0.js | 5 +- ...lationalexpression-in-shiftexpression-1.js | 5 +- ...lationalexpression-in-shiftexpression-2.js | 5 +- ...expression-instanceof-shiftexpression-0.js | 5 +- ...expression-instanceof-shiftexpression-1.js | 5 +- ...expression-instanceof-shiftexpression-2.js | 5 +- ...less-than-or-equal-to-shiftexpression-0.js | 5 +- ...less-than-or-equal-to-shiftexpression-1.js | 5 +- ...less-than-or-equal-to-shiftexpression-2.js | 5 +- ...lexpression-less-than-shiftexpression-0.js | 5 +- ...lexpression-less-than-shiftexpression-1.js | 5 +- ...lexpression-less-than-shiftexpression-2.js | 5 +- ...ssion-bitwise-left-additiveexpression-0.js | 5 +- ...ssion-bitwise-left-additiveexpression-1.js | 5 +- ...ssion-bitwise-left-additiveexpression-2.js | 5 +- ...sion-bitwise-right-additiveexpression-0.js | 5 +- ...sion-bitwise-right-additiveexpression-1.js | 5 +- ...sion-bitwise-right-additiveexpression-2.js | 5 +- ...gned-bitwise-right-additiveexpression-0.js | 5 +- ...gned-bitwise-right-additiveexpression-1.js | 5 +- ...gned-bitwise-right-additiveexpression-2.js | 5 +- ...texpression-else-assignmentexpression-0.js | 5 +- ...texpression-else-assignmentexpression-1.js | 5 +- ...texpression-else-assignmentexpression-2.js | 5 +- ...-unaryexpression-delete-unaryexpression.js | 5 +- ...xpression-exclamation-unaryexpression-0.js | 5 +- ...xpression-exclamation-unaryexpression-1.js | 5 +- ...xpression-exclamation-unaryexpression-2.js | 5 +- ...unaryexpression-minus-unaryexpression-0.js | 5 +- ...unaryexpression-minus-unaryexpression-1.js | 5 +- ...unaryexpression-minus-unaryexpression-2.js | 5 +- ...-unaryexpression-plus-unaryexpression-0.js | 5 +- ...-unaryexpression-plus-unaryexpression-1.js | 5 +- ...-unaryexpression-plus-unaryexpression-2.js | 5 +- ...unaryexpression-tilde-unaryexpression-0.js | 5 +- ...unaryexpression-tilde-unaryexpression-1.js | 5 +- ...unaryexpression-tilde-unaryexpression-2.js | 5 +- ...naryexpression-typeof-unaryexpression-0.js | 5 +- ...naryexpression-typeof-unaryexpression-1.js | 5 +- ...naryexpression-typeof-unaryexpression-2.js | 5 +- ...-unaryexpression-void-unaryexpression-0.js | 5 +- ...-unaryexpression-void-unaryexpression-1.js | 5 +- ...-unaryexpression-void-unaryexpression-2.js | 5 +- ...on-star-star-exponentiationexpression-0.js | 5 +- ...on-star-star-exponentiationexpression-1.js | 5 +- ...on-star-star-exponentiationexpression-2.js | 5 +- .../parenthesized-yieldexpression-0.js | 5 +- .../parenthesized-yieldexpression-1.js | 5 +- .../named-yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../await/await-throws-rejections.js | 5 +- .../call/spread-obj-spread-order.js | 2 +- .../call/tco-cross-realm-class-construct.js | 42 - ...tco-cross-realm-class-derived-construct.js | 42 - .../call/tco-cross-realm-fun-call.js | 41 - .../call/tco-cross-realm-fun-construct.js | 41 - .../yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- ...ted-property-name-from-yield-expression.js | 2 + ...ted-property-name-from-yield-expression.js | 2 + ...ted-property-name-from-yield-expression.js | 2 + ...ted-property-name-from-yield-expression.js | 2 + .../yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../class/elements/redeclaration-symbol.js | 2 +- .../class/elements/redeclaration.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../gen-method/yield-spread-arr-multiple.js | 2 +- ...private-reference-accessor-property-add.js | 62 + ...vate-reference-accessor-property-bitand.js | 62 + ...ivate-reference-accessor-property-bitor.js | 62 + ...vate-reference-accessor-property-bitxor.js | 62 + ...private-reference-accessor-property-div.js | 62 + ...private-reference-accessor-property-exp.js | 62 + ...vate-reference-accessor-property-lshift.js | 62 + ...private-reference-accessor-property-mod.js | 62 + ...rivate-reference-accessor-property-mult.js | 62 + ...vate-reference-accessor-property-rshift.js | 62 + ...ate-reference-accessor-property-srshift.js | 62 + ...private-reference-accessor-property-sub.js | 62 + ...ide-private-reference-data-property-add.js | 54 + ...-private-reference-data-property-bitand.js | 54 + ...e-private-reference-data-property-bitor.js | 54 + ...-private-reference-data-property-bitxor.js | 54 + ...ide-private-reference-data-property-div.js | 54 + ...ide-private-reference-data-property-exp.js | 54 + ...-private-reference-data-property-lshift.js | 54 + ...ide-private-reference-data-property-mod.js | 54 + ...de-private-reference-data-property-mult.js | 54 + ...-private-reference-data-property-rshift.js | 54 + ...private-reference-data-property-srshift.js | 54 + ...ide-private-reference-data-property-sub.js | 54 + ...-hand-side-private-reference-method-add.js | 50 + ...nd-side-private-reference-method-bitand.js | 50 + ...and-side-private-reference-method-bitor.js | 50 + ...nd-side-private-reference-method-bitxor.js | 50 + ...-hand-side-private-reference-method-div.js | 50 + ...-hand-side-private-reference-method-exp.js | 50 + ...nd-side-private-reference-method-lshift.js | 50 + ...-hand-side-private-reference-method-mod.js | 50 + ...hand-side-private-reference-method-mult.js | 50 + ...nd-side-private-reference-method-rshift.js | 50 + ...d-side-private-reference-method-srshift.js | 50 + ...-hand-side-private-reference-method-sub.js | 50 + ...eference-readonly-accessor-property-add.js | 52 + ...rence-readonly-accessor-property-bitand.js | 52 + ...erence-readonly-accessor-property-bitor.js | 52 + ...rence-readonly-accessor-property-bitxor.js | 52 + ...eference-readonly-accessor-property-div.js | 52 + ...eference-readonly-accessor-property-exp.js | 52 + ...rence-readonly-accessor-property-lshift.js | 52 + ...eference-readonly-accessor-property-mod.js | 52 + ...ference-readonly-accessor-property-mult.js | 52 + ...rence-readonly-accessor-property-rshift.js | 52 + ...ence-readonly-accessor-property-srshift.js | 52 + ...eference-readonly-accessor-property-sub.js | 52 + .../expressions/delete/11.4.1-4.a-11.js | 3 - .../expressions/division/S11.5.2_A4_T8.js | 4 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- ...l-script-code-host-resolves-module-code.js | 2 +- .../applying-the-exp-operator_A15.js | 4 +- .../applying-the-exp-operator_A19.js | 4 +- .../named-yield-spread-arr-multiple.js | 2 +- .../generators/yield-spread-arr-multiple.js | 2 +- ...private-reference-accessor-property-and.js | 63 + ...ate-reference-accessor-property-nullish.js | 62 + ...-private-reference-accessor-property-or.js | 63 + ...nce-accessor-property-short-circuit-and.js | 64 + ...accessor-property-short-circuit-nullish.js | 63 + ...ence-accessor-property-short-circuit-or.js | 64 + ...ide-private-reference-data-property-and.js | 55 + ...private-reference-data-property-nullish.js | 54 + ...side-private-reference-data-property-or.js | 55 + ...ference-data-property-short-circuit-and.js | 58 + ...nce-data-property-short-circuit-nullish.js | 57 + ...eference-data-property-short-circuit-or.js | 58 + ...-hand-side-private-reference-method-and.js | 51 + ...-reference-method-short-circuit-nullish.js | 57 + ...ivate-reference-method-short-circuit-or.js | 58 + ...eference-readonly-accessor-property-and.js | 53 + ...ence-readonly-accessor-property-nullish.js | 52 + ...reference-readonly-accessor-property-or.js | 53 + ...nly-accessor-property-short-circuit-and.js | 57 + ...accessor-property-short-circuit-nullish.js | 56 + ...only-accessor-property-short-circuit-or.js | 57 + .../new/spread-obj-spread-order.js | 2 +- ...ted-property-name-from-yield-expression.js | 2 + .../object/getter-body-strict-inside.js | 2 +- .../getter-body-strict-outside-strict.js | 2 +- .../async-gen-yield-spread-arr-multiple.js | 2 +- .../gen-yield-spread-arr-multiple.js | 2 +- .../object/setter-body-strict-inside.js | 2 +- .../setter-body-strict-outside-strict.js | 2 +- .../setter-param-arguments-strict-inside.js | 2 +- ...r-param-arguments-strict-outside-strict.js | 2 +- .../object/setter-param-eval-strict-inside.js | 2 +- ...setter-param-eval-strict-outside-strict.js | 2 +- .../call-expression-super-no-base.js | 2 +- ...il-position-null-op-template-string-esi.js | 2 +- ...s-tail-position-null-op-template-string.js | 2 +- ...ition-null-optchain-template-string-esi.js | 2 +- ...-position-null-optchain-template-string.js | 2 +- ...rs-tail-position-op-template-string-esi.js | 2 +- ...errors-tail-position-op-template-string.js | 2 +- ...l-position-optchain-template-string-esi.js | 2 +- ...-tail-position-optchain-template-string.js | 2 +- .../static-semantics-simple-assignment.js | 2 +- .../update-expression-postfix.js | 2 +- .../update-expression-prefix.js | 2 +- .../property-accessors/non-identifier-name.js | 2 +- .../super/call-spread-obj-spread-order.js | 2 +- .../expressions/unary-plus/S11.4.6_A3_T3.js | 18 +- .../part-unicode-10.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-10.0.0-class.js | 19 + .../part-unicode-10.0.0-escaped.js | 2 +- .../identifiers/part-unicode-10.0.0.js | 2 +- .../part-unicode-11.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-11.0.0-class.js | 19 + .../part-unicode-11.0.0-escaped.js | 2 +- .../identifiers/part-unicode-11.0.0.js | 2 +- .../part-unicode-12.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-12.0.0-class.js | 19 + .../part-unicode-12.0.0-escaped.js | 2 +- .../identifiers/part-unicode-12.0.0.js | 2 +- .../part-unicode-13.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-13.0.0-class.js | 19 + .../part-unicode-13.0.0-escaped.js | 2 +- .../identifiers/part-unicode-13.0.0.js | 2 +- .../part-unicode-14.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-14.0.0-class.js | 19 + .../part-unicode-14.0.0-escaped.js | 18 + .../identifiers/part-unicode-14.0.0.js | 16 + .../part-unicode-5.2.0-class-escaped.js | 22 + .../identifiers/part-unicode-5.2.0-class.js | 19 + .../identifiers/part-unicode-5.2.0-escaped.js | 2 +- .../identifiers/part-unicode-5.2.0.js | 2 +- .../part-unicode-6.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-6.0.0-class.js | 19 + .../identifiers/part-unicode-6.0.0-escaped.js | 2 +- .../identifiers/part-unicode-6.0.0.js | 2 +- .../part-unicode-6.1.0-class-escaped.js | 22 + .../identifiers/part-unicode-6.1.0-class.js | 19 + .../identifiers/part-unicode-6.1.0-escaped.js | 2 +- .../identifiers/part-unicode-6.1.0.js | 2 +- .../part-unicode-7.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-7.0.0-class.js | 19 + .../identifiers/part-unicode-7.0.0-escaped.js | 2 +- .../identifiers/part-unicode-7.0.0.js | 2 +- .../part-unicode-8.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-8.0.0-class.js | 19 + .../identifiers/part-unicode-8.0.0-escaped.js | 2 +- .../identifiers/part-unicode-8.0.0.js | 2 +- .../part-unicode-9.0.0-class-escaped.js | 22 + .../identifiers/part-unicode-9.0.0-class.js | 19 + .../identifiers/part-unicode-9.0.0-escaped.js | 2 +- .../identifiers/part-unicode-9.0.0.js | 2 +- .../start-unicode-10.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-10.0.0-class.js | 19 + .../start-unicode-10.0.0-escaped.js | 2 +- .../identifiers/start-unicode-10.0.0.js | 2 +- .../start-unicode-11.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-11.0.0-class.js | 19 + .../start-unicode-11.0.0-escaped.js | 2 +- .../identifiers/start-unicode-11.0.0.js | 2 +- .../start-unicode-12.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-12.0.0-class.js | 19 + .../start-unicode-12.0.0-escaped.js | 2 +- .../identifiers/start-unicode-12.0.0.js | 2 +- .../start-unicode-13.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-13.0.0-class.js | 19 + .../start-unicode-13.0.0-escaped.js | 2 +- .../identifiers/start-unicode-13.0.0.js | 2 +- .../start-unicode-14.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-14.0.0-class.js | 19 + .../start-unicode-14.0.0-escaped.js | 18 + .../identifiers/start-unicode-14.0.0.js | 16 + .../start-unicode-5.2.0-class-escaped.js | 22 + .../identifiers/start-unicode-5.2.0-class.js | 19 + .../start-unicode-5.2.0-escaped.js | 2 +- .../identifiers/start-unicode-5.2.0.js | 2 +- .../start-unicode-6.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-6.0.0-class.js | 19 + .../start-unicode-6.0.0-escaped.js | 2 +- .../identifiers/start-unicode-6.0.0.js | 2 +- .../start-unicode-6.1.0-class-escaped.js | 22 + .../identifiers/start-unicode-6.1.0-class.js | 19 + .../start-unicode-6.1.0-escaped.js | 2 +- .../identifiers/start-unicode-6.1.0.js | 2 +- .../start-unicode-7.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-7.0.0-class.js | 19 + .../start-unicode-7.0.0-escaped.js | 2 +- .../identifiers/start-unicode-7.0.0.js | 2 +- .../start-unicode-8.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-8.0.0-class.js | 19 + .../start-unicode-8.0.0-escaped.js | 2 +- .../identifiers/start-unicode-8.0.0.js | 2 +- .../start-unicode-9.0.0-class-escaped.js | 22 + .../identifiers/start-unicode-9.0.0-class.js | 19 + .../start-unicode-9.0.0-escaped.js | 2 +- .../identifiers/start-unicode-9.0.0.js | 2 +- .../vertical-tilde-continue-escaped.js | 2 +- .../identifiers/vertical-tilde-continue.js | 2 +- .../vertical-tilde-start-escaped.js | 2 +- .../identifiers/vertical-tilde-start.js | 2 +- .../language/module-code/early-dup-lex.js | 2 +- .../early-dup-top-function-async-generator.js | 21 + .../early-dup-top-function-async.js | 21 + .../early-dup-top-function-generator.js | 21 + .../module-code/early-dup-top-function.js | 21 + .../internals/define-own-property.js | 21 + .../rest-parameters/arrow-function.js | 14 +- .../rest-parameters/no-alias-arguments.js | 2 +- .../rest-parameters/with-new-target.js | 16 +- .../block-array-literal-with-item.js | 2 +- .../statementList/block-array-literal.js | 2 +- .../block-arrow-function-assignment-expr.js | 2 +- .../block-arrow-function-functionbody.js | 2 +- .../statementList/block-block-with-labels.js | 2 +- .../language/statementList/block-block.js | 2 +- ...ock-expr-arrow-function-boolean-literal.js | 2 +- .../statementList/block-let-declaration.js | 2 +- .../block-regexp-literal-flags.js | 2 +- .../statementList/block-regexp-literal.js | 2 +- ...k-with-statment-array-literal-with-item.js | 2 +- .../block-with-statment-array-literal.js | 2 +- ...statment-arrow-function-assignment-expr.js | 2 +- ...th-statment-arrow-function-functionbody.js | 2 +- .../block-with-statment-block-with-labels.js | 2 +- .../block-with-statment-block.js | 2 +- ...ent-expr-arrow-function-boolean-literal.js | 2 +- .../block-with-statment-let-declaration.js | 2 +- ...lock-with-statment-regexp-literal-flags.js | 2 +- .../block-with-statment-regexp-literal.js | 2 +- .../class-array-literal-with-item.js | 2 +- .../statementList/class-array-literal.js | 2 +- .../class-arrow-function-assignment-expr.js | 2 +- .../class-arrow-function-functionbody.js | 2 +- .../statementList/class-block-with-labels.js | 2 +- .../language/statementList/class-block.js | 2 +- ...ass-expr-arrow-function-boolean-literal.js | 2 +- .../statementList/class-let-declaration.js | 2 +- .../class-regexp-literal-flags.js | 2 +- .../statementList/class-regexp-literal.js | 2 +- ...k-with-statment-array-literal-with-item.js | 2 +- .../eval-block-with-statment-array-literal.js | 2 +- ...statment-arrow-function-assignment-expr.js | 2 +- ...th-statment-arrow-function-functionbody.js | 2 +- ...l-block-with-statment-block-with-labels.js | 2 +- .../eval-block-with-statment-block.js | 2 +- ...ent-expr-arrow-function-boolean-literal.js | 2 +- ...val-block-with-statment-let-declaration.js | 2 +- ...lock-with-statment-regexp-literal-flags.js | 2 +- ...eval-block-with-statment-regexp-literal.js | 2 +- .../eval-class-array-literal-with-item.js | 2 +- .../statementList/eval-class-array-literal.js | 2 +- ...al-class-arrow-function-assignment-expr.js | 2 +- .../eval-class-arrow-function-functionbody.js | 2 +- .../eval-class-block-with-labels.js | 2 +- .../statementList/eval-class-block.js | 2 +- ...ass-expr-arrow-function-boolean-literal.js | 2 +- .../eval-class-let-declaration.js | 2 +- .../eval-class-regexp-literal-flags.js | 2 +- .../eval-class-regexp-literal.js | 2 +- .../eval-fn-array-literal-with-item.js | 2 +- .../statementList/eval-fn-array-literal.js | 2 +- .../eval-fn-arrow-function-assignment-expr.js | 2 +- .../eval-fn-arrow-function-functionbody.js | 2 +- .../eval-fn-block-with-labels.js | 2 +- .../language/statementList/eval-fn-block.js | 2 +- ...-fn-expr-arrow-function-boolean-literal.js | 2 +- .../statementList/eval-fn-let-declaration.js | 2 +- .../eval-fn-regexp-literal-flags.js | 2 +- .../statementList/eval-fn-regexp-literal.js | 2 +- .../fn-array-literal-with-item.js | 2 +- .../statementList/fn-array-literal.js | 2 +- .../fn-arrow-function-assignment-expr.js | 2 +- .../fn-arrow-function-functionbody.js | 2 +- .../statementList/fn-block-with-labels.js | 2 +- .../language/statementList/fn-block.js | 2 +- .../fn-expr-arrow-function-boolean-literal.js | 2 +- .../statementList/fn-let-declaration.js | 2 +- .../statementList/fn-regexp-literal-flags.js | 2 +- .../statementList/fn-regexp-literal.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../statements/block/labeled-continue.js | 25 + .../yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- ...ted-property-name-from-yield-expression.js | 2 + ...ted-property-name-from-yield-expression.js | 2 + ...ted-property-name-from-yield-expression.js | 2 + ...ted-property-name-from-yield-expression.js | 2 + .../fn-length-static-precedence-order.js | 10 +- .../fn-name-static-precedence-order.js | 10 +- .../yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../class/elements/redeclaration-symbol.js | 2 +- .../class/elements/redeclaration.js | 2 +- .../yield-spread-arr-multiple.js | 2 +- .../gen-method/yield-spread-arr-multiple.js | 2 +- .../class/static-init-arguments-functions.js | 12 +- .../class/static-init-arguments-methods.js | 18 +- ...ntructor-calls-super-multiple-arguments.js | 2 +- .../Array/regular-subclassing.js | 2 +- .../statements/for-in/S12.6.4_A7_T2.js | 26 +- .../dstr/array-rest-iter-rtrn-close-err.js | 1 - .../statements/for-of/dstr/obj-rest-order.js | 2 +- .../generators/yield-spread-arr-multiple.js | 2 +- .../language/statements/throw/S12.13_A2_T5.js | 2 +- .../language/statements/try/S12.14_A18_T5.js | 2 +- js/src/tests/test262/shell.js | 64 +- 7922 files changed, 323917 insertions(+), 28214 deletions(-) create mode 100644 js/src/tests/test262/built-ins/Array/from/array-like-has-length-but-no-indexes-with-values.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/array-find-from-last.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/array-grouping.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/every/callbackfn-resize-arraybuffer.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/filter/callbackfn-resize-arraybuffer.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/find/callbackfn-resize-arraybuffer.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/findIndex/callbackfn-resize-arraybuffer.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/findLast/callbackfn-resize-arraybuffer.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/findLastIndex/callbackfn-resize-arraybuffer.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/forEach/callbackfn-resize-arraybuffer.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A6.7.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/map/callbackfn-resize-arraybuffer.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A5.7.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/pop/set-length-array-is-frozen.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/pop/set-length-array-length-is-non-writable.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/pop/set-length-zero-array-is-frozen.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/pop/set-length-zero-array-length-is-non-writable.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A6.7.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/push/set-length-array-is-frozen.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/push/set-length-array-length-is-non-writable.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/push/set-length-zero-array-is-frozen.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/push/set-length-zero-array-length-is-non-writable.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/reduce/callbackfn-resize-arraybuffer.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/reduceRight/callbackfn-resize-arraybuffer.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A5.7.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A5.7.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/shift/set-length-array-is-frozen.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/shift/set-length-array-length-is-non-writable.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/shift/set-length-zero-array-is-frozen.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/shift/set-length-zero-array-length-is-non-writable.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A5.7.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/some/callbackfn-resize-arraybuffer.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A7.7.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A5.7.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A4.7.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A4.7.js delete mode 100644 js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A5.7.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-array-is-frozen.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-array-length-is-non-writable.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-zero-array-is-frozen.js create mode 100644 js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-zero-array-length-is-non-writable.js rename js/src/tests/test262/built-ins/Boolean/prototype/{S15.6.3.1_A3.js => S15.6.3.1_A3-strict.js} (64%) delete mode 100644 js/src/tests/test262/built-ins/Boolean/prototype/S15.6.4_A1.js create mode 100644 js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-invalid-by-length.js create mode 100644 js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-invalid-by-offset.js create mode 100644 js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-valid-by-length.js create mode 100644 js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-valid-by-offset.js create mode 100644 js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T0.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setDate/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setHours/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setMinutes/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setMonth/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setSeconds/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setUTCDate/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setUTCHours/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/arg-coercion-order.js create mode 100644 js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/arg-coercion-order.js delete mode 100644 js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T1.js delete mode 100644 js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T2.js delete mode 100644 js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T1.js delete mode 100644 js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T2.js delete mode 100644 js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A7.js create mode 100644 js/src/tests/test262/built-ins/Map/bigint-number-same-value.js delete mode 100644 js/src/tests/test262/built-ins/Map/symbol-as-entry-key.js create mode 100644 js/src/tests/test262/built-ins/Map/valid-keys.js create mode 100644 js/src/tests/test262/built-ins/Math/hypot/Math.hypot_ToNumberErr.js delete mode 100644 js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A7.js delete mode 100644 js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A7.js delete mode 100644 js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A7.js delete mode 100644 js/src/tests/test262/built-ins/Object/prototype/toString/not-ctor.js delete mode 100644 js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A7.js create mode 100644 js/src/tests/test262/built-ins/Proxy/revocable/tco-fn-realm-strict.js delete mode 100644 js/src/tests/test262/built-ins/Realm/constructor.js delete mode 100644 js/src/tests/test262/built-ins/Realm/instance.js delete mode 100644 js/src/tests/test262/built-ins/Realm/prototype/evaluate/errors-from-the-other-realm-is-wrapped-into-a-typeerror.js delete mode 100644 js/src/tests/test262/built-ins/Realm/prototype/evaluate/not-constructor.js delete mode 100644 js/src/tests/test262/built-ins/Realm/prototype/evaluate/returns-symbol-values.js delete mode 100644 js/src/tests/test262/built-ins/Realm/prototype/evaluate/validates-realm-object.js delete mode 100644 js/src/tests/test262/built-ins/Realm/prototype/importValue/import-value.js delete mode 100644 js/src/tests/test262/built-ins/Realm/prototype/importValue/not-constructor.js delete mode 100644 js/src/tests/test262/built-ins/Realm/prototype/importValue/specifier-tostring.js delete mode 100644 js/src/tests/test262/built-ins/Realm/prototype/importValue/validates-realm-object.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cypro_Minoan.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Uyghur.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tangsa.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Toto.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Vithkuqi.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cypro_Minoan.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Uyghur.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tangsa.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Toto.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Vithkuqi.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-CharacterClass.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-P.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-u.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-CharacterClass.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-P.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-u.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-CharacterClass.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-P.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-u.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-CharacterClass.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-P.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-u.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-CharacterClass.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-P.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-u.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-CharacterClass.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-P.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-u.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-CharacterClass.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-P.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-u.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-CharacterClass.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-P.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-u.js create mode 100644 js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence.js rename js/src/tests/test262/built-ins/{Realm => RegExp/property-escapes/generated/strings}/browser.js (100%) rename js/src/tests/test262/built-ins/{Realm/prototype/evaluate => RegExp/property-escapes/generated/strings}/shell.js (100%) create mode 100644 js/src/tests/test262/built-ins/RegExp/prototype/exec/failure-lastindex-set.js create mode 100644 js/src/tests/test262/built-ins/Set/bigint-number-same-value.js delete mode 100644 js/src/tests/test262/built-ins/Set/prototype/set-prototype.js delete mode 100644 js/src/tests/test262/built-ins/Set/symbol-as-entry.js create mode 100644 js/src/tests/test262/built-ins/Set/valid-values.js rename js/src/tests/test262/built-ins/{Realm/prototype => ShadowRealm/WrappedFunction}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/length-throws-typeerror.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/length.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/name-throws-typeerror.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/name.js rename js/src/tests/test262/built-ins/{Realm/prototype/importValue => ShadowRealm/WrappedFunction}/shell.js (100%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js rename js/src/tests/test262/built-ins/{Realm/prototype/evaluate => ShadowRealm}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/constructor.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/descriptor.js (52%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/extensibility.js (61%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/instance-extensibility.js (70%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/instance.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/length.js (80%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/name.js (65%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/proto.js (61%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/Symbol.toStringTag.js (67%) rename js/src/tests/test262/built-ins/{Realm/prototype/importValue => ShadowRealm/prototype}/browser.js (100%) rename js/src/tests/test262/built-ins/{Temporal/Calendar/prototype/era => ShadowRealm/prototype/evaluate}/browser.js (100%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/descriptor.js (51%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/errors-from-the-other-realm-is-wrapped-into-a-typeerror.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-available-properties.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-config-only-properties.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-orginary-object.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/length.js (74%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/name.js (60%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/nested-realms.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/no-conditional-strict-mode.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/not-constructor.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/proto.js (58%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/returns-primitive-values.js (72%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-proxy-callable-object.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-symbol-values.js rename js/src/tests/test262/built-ins/{Realm/prototype => ShadowRealm/prototype/evaluate}/shell.js (100%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-error-from-ctor-realm.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-syntaxerror-on-bad-syntax.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/throws-typeerror-if-evaluation-resolves-to-non-primitive.js (66%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/throws-when-argument-is-not-a-string.js (66%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/validates-realm-object.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm-extended.js (70%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm.js (53%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-function-from-return-values-share-no-identity.js (88%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-multiple-different-realms-nested.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-multiple-different-realms.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-function-observing-their-scopes.js (54%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-proto-from-caller-realm.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-proxied-observes-boundary.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-from-caller-realm.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-exceptional-exit.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-non-primitive-arguments.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-non-primitive-returns.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-functions-accepts-callable-objects.js (64%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-functions-can-resolve-callable-returns.js (59%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-functions-new-wrapping-on-each-evaluation.js (55%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-functions-share-no-properties-extended.js (86%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/evaluate/wrapped-functions-share-no-properties.js (55%) rename js/src/tests/test262/built-ins/{Temporal/Calendar/prototype/eraYear => ShadowRealm/prototype/importValue}/browser.js (100%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/importValue/descriptor.js (50%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/importValue/exportName-tostring.js (55%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/importValue/import-value_FIXTURE.js (100%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_syntax_error_FIXTURE.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_throws_FIXTURE.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/importValue/length.js (77%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/importValue/name.js (58%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/not-constructor.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/importValue/proto.js (58%) rename js/src/tests/test262/built-ins/{Temporal/Calendar/prototype/era => ShadowRealm/prototype/importValue}/shell.js (100%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/specifier-tostring.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/importValue/throws-if-import-value-does-not-exist.js (71%) create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-syntax-error.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-throws.js create mode 100644 js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/validates-realm-object.js rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/prototype/proto.js (67%) rename js/src/tests/test262/built-ins/{Temporal/Calendar/prototype/eraYear => ShadowRealm/prototype}/shell.js (100%) rename js/src/tests/test262/built-ins/{Realm => ShadowRealm}/shell.js (100%) create mode 100644 js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/constructor.js rename js/src/tests/test262/built-ins/Temporal/{PlainDate/prototype/era => Calendar/from}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-not-builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/missing-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/balance-smaller-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/duration-argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalOverflow.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-type-error-from-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/fields-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-range-error-from-ISODateFromFields.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-fields-is-not-object.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-from-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-iterable-not-array.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-duplicate-keys.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-invalid-keys.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/non-string-element-throws.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/repeated-throw.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/reverse.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-empty-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/branding.js rename js/src/tests/test262/built-ins/Temporal/{PlainDate/prototype/eraYear => Calendar/prototype/toJSON}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/cross-year.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/prop-desc.js delete mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-type-error-RequireInternalSlot.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/call-builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/argument-string-negative-fractional-units.js rename js/src/tests/test262/built-ins/Temporal/{PlainDateTime/prototype/era => Duration/compare}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-possibly-required.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-zoneddatetime-wrong-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-undefined-throw-on-calendar-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/compare/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/days-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/fractional-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/argument-existing-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/argument-non-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/argument-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string.js rename js/src/tests/test262/built-ins/Temporal/{PlainDateTime/prototype/eraYear => Duration/from}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/negative-inifinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/string-with-skipped-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/hours-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/microseconds-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/milliseconds-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/minutes-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/mixed.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/months-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/nanoseconds-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/balance-negative-result.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-zoneddatetime-wrong-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/blank/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/days/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/hours/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/microseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/milliseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/minutes/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/months/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/nanoseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/balance-negative-result.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-possibly-required.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/dateuntil-field.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-zoneddatetime-wrong-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-undefined-throw-on-calendar-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/round-negative-result.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-disallowed-units-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-plurals-accepted-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-string-shorthand-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/seconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/sign/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/balance-negative-result.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-zoneddatetime-wrong-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/negative-components.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/balance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/blank-duration-precision.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-exact-number-of-digits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/negative-components.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/precision.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-valid-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/balance-negative-result.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-possibly-required.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/dateuntil-field.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/options-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-zoneddatetime-wrong-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-undefined-throw-on-calendar-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-disallowed-units-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-string-shorthand-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/weeks/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/all-negative.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/all-positive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/copy-properties-not-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/partial-positive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/prototype/years/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/seconds-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/weeks-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Duration/years-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/argument.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/argument-zoneddatetime.js rename js/src/tests/test262/built-ins/Temporal/{PlainYearMonth/prototype/era => Instant/compare}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/instant-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/compare/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/argument-zoneddatetime.js rename js/src/tests/test262/built-ins/Temporal/{PlainYearMonth/prototype/eraYear => Instant/from}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/instant-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/timezone-custom.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/from/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/basic.js rename js/src/tests/test262/built-ins/Temporal/{ZonedDateTime/prototype/era => Instant/fromEpochMicroseconds}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/basic.js rename js/src/tests/test262/built-ins/Temporal/{ZonedDateTime/prototype/eraYear => Instant/fromEpochMilliseconds}/browser.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/basic.js rename js/src/tests/test262/built-ins/Temporal/{PlainDate/prototype/era/shell.js => Instant/fromEpochNanoseconds/browser.js} (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/basic.js rename js/src/tests/test262/built-ins/Temporal/{PlainDate/prototype/eraYear/shell.js => Instant/fromEpochSeconds/browser.js} (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/disallowed-duration-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/result-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMicroseconds/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMicroseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMilliseconds/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMilliseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochNanoseconds/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochNanoseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochSeconds/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochSeconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/argument-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/argument-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/instant-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/options-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-disallowed-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-string-shorthand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/argument-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/instant-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/disallowed-duration-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/result-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/return-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/precision.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-valid-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/year-format.js rename js/src/tests/test262/built-ins/Temporal/{PlainDateTime/prototype/era/shell.js => Instant/prototype/toStringTag/browser.js} (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toStringTag/prop-desc.js rename js/src/tests/test262/built-ins/Temporal/{PlainDateTime/prototype/eraYear => Instant/prototype/toStringTag}/shell.js (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/plain-custom-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/argument-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/instant-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/instant/return-value-instance.js rename js/src/tests/test262/built-ins/Temporal/{PlainYearMonth/prototype/era/shell.js => Now/plainDate/browser.js} (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDate/toPlainDate-override.js rename js/src/tests/test262/built-ins/Temporal/{PlainYearMonth/prototype/eraYear/shell.js => Now/plainDateISO/browser.js} (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/return-value.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone.js rename js/src/tests/test262/built-ins/Temporal/{ZonedDateTime/prototype/era/shell.js => Now/plainDateTimeISO/browser.js} (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/extensible.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/return-value-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/return-value.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/time-zone-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-invocation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-non-method.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-not-a-number.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-poisoned.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-throws.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-call-tostring.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-get-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-has-nested-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-has-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-string-datetime.js rename js/src/tests/test262/built-ins/Temporal/{ZonedDateTime/prototype/eraYear/shell.js => Now/plainTimeISO/browser.js} (100%) create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/return-value.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/toPlainTime-override.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/toStringTag/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/toStringTag/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/toStringTag/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/toStringTag/string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-function.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-call-tostring.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-get-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-has-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-has-nested-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/extensible.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/time-zone-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-call-tostring.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-get-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-has-nested-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-has-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/extensible.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/return-value.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/time-zone-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-call-tostring.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-get-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-has-nested-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-has-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/use-internal-slots.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/compare/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-number.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-object-valid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-trailing-junk.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/from/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/missing-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-invalid-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-missing-properties.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-singular-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/balance-smaller-units-basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/balance-smaller-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-constrain.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-reject.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/calendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/day/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/day/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfWeek/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfWeek/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInMonth/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInWeek/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInWeek/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-object-valid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-call-different.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-call-same.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-no-call.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-names.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-traversal-order.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/inLeapYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/month/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/month/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthCode/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthsInYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthsInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-id-match.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/days-in-month.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/days-in-year.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-default.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-higher-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/rounding-relative.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-ceil.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-floor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-halfExpand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-trunc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-higher-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/weeks-months.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-invalid-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-missing-properties.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-singular-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/balance-smaller-units-basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/balance-smaller-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-constrain.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-reject.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/return-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/plaintime-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/time-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/time-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-always.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-auto.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-never.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-id-match.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-month.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-year.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-relative.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-ceil.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-floor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfExpand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-trunc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-higher-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/weeks-months.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/weekOfYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/weekOfYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/calendar-merge-fields-returns-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/copies-merge-fields-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/copy-properties-not-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/plaindatelike-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/missing-argument.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/year/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/year/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/cast.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/use-internal-slots.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/constructor-full.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/datetime-math.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/parser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/hour-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/microsecond-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/millisecond-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/minute-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/missing-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/calendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/day/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/day/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-names.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-traversal-order.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/hour/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/inLeapYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/microsecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/millisecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/minute/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/month/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/month/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthCode/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/nanosecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-disallowed-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-string-shorthand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/second/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-copy-of-options.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-plaindate-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/round-negative-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/return-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-valid-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/plain-custom-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-copy-of-options.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-plaindate-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/round-negative-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-merge-fields-returns-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/copies-merge-fields-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/copy-properties-not-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/missing-argument.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/plaintime-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/time-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/year/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/year/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainDateTime/second-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-always.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-leap-day.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-missing-properties.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-plainmonthday.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/missing-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendars.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-names.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-traversal-order.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/unsupported.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/calendarname.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/copies-merge-fields-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-auto.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-never.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-merge-fields-returns-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copies-merge-fields-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copy-properties-not-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-cast.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/plaintime-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/use-internal-slots.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/compare/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-number.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object-leap-second.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaintime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-leap-second.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-trailing-junk.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-constrain.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-reject.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/plaintime-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/from/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/hour-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/microsecond-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/millisecond-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/minute-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/nanosecond-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/negative-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-higher-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/options-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/calendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-cast.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/plaintime-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-names.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-traversal-order.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/rounding-cross-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-hours.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-microseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-milliseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-minutes.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-seconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-ceil.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-floor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfExpand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-trunc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-disallowed-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-missing.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-string-shorthand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-cast.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/result-sub-second.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-hours.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-microseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-milliseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-minutes.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-seconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-ceil.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-floor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfExpand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-trunc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-higher-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/options-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-cast.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/result-sub-second.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-hours.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-microseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-milliseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-minutes.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-seconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-ceil.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-floor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfExpand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-trunc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/copy-properties-not-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/plaintimelike-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainTime/second-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-always.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/argument-cast.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/compare-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/compare-reference-day.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/use-internal-slots.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-number.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-plainyearmonth.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-trailing-junk.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-constrain.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-reject.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/missing-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-duration-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-lower-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object-plural.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-arguments-extra-options.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-datefromfields-called.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-daysinmonth-wrong-value.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/month-length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/calendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInMonth/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInMonth/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-cast.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/compare-calendar.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/compare-reference-day.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/use-internal-slots.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-names.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-traversal-order.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/inLeapYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/month/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/month/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthCode/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthsInYear/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthsInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/argument-casting.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/arguments-missing-throws.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-auto.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-disallowed-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-months.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-years.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/mixed-calendar-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-ceil.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-floor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfExpand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-trunc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/symmetry.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-duration-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-lower-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object-plural.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-arguments-extra-options.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-datefromfields-called.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-daysinmonth-wrong-value.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/month-length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/negative-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/argument-not-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/copies-merge-fields-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/limits.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-auto.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-never.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/argument-casting.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/arguments-missing-throws.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-dateadd-called-with-plaindate-instance.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-auto.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-disallowed-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-months.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-years.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/mixed-calendar-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/options-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-as-expected.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-ceil.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-floor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfExpand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-trunc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-calendar-field.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-missing-fields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-timezone-field.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-merge-fields-returns-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/copies-merge-fields-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/copy-properties-not-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/options-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/order-of-operations.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/year/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/year/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/PlainYearMonth/refisoday-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-object-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-valid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/from/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/missing-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-not-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-not-absolute.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute-getOffsetNanosecondsFor-override.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute-getOffsetNanosecondsFor-override.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/branding.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/custom-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/pre-epoch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-not-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-plaindate.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-zoneddatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/branding.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-call.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-undefined-custom.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/calendar-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-offset-not-agreeing-with-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/zoneddatetime-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/zoneddatetime-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-offset-not-agreeing-with-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/missing-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/calendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMicroseconds/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMicroseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMilliseconds/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMilliseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochNanoseconds/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochNanoseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochSeconds/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochSeconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-offset-not-agreeing-with-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/zoneddatetime-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/zoneddatetime-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-names.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-traversal-order.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/basic.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/dateadd-options.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/div-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-disallowed-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-string-shorthand.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/argument-propertybag-offset-not-agreeing-with-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-copy-of-options.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/zoneddatetime-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/zoneddatetime-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/argument-string-negative-fractional-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/non-integer-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/timeZone/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/return-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/plain-custom-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-result.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-arguments.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-result.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-valid-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/year-format.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/argument-propertybag-offset-not-agreeing-with-timezone.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-copy-of-options.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-smallestunit-mismatch.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-nan.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-plurals-accepted.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/sub-minute-offset.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-merge-fields-returns-primitive.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copies-merge-fields-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copy-properties-not-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-property-sub-minute.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/read-time-fields-before-datefromfields.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/receiver-offset-broken.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/missing-argument.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-plaindatetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-fields-iterable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-no-implicit-midnight.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-time-designator-required-for-disambiguation.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-with-time-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/calendar-dateadd-called-with-options-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/calendar-temporal-object.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/plaintime-propertybag-no-time-units.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/time-undefined.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/year-zero.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/builtin.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/length.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/name.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/not-a-constructor.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/subclassing-ignored.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-multiple-offsets.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/built-ins/Temporal/ZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/built-ins/Temporal/getOwnPropertyNames.js create mode 100644 js/src/tests/test262/built-ins/Temporal/keys.js create mode 100644 js/src/tests/test262/built-ins/Temporal/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/toStringTag/browser.js create mode 100644 js/src/tests/test262/built-ins/Temporal/toStringTag/prop-desc.js create mode 100644 js/src/tests/test262/built-ins/Temporal/toStringTag/shell.js create mode 100644 js/src/tests/test262/built-ins/Temporal/toStringTag/string.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/browser.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/shell.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/BigInt/resizable-array-buffer-auto.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/BigInt/resizable-array-buffer-fixed.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/BigInt/resizable-array-buffer-auto.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/BigInt/resizable-array-buffer-fixed.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/byteoffset.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/entries/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/every/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/every/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/fill/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/filter/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/filter/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/find/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/find/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/findIndex/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/findIndex/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/findLast/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/findLast/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/findLastIndex/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/forEach/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/forEach/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/includes/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/indexOf/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/join/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/keys/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/lastIndexOf/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-auto.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-fixed.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/map/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/map/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/reduce/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/reduce/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/callbackfn-resize.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/reverse/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/set/BigInt/typedarray-arg-set-values-same-buffer-same-type-resized.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/set/BigInt/typedarray-arg-target-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js delete mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/slice/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/some/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/some/callbackfn-resize.js delete mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/sort/BigInt/return-abrupt-from-this-out-of-bounds.js delete mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn-coerce.js delete mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/toLocaleString/BigInt/return-abrupt-from-this-out-of-bounds.js create mode 100644 js/src/tests/test262/built-ins/TypedArray/prototype/values/BigInt/return-abrupt-from-this-out-of-bounds.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-different-type.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-same-type.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-access-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-access-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js create mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/no-species.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-null.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-undefined.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js delete mode 100644 js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js delete mode 100644 js/src/tests/test262/harness/arrayContains.js create mode 100644 js/src/tests/test262/harness/assert-throws-custom-typeerror.js create mode 100644 js/src/tests/test262/harness/assert-throws-same-realm.js create mode 100644 js/src/tests/test262/harness/compare-array-arguments.js create mode 100644 js/src/tests/test262/harness/compare-array-arraylike.js create mode 100644 js/src/tests/test262/harness/compare-array-message.js create mode 100644 js/src/tests/test262/harness/temporalHelpers-one-shift-time-zone.js create mode 100644 js/src/tests/test262/intl402/DateTimeFormat/prototype/format/temporal-objects-resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/DateTimeFormat/prototype/format/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/temporal-objects-resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/browser.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/instance/browser.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/instance/extensibility.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/instance/length.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/instance/name.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/instance/prop-desc.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/instance/prototype.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/instance/shell.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/constructor/browser.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/constructor/prop-desc.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/constructor/shell.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/constructor/value.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/format/browser.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/format/length.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/format/name.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/format/prop-desc.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/format/shell.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/format/throw-invoked-as-func.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/browser.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/length.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/name.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/prop-desc.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/shell.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/throw-invoked-as-func.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/prototype_attributes.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/browser.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/length.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/name.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/prop-desc.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/shell.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/throw-invoked-as-func.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/browser.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/shell.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/toString.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/toStringTag.js create mode 100644 js/src/tests/test262/intl402/DurationFormat/shell.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/browser.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/browser.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/fails-on-distinct-temporal-types.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/shell.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/browser.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/fails-on-distinct-temporal-types.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/shell.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Intl/DateTimeFormat/shell.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/browser.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/builtin.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars-accepted-by-DateTimeFormat.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars-accepted-by-DisplayNames.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/coerced-to-string.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/collations-accepted-by-Collator.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/collations.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies-accepted-by-DisplayNames.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies-accepted-by-NumberFormat.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/invalid-key.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/length.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/name.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-DateTimeFormat.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-NumberFormat.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-RelativeTimeFormat.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-with-simple-digit-mappings.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/shell.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/timeZones-accepted-by-DateTimeFormat.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/timeZones.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/units-accepted-by-NumberFormat.js create mode 100644 js/src/tests/test262/intl402/Intl/supportedValuesOf/units.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-options-roundingMode-invalid.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-increment.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-mode.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-priority.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-trailing-zero-display.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay-negative.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay-invalid.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-ceil.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-expand.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-floor.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-ceil.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-even.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-expand.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-floor.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-trunc.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-trunc.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-auto.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-more-precision.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-de-DE.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-en-US.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ja-JP.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ko-KR.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-zh-TW.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-de-DE.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-en-US.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ja-JP.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ko-KR.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-zh-TW.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-de-DE.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-IN.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-US.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-de-DE.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-IN.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-US.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/format/value-decimal-string.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/argument-to-Intlmathematicalvalue-throws.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/browser.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/builtin.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/en-US.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/invoked-as-func.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/length.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/name.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/nan-arguments-throws.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/prop-desc.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/pt-PT.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/shell.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/undefined-arguments-throws.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/argument-to-Intlmathematicalvalue-throws.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/browser.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/builtin.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/en-US.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/length.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/name.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/prop-desc.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/shell.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/undefined-arguments-throws.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-de-DE.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-en-US.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ja-JP.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ko-KR.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-zh-TW.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-de-DE.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-en-US.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ja-JP.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ko-KR.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-zh-TW.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/roundingMode.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority.js create mode 100644 js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping-extended.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/argument-tonumber-throws.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/browser.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/default-en-us.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/invoked-as-func.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/length.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/name.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/nan-arguments-throws.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/prop-desc.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/shell.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/undefined-arguments-throws.js create mode 100644 js/src/tests/test262/intl402/PluralRules/prototype/selectRange/x-greater-than-y-throws.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/from/basic.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/from/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/from/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/Calendar/prototype/era/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/builtin.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/length.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/name.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/not-a-constructor.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/year-zero.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-string-with-utc-designator.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/Calendar/prototype/eraYear/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/builtin.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/length.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/name.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/not-a-constructor.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/year-zero.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Calendar/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/add/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/add/relativeto-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/add/relativeto-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/add/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/round/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/round/relativeto-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/round/relativeto-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/round/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/relativeto-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/relativeto-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/total/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/total/relativeto-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/total/relativeto-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/prototype/total/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Duration/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/locales-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/options-conflict.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Instant/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDate/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDate/calendar-string.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDate/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDateTime/calendar-string.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/calendar-string.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/calendar-timezone-string.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/timezone-string.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/compare/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/compare/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/compare/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/from/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/from/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/shell.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/PlainDate/prototype/era/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/shell.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/PlainDate/prototype/eraYear/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/locales-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDate/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/from/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/from/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/shell.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/PlainDateTime/prototype/era/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/shell.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/PlainDateTime/prototype/eraYear/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/locales-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/locales-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainMonthDay/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/locales-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/argument-object.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/shell.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/PlainYearMonth/prototype/era/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/shell.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/PlainYearMonth/prototype/eraYear/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/locales-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/resolved-time-zone.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/PlainYearMonth/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/basic.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/etc-timezone.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/from/argument-object.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/from/argument-valid.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/from/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/from/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/from/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/TimeZone/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/timezone-string-datetime.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/ZonedDateTime/prototype/era/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-wrong-type.js rename js/src/tests/test262/{built-ins => intl402}/Temporal/ZonedDateTime/prototype/eraYear/branding.js (100%) create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/calendar-returns-infinity.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/prop-desc.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-non-integer.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-not-callable.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-out-of-range.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-wrong-type.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/locales-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-undefined.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/timezone-string-datetime.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/ZonedDateTime/shell.js create mode 100644 js/src/tests/test262/intl402/Temporal/browser.js create mode 100644 js/src/tests/test262/intl402/Temporal/shell.js delete mode 100644 js/src/tests/test262/language/expressions/call/tco-cross-realm-class-construct.js delete mode 100644 js/src/tests/test262/language/expressions/call/tco-cross-realm-class-derived-construct.js delete mode 100644 js/src/tests/test262/language/expressions/call/tco-cross-realm-fun-call.js delete mode 100644 js/src/tests/test262/language/expressions/call/tco-cross-realm-fun-construct.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-add.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitand.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitor.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitxor.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-div.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-exp.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-lshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-mod.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-mult.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-rshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-srshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-sub.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-add.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitand.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitor.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitxor.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-div.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-exp.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-lshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-mod.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-mult.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-rshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-srshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-sub.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-add.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitand.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitor.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitxor.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-div.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-exp.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-lshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-mod.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-mult.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-rshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-srshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-sub.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-add.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitand.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitor.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitxor.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-div.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-exp.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-lshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-mod.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-mult.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-rshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-srshift.js create mode 100644 js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-sub.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-and.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-nullish.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-or.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-and.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-nullish.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-or.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-and.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-nullish.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-or.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-and.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-nullish.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-or.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-and.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-nullish.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-or.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-and.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-nullish.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-or.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-and.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-nullish.js create mode 100644 js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-or.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-10.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-10.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-11.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-11.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-12.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-12.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-13.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-13.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-14.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-14.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-14.0.0-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-14.0.0.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-5.2.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-5.2.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-6.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-6.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-6.1.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-6.1.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-7.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-7.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-8.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-8.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-9.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/part-unicode-9.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-10.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-10.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-11.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-11.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-12.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-12.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-13.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-13.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-14.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-14.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-14.0.0-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-14.0.0.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-5.2.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-5.2.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-6.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-6.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-6.1.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-6.1.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-7.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-7.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-8.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-8.0.0-class.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-9.0.0-class-escaped.js create mode 100644 js/src/tests/test262/language/identifiers/start-unicode-9.0.0-class.js create mode 100644 js/src/tests/test262/language/module-code/early-dup-top-function-async-generator.js create mode 100644 js/src/tests/test262/language/module-code/early-dup-top-function-async.js create mode 100644 js/src/tests/test262/language/module-code/early-dup-top-function-generator.js create mode 100644 js/src/tests/test262/language/module-code/early-dup-top-function.js create mode 100644 js/src/tests/test262/language/statements/block/labeled-continue.js diff --git a/js/src/tests/test262/GIT-INFO b/js/src/tests/test262/GIT-INFO index e559f90ff99f..7529353c55c4 100644 --- a/js/src/tests/test262/GIT-INFO +++ b/js/src/tests/test262/GIT-INFO @@ -1,9 +1,8 @@ -commit 45a913c057892bdd26f7bc06a59a0c7420f2d3ec -Author: Philip Chimento -Date: Wed Aug 11 12:31:23 2021 -0700 +commit d7c0a2076c2b0c1531aef7069d4abe70eec44ee3 +Author: Shu-yu Guo +Date: Mon Apr 4 16:36:56 2022 -0700 - Add branding tests from Temporal (#3138) + Remove check for per-comparator call detach check in TypedArray.prototype.sort - Closes: #3137 - - Co-authored-by: Ms2ger + This updates tests in line with the normative change in + https://github.com/tc39/ecma262/pull/2723 diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-cross-realm-instance.js b/js/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-cross-realm-instance.js index 413884a44e2f..5c4f9a82340e 100644 --- a/js/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-cross-realm-instance.js +++ b/js/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-cross-realm-instance.js @@ -21,7 +21,7 @@ assert.throws( ); assert.throws( - TypeError, + other.TypeError, function () { other.RegExp.prototype.compile.call(regexp); }, diff --git a/js/src/tests/test262/built-ins/Array/S15.4.1_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.1_A1.1_T1.js index 7ea22f6e89dd..94bd07777f7b 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.1_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.1_A1.1_T1.js @@ -12,7 +12,6 @@ description: > this property ---*/ -//CHECK#1 Array.prototype.myproperty = 42; var x = Array(); assert.sameValue(x.myproperty, 42, 'The value of x.myproperty is expected to be 42'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.1_A1.1_T2.js b/js/src/tests/test262/built-ins/Array/S15.4.1_A1.1_T2.js index c0a3abf776c2..864c449d4b1f 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.1_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.1_A1.1_T2.js @@ -10,12 +10,10 @@ es5id: 15.4.1_A1.1_T2 description: Array.prototype.toString = Object.prototype.toString ---*/ -//CHECK#1 Array.prototype.toString = Object.prototype.toString; var x = Array(); assert.sameValue(x.toString(), "[object Array]", 'x.toString() must return "[object Array]"'); -//CHECK#2 Array.prototype.toString = Object.prototype.toString; var x = Array(0, 1, 2); assert.sameValue(x.toString(), "[object Array]", 'x.toString() must return "[object Array]"'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.1_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.1_A1.2_T1.js index 92ad2324124f..c398a6535c04 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.1_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.1_A1.2_T1.js @@ -7,12 +7,10 @@ es5id: 15.4.1_A1.2_T1 description: Checking use Object.prototype.toString ---*/ -//CHECK#1 var x = Array(); x.getClass = Object.prototype.toString; assert.sameValue(x.getClass(), "[object Array]", 'x.getClass() must return "[object Array]"'); -//CHECK#2 var x = Array(0, 1, 2); x.getClass = Object.prototype.toString; assert.sameValue(x.getClass(), "[object Array]", 'x.getClass() must return "[object Array]"'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.1_A2.2_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.1_A2.2_T1.js index 0bc8bb617534..b2cbaa38fed9 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.1_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.1_A2.2_T1.js @@ -12,7 +12,6 @@ es5id: 15.4.1_A2.2_T1 description: Checking correct work this algorithm ---*/ -//CHECK# var x = Array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, diff --git a/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.1_T1.js index 65306c3a56b9..e682359d1b6f 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.1_T1.js @@ -12,7 +12,6 @@ description: > this property ---*/ -//CHECK#1 Array.prototype.myproperty = 1; var x = new Array(); assert.sameValue(x.myproperty, 1, 'The value of x.myproperty is expected to be 1'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.1_T2.js b/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.1_T2.js index c8456300579a..17a7a33d2e4c 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.1_T2.js @@ -10,12 +10,10 @@ es5id: 15.4.2.1_A1.1_T2 description: Array.prototype.toString = Object.prototype.toString ---*/ -//CHECK#1 Array.prototype.toString = Object.prototype.toString; var x = new Array(); assert.sameValue(x.toString(), "[object Array]", 'x.toString() must return "[object Array]"'); -//CHECK#2 Array.prototype.toString = Object.prototype.toString; var x = new Array(0, 1, 2); assert.sameValue(x.toString(), "[object Array]", 'x.toString() must return "[object Array]"'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.2_T1.js index b6d00968ac61..080ed966349d 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.2.1_A1.2_T1.js @@ -7,12 +7,10 @@ es5id: 15.4.2.1_A1.2_T1 description: Checking use Object.prototype.toString ---*/ -//CHECK#1 var x = new Array(); x.getClass = Object.prototype.toString; assert.sameValue(x.getClass(), "[object Array]", 'x.getClass() must return "[object Array]"'); -//CHECK#2 var x = new Array(0, 1, 2); x.getClass = Object.prototype.toString; assert.sameValue(x.getClass(), "[object Array]", 'x.getClass() must return "[object Array]"'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.2.1_A2.2_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.2.1_A2.2_T1.js index 556cf7c77580..8b56efd0ac8f 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.2.1_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.2.1_A2.2_T1.js @@ -12,7 +12,6 @@ es5id: 15.4.2.1_A2.2_T1 description: Checking correct work this algorithm ---*/ -//CHECK# var x = new Array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, diff --git a/js/src/tests/test262/built-ins/Array/S15.4.3_A1.1_T2.js b/js/src/tests/test262/built-ins/Array/S15.4.3_A1.1_T2.js index 7c306aa6303d..53fbd5f16985 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.3_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.3_A1.1_T2.js @@ -9,7 +9,6 @@ es5id: 15.4.3_A1.1_T2 description: Function.prototype.toString = Object.prototype.toString ---*/ -//CHECK#1 Function.prototype.toString = Object.prototype.toString; assert.sameValue( diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.1_A1.2_T2.js b/js/src/tests/test262/built-ins/Array/S15.4.5.1_A1.2_T2.js index aa2d694637cc..aa7add825645 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.1_A1.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.1_A1.2_T2.js @@ -11,12 +11,10 @@ es5id: 15.4.5.1_A1.2_T2 description: Checking an inherited property ---*/ -//CHECK#1 Array.prototype[2] = -1; var x = [0, 1, 2]; assert.sameValue(x[2], 2, 'The value of x[2] is expected to be 2'); -//CHECK#2 x.length = 2; assert.sameValue(x[2], -1, 'The value of x[2] is expected to be -1'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.1_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.1_T1.js index 6c70aac1bcd8..7edca01d0f6d 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.1_T1.js @@ -9,19 +9,16 @@ es5id: 15.4.5.1_A2.1_T1 description: P in [4294967295, -1, true] ---*/ -//CHECK#1 var x = []; x[4294967295] = 1; assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); assert.sameValue(x[4294967295], 1, 'The value of x[4294967295] is expected to be 1'); -//CHECK#2 x = []; x[-1] = 1; assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); assert.sameValue(x[-1], 1, 'The value of x[-1] is expected to be 1'); -//CHECK#3 x = []; x[true] = 1; assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.2_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.2_T1.js index 0e7bee8bbec6..0cf2eab493e5 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.2_T1.js @@ -9,16 +9,13 @@ es5id: 15.4.5.1_A2.2_T1 description: length === 100, P in [0, 98, 99] ---*/ -//CHECK#1 var x = Array(100); x[0] = 1; assert.sameValue(x.length, 100, 'The value of x.length is expected to be 100'); -//CHECK#2 x[98] = 1; assert.sameValue(x.length, 100, 'The value of x.length is expected to be 100'); -//CHECK#3 x[99] = 1; assert.sameValue(x.length, 100, 'The value of x.length is expected to be 100'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.3_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.3_T1.js index fcdd2dcfc1dd..9a0a14eaba11 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.3_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.1_A2.3_T1.js @@ -9,12 +9,10 @@ es5id: 15.4.5.1_A2.3_T1 description: length = 100, P in [100, 199] ---*/ -//CHECK#1 var x = Array(100); x[100] = 1; assert.sameValue(x.length, 101, 'The value of x.length is expected to be 101'); -//CHECK#2 x[199] = 1; assert.sameValue(x.length, 200, 'The value of x.length is expected to be 200'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A1_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A1_T1.js index f04edf0c1239..6da4cde919fa 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A1_T1.js @@ -10,23 +10,18 @@ es5id: 15.4.5.2_A1_T1 description: Checking boundary points ---*/ -//CHECK#1 var x = []; assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); -//CHECK#2 x[0] = 1; assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#3 x[1] = 1; assert.sameValue(x.length, 2, 'The value of x.length is expected to be 2'); -//CHECK#4 x[2147483648] = 1; assert.sameValue(x.length, 2147483649, 'The value of x.length is expected to be 2147483649'); -//CHECK#5 x[4294967294] = 1; assert.sameValue(x.length, 4294967295, 'The value of x.length is expected to be 4294967295'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A1_T2.js b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A1_T2.js index 3d6c17443d6a..7cca401c0497 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A1_T2.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A1_T2.js @@ -10,12 +10,10 @@ es5id: 15.4.5.2_A1_T2 description: P = "2^32 - 1" is not index array ---*/ -//CHECK#1 var x = []; x[4294967295] = 1; assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); -//CHECK#2 var y = []; y[1] = 1; y[4294967295] = 1; diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A2_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A2_T1.js index 0a7b44d0029c..f4f37defe321 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A2_T1.js @@ -9,19 +9,15 @@ es5id: 15.4.5.2_A2_T1 description: Checking length property ---*/ -//CHECK#1 var x = []; assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); -//CHECK#2 x[0] = 1; assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#3 x[1] = 1; assert.sameValue(x.length, 2, 'The value of x.length is expected to be 2'); -//CHECK#4 x[9] = 1; assert.sameValue(x.length, 10, 'The value of x.length is expected to be 10'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T1.js b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T1.js index a85944b63c48..bf423b476c3e 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T1.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T1.js @@ -11,12 +11,10 @@ description: > is an array index ---*/ -//CHECK#1 var x = []; x.length = 1; assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#2 x[5] = 1; x.length = 10; assert.sameValue(x.length, 10, 'The value of x.length is expected to be 10'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T2.js b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T2.js index cdb9f27f67b7..1a7de49f0204 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T2.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T2.js @@ -11,7 +11,6 @@ description: > is an array index ---*/ -//CHECK#1 var x = []; x[1] = 1; x[3] = 3; @@ -21,15 +20,12 @@ assert.sameValue(x.length, 4, 'The value of x.length is expected to be 4'); assert.sameValue(x[5], undefined, 'The value of x[5] is expected to equal undefined'); assert.sameValue(x[3], 3, 'The value of x[3] is expected to be 3'); -//CHECK#4 x.length = new Number(6); assert.sameValue(x[5], undefined, 'The value of x[5] is expected to equal undefined'); -//CHECK#5 x.length = 0; assert.sameValue(x[0], undefined, 'The value of x[0] is expected to equal undefined'); -//CHECK#6 x.length = 1; assert.sameValue(x[1], undefined, 'The value of x[1] is expected to equal undefined'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T3.js b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T3.js index ed1ddffc3257..63bee674937c 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T3.js +++ b/js/src/tests/test262/built-ins/Array/S15.4.5.2_A3_T3.js @@ -9,12 +9,10 @@ es5id: 15.4.5.2_A3_T3 description: "[[Put]] (length, 4294967296)" ---*/ -//CHECK#1 var x = []; x.length = 4294967295; assert.sameValue(x.length, 4294967295, 'The value of x.length is expected to be 4294967295'); -//CHECK#2 try { x = []; x.length = 4294967296; diff --git a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T10.js b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T10.js index 7aecee307ca2..6ba208ed862c 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T10.js +++ b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T10.js @@ -9,7 +9,6 @@ es5id: 15.4_A1.1_T10 description: Array index is power of two ---*/ -//CHECK# var x = []; var k = 1; for (var i = 0; i < 32; i++) { diff --git a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T4.js b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T4.js index becd2fecb42e..8918ed2b0841 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T4.js +++ b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T4.js @@ -9,12 +9,10 @@ es5id: 15.4_A1.1_T4 description: Checking for string primitive ---*/ -//CHECK#1 var x = []; x["0"] = 0; assert.sameValue(x[0], 0, 'The value of x[0] is expected to be 0'); -//CHECK#2 var y = []; y["1"] = 1; assert.sameValue(y[1], 1, 'The value of y[1] is expected to be 1'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T5.js b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T5.js index 98006fed2aad..eced3ea7c4a0 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T5.js +++ b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T5.js @@ -9,13 +9,11 @@ es5id: 15.4_A1.1_T5 description: Checking for null and undefined ---*/ -//CHECK#1 var x = []; x[null] = 0; assert.sameValue(x[0], undefined, 'The value of x[0] is expected to equal undefined'); assert.sameValue(x["null"], 0, 'The value of x["null"] is expected to be 0'); -//CHECK#3 var y = []; y[undefined] = 0; assert.sameValue(y[0], undefined, 'The value of y[0] is expected to equal undefined'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T6.js b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T6.js index ce5f4e7256f1..ba9403e4792d 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T6.js +++ b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T6.js @@ -9,13 +9,11 @@ es5id: 15.4_A1.1_T6 description: Checking for Boolean object ---*/ -//CHECK#1 var x = []; x[new Boolean(true)] = 1; assert.sameValue(x[1], undefined, 'The value of x[1] is expected to equal undefined'); assert.sameValue(x["true"], 1, 'The value of x["true"] is expected to be 1'); -//CHECK#3 x[new Boolean(false)] = 0; assert.sameValue(x[0], undefined, 'The value of x[0] is expected to equal undefined'); assert.sameValue(x["false"], 0, 'The value of x["false"] is expected to be 0'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T7.js b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T7.js index 9f6a1ec5549f..119c825b160f 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T7.js +++ b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T7.js @@ -9,17 +9,14 @@ es5id: 15.4_A1.1_T7 description: Checking for Number object ---*/ -//CHECK#1 var x = []; x[new Number(0)] = 0; assert.sameValue(x[0], 0, 'The value of x[0] is expected to be 0'); -//CHECK#2 var y = []; y[new Number(1)] = 1; assert.sameValue(y[1], 1, 'The value of y[1] is expected to be 1'); -//CHECK#3 var z = []; z[new Number(1.1)] = 1; assert.sameValue(z["1.1"], 1, 'The value of z["1.1"] is expected to be 1'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T8.js b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T8.js index f02ab69a1cfa..feb6e094a03d 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T8.js +++ b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T8.js @@ -9,17 +9,14 @@ es5id: 15.4_A1.1_T8 description: Checking for Number object ---*/ -//CHECK#1 var x = []; x[new String("0")] = 0; assert.sameValue(x[0], 0, 'The value of x[0] is expected to be 0'); -//CHECK#2 var y = []; y[new String("1")] = 1; assert.sameValue(y[1], 1, 'The value of y[1] is expected to be 1'); -//CHECK#3 var z = []; z[new String("1.1")] = 1; assert.sameValue(z["1.1"], 1, 'The value of z["1.1"] is expected to be 1'); diff --git a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T9.js b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T9.js index e2ec5019ec04..2b56d5a27bc6 100644 --- a/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T9.js +++ b/js/src/tests/test262/built-ins/Array/S15.4_A1.1_T9.js @@ -9,7 +9,6 @@ es5id: 15.4_A1.1_T9 description: If Type(value) is Object, evaluate ToPrimitive(value, String) ---*/ -//CHECK#1 var x = []; var object = { valueOf: function() { @@ -19,7 +18,6 @@ var object = { x[object] = 0; assert.sameValue(x["[object Object]"], 0, 'The value of x["[object Object]"] is expected to be 0'); -//CHECK#2 x = []; var object = { valueOf: function() { @@ -32,7 +30,6 @@ var object = { x[object] = 0; assert.sameValue(x[0], 0, 'The value of x[0] is expected to be 0'); -//CHECK#3 x = []; var object = { valueOf: function() { @@ -45,7 +42,6 @@ var object = { x[object] = 0; assert.sameValue(x[1], 0, 'The value of x[1] is expected to be 0'); -//CHECK#4 try { x = []; var object = { @@ -63,7 +59,6 @@ catch (e) { assert.notSameValue(e, "error", 'The value of e is not "error"'); } -//CHECK#5 x = []; var object = { toString: function() { @@ -73,7 +68,6 @@ var object = { x[object] = 0; assert.sameValue(x[1], 0, 'The value of x[1] is expected to be 0'); -//CHECK#6 x = []; var object = { valueOf: function() { @@ -86,7 +80,6 @@ var object = { x[object] = 0; assert.sameValue(x[1], 0, 'The value of x[1] is expected to be 0'); -//CHECK#7 try { x = []; var object = { @@ -104,7 +97,6 @@ catch (e) { assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } -//CHECK#8 try { x = []; var object = { diff --git a/js/src/tests/test262/built-ins/Array/from/Array.from-descriptor.js b/js/src/tests/test262/built-ins/Array/from/Array.from-descriptor.js index c468b95e3037..4d68536a30b0 100644 --- a/js/src/tests/test262/built-ins/Array/from/Array.from-descriptor.js +++ b/js/src/tests/test262/built-ins/Array/from/Array.from-descriptor.js @@ -3,8 +3,7 @@ /*--- description: Testing descriptor property of Array.from -includes: - - propertyHelper.js +includes: [propertyHelper.js] esid: sec-array.from ---*/ diff --git a/js/src/tests/test262/built-ins/Array/from/array-like-has-length-but-no-indexes-with-values.js b/js/src/tests/test262/built-ins/Array/from/array-like-has-length-but-no-indexes-with-values.js new file mode 100644 index 000000000000..e83db0f6564a --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/from/array-like-has-length-but-no-indexes-with-values.js @@ -0,0 +1,41 @@ +// Copyright (c) 2021 Rick Waldron. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-array.from +description: > + Creates an array with length that is equal to the value of the + length property of the given array-like, regardless of + the presence of corresponding indices and values. +info: | + Array.from ( items [ , mapfn [ , thisArg ] ] ) + + 7. Let arrayLike be ! ToObject(items). + 8. Let len be ? LengthOfArrayLike(arrayLike). + 9. If IsConstructor(C) is true, then + a. Let A be ? Construct(C, « 𝔽(len) »). + 10. Else, + a. Let A be ? ArrayCreate(len). + +includes: [compareArray.js] +---*/ + +const length = 5; + +const newlyCreatedArray = Array.from({ length }); +assert.sameValue( + newlyCreatedArray.length, + length, + "The newly created array's length is equal to the value of the length property for the provided array like object" +); +assert.compareArray(newlyCreatedArray, [undefined, undefined, undefined, undefined, undefined]); + +const newlyCreatedAndMappedArray = Array.from({ length }).map(x => 1); +assert.sameValue( + newlyCreatedAndMappedArray.length, + length, + "The newly created and mapped array's length is equal to the value of the length property for the provided array like object" +); +assert.compareArray(newlyCreatedAndMappedArray, [1, 1, 1, 1, 1]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/isArray/descriptor.js b/js/src/tests/test262/built-ins/Array/isArray/descriptor.js index 70e5c8fbb922..1c5c6ef73b47 100644 --- a/js/src/tests/test262/built-ins/Array/isArray/descriptor.js +++ b/js/src/tests/test262/built-ins/Array/isArray/descriptor.js @@ -3,8 +3,7 @@ /*--- description: Testing descriptor property of Array.isArray -includes: - - propertyHelper.js +includes: [propertyHelper.js] esid: sec-array.isarray ---*/ diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.1_T1.js index bba60969a36d..c8c9391b0865 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.1_T1.js @@ -13,7 +13,6 @@ description: > this property ---*/ -//CHECK#1 Array.prototype.myproperty = 1; var x = new Array(0); assert.sameValue(x.myproperty, 1, 'The value of x.myproperty is expected to be 1'); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.1_T2.js b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.1_T2.js index 6b81a645ba48..b0f132136737 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.1_T2.js @@ -11,7 +11,6 @@ es5id: 15.4.2.2_A1.1_T2 description: Array.prototype.toString = Object.prototype.toString ---*/ -//CHECK#1 Array.prototype.toString = Object.prototype.toString; var x = new Array(0); assert.sameValue(x.toString(), "[object Array]", 'x.toString() must return "[object Array]"'); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.2_T1.js index 8f8201947280..1e6c52e8cdff 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A1.2_T1.js @@ -8,7 +8,6 @@ es5id: 15.4.2.2_A1.2_T1 description: Checking use Object.prototype.toString ---*/ -//CHECK#1 var x = new Array(0); assert.sameValue(Object.prototype.toString.call(x), "[object Array]", 'Object.prototype.toString.call(new Array(0)) must return "[object Array]"'); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.1_T1.js b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.1_T1.js index b1cd8f613684..da22b03edcd7 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.1_T1.js @@ -10,15 +10,12 @@ es5id: 15.4.2.2_A2.1_T1 description: Array constructor is given one argument ---*/ -//CHECK#1 var x = new Array(0); assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); -//CHECK#2 var x = new Array(1); assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#3 var x = new Array(4294967295); assert.sameValue(x.length, 4294967295, 'The value of x.length is expected to be 4294967295'); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T1.js b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T1.js index ddf3425ab163..87243a739ed5 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T1.js @@ -10,7 +10,6 @@ es5id: 15.4.2.2_A2.2_T1 description: Use try statement. len = -1, 4294967296, 4294967297 ---*/ -//CHECK#1 try { new Array(-1); throw new Test262Error('#1.1: new Array(-1) throw RangeError. Actual: ' + (new Array(-1))); @@ -22,7 +21,6 @@ try { ); } -//CHECK#2 try { new Array(4294967296); throw new Test262Error('#2.1: new Array(4294967296) throw RangeError. Actual: ' + (new Array(4294967296))); @@ -34,7 +32,6 @@ try { ); } -//CHECK#3 try { new Array(4294967297); throw new Test262Error('#3.1: new Array(4294967297) throw RangeError. Actual: ' + (new Array(4294967297))); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T2.js b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T2.js index 3dffff06ea72..9785dccba002 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T2.js @@ -10,7 +10,6 @@ es5id: 15.4.2.2_A2.2_T2 description: Use try statement. len = NaN, +/-Infinity ---*/ -//CHECK#1 try { new Array(NaN); throw new Test262Error('#1.1: new Array(NaN) throw RangeError. Actual: ' + (new Array(NaN))); @@ -22,7 +21,6 @@ try { ); } -//CHECK#2 try { new Array(Number.POSITIVE_INFINITY); throw new Test262Error('#2.1: new Array(Number.POSITIVE_INFINITY) throw RangeError. Actual: ' + (new Array(Number.POSITIVE_INFINITY))); @@ -34,7 +32,6 @@ try { ); } -//CHECK#3 try { new Array(Number.NEGATIVE_INFINITY); throw new Test262Error('#3.1: new Array(Number.NEGATIVE_INFINITY) throw RangeError. Actual: ' + (new Array(Number.NEGATIVE_INFINITY))); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T3.js b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T3.js index 4665c84ba22c..4acedfcaa003 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T3.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.2.2_A2.2_T3.js @@ -10,7 +10,6 @@ es5id: 15.4.2.2_A2.2_T3 description: Use try statement. len = 1.5, Number.MAX_VALUE, Number.MIN_VALUE ---*/ -//CHECK#1 try { new Array(1.5); throw new Test262Error('#1.1: new Array(1.5) throw RangeError. Actual: ' + (new Array(1.5))); @@ -22,7 +21,6 @@ try { ); } -//CHECK#2 try { new Array(Number.MAX_VALUE); throw new Test262Error('#2.1: new Array(Number.MAX_VALUE) throw RangeError. Actual: ' + (new Array(Number.MAX_VALUE))); @@ -34,7 +32,6 @@ try { ); } -//CHECK#3 try { new Array(Number.MIN_VALUE); throw new Test262Error('#3.1: new Array(Number.MIN_VALUE) throw RangeError. Actual: ' + (new Array(Number.MIN_VALUE))); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.1_T1.js index 3f8c633c6ec6..771311678c43 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.1_T1.js @@ -8,7 +8,6 @@ es5id: 15.4.5.1_A1.1_T1 description: length in [4294967296, -1, 1.5] ---*/ -//CHECK#1 try { var x = []; x.length = 4294967296; @@ -21,7 +20,6 @@ try { ); } -//CHECK#2 try { x = []; x.length = -1; @@ -34,7 +32,6 @@ try { ); } -//CHECK#3 try { x = []; x.length = 1.5; diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.1_T2.js b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.1_T2.js index 8f1626d79723..283049dbe474 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.1_T2.js @@ -8,7 +8,6 @@ es5id: 15.4.5.1_A1.1_T2 description: length in [NaN, Infinity, -Infinity, undefined] ---*/ -//CHECK#1 try { var x = []; x.length = NaN; @@ -21,7 +20,6 @@ try { ); } -//CHECK#2 try { x = []; x.length = Number.POSITIVE_INFINITY; @@ -34,7 +32,6 @@ try { ); } -//CHECK#3 try { x = []; x.length = Number.NEGATIVE_INFINITY; @@ -47,7 +44,6 @@ try { ); } -//CHECK#4 try { x = []; x.length = undefined; diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.2_T1.js index c0732bc4aa7c..9084747caeae 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.2_T1.js @@ -12,12 +12,10 @@ es5id: 15.4.5.1_A1.2_T1 description: Change length of array ---*/ -//CHECK#1 var x = [0, , 2, , 4]; x.length = 4; assert.sameValue(x[4], undefined, 'The value of x[4] is expected to equal undefined'); -//CHECK#2 x.length = 3; assert.sameValue(x[3], undefined, 'The value of x[3] is expected to equal undefined'); assert.sameValue(x[2], 2, 'The value of x[2] is expected to be 2'); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.2_T3.js b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.2_T3.js index 38f17683dc55..1d3d0b9911f1 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.2_T3.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.2_T3.js @@ -12,13 +12,11 @@ es5id: 15.4.5.1_A1.2_T3 description: Checking an inherited property ---*/ -//CHECK#1 Array.prototype[2] = 2; var x = [0, 1]; x.length = 3; assert.sameValue(x.hasOwnProperty('2'), false, 'x.hasOwnProperty("2") must return false'); -//CHECK#2 x.length = 2; assert.sameValue(x[2], 2, 'The value of x[2] is expected to be 2'); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.3_T1.js b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.3_T1.js index d855b1d60f9d..711cd65564d3 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.3_T1.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.3_T1.js @@ -8,32 +8,26 @@ es5id: 15.4.5.1_A1.3_T1 description: length is object or primitve ---*/ -//CHECK#1 var x = []; x.length = true; assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#2 x = [0]; x.length = null; assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); -//CHECK#3 x = [0]; x.length = new Boolean(false); assert.sameValue(x.length, 0, 'The value of x.length is expected to be 0'); -//CHECK#4 x = []; x.length = new Number(1); assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#5 x = []; x.length = "1"; assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#6 x = []; x.length = new String("1"); assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.3_T2.js b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.3_T2.js index 4dae8b4289e5..c1b163c5603b 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.3_T2.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.5.1_A1.3_T2.js @@ -8,7 +8,6 @@ es5id: 15.4.5.1_A1.3_T2 description: Uint32 use ToNumber and ToPrimitve ---*/ -//CHECK#1 var x = []; x.length = { valueOf: function() { @@ -17,7 +16,6 @@ x.length = { }; assert.sameValue(x.length, 2, 'The value of x.length is expected to be 2'); -//CHECK#2 x = []; x.length = { valueOf: function() { @@ -29,7 +27,6 @@ x.length = { }; assert.sameValue(x.length, 2, 'The value of x.length is expected to be 2'); -//CHECK#3 x = []; x.length = { valueOf: function() { @@ -41,7 +38,6 @@ x.length = { }; assert.sameValue(x.length, 2, 'The value of x.length is expected to be 2'); -//CHECK#4 try { x = []; x.length = { @@ -58,7 +54,6 @@ catch (e) { assert.notSameValue(e, "error", 'The value of e is not "error"'); } -//CHECK#5 x = []; x.length = { toString: function() { @@ -67,7 +62,6 @@ x.length = { }; assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#6 x = []; x.length = { valueOf: function() { @@ -79,7 +73,6 @@ x.length = { } assert.sameValue(x.length, 1, 'The value of x.length is expected to be 1'); -//CHECK#7 try { x = []; x.length = { @@ -97,7 +90,6 @@ catch (e) { assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } -//CHECK#8 try { x = []; x.length = { diff --git a/js/src/tests/test262/built-ins/Array/length/S15.4.5.2_A3_T4.js b/js/src/tests/test262/built-ins/Array/length/S15.4.5.2_A3_T4.js index 583cad720c6b..a073a7a0ef3a 100644 --- a/js/src/tests/test262/built-ins/Array/length/S15.4.5.2_A3_T4.js +++ b/js/src/tests/test262/built-ins/Array/length/S15.4.5.2_A3_T4.js @@ -12,7 +12,6 @@ description: > is an array index ---*/ -//CHECK#1 var x = [0, 1, 2]; x[4294967294] = 4294967294; x.length = 2; diff --git a/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/array-find-from-last.js b/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/array-find-from-last.js new file mode 100644 index 000000000000..6db4575ecb1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/array-find-from-last.js @@ -0,0 +1,34 @@ +// |reftest| skip -- array-find-from-last is not supported +// Copyright (C) 2022 Microsoft. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype-@@unscopables +description: > + Initial value of `Symbol.unscopables` property +info: | + 22.1.3.32 Array.prototype [ @@unscopables ] + + ... + 7. Perform CreateDataProperty(unscopableList, "findLast", true). + 8. Perform CreateDataProperty(unscopableList, "findLastIndex", true). + ... + +includes: [propertyHelper.js] +features: [Symbol.unscopables, array-find-from-last] +---*/ + +var unscopables = Array.prototype[Symbol.unscopables]; + +assert.sameValue(Object.getPrototypeOf(unscopables), null); + +assert.sameValue(unscopables.findLast, true, '`findLast` property value'); +verifyEnumerable(unscopables, 'findLast'); +verifyWritable(unscopables, 'findLast'); +verifyConfigurable(unscopables, 'findLast'); + +assert.sameValue(unscopables.findLastIndex, true, '`findLastIndex` property value'); +verifyEnumerable(unscopables, 'findLastIndex'); +verifyWritable(unscopables, 'findLastIndex'); +verifyConfigurable(unscopables, 'findLastIndex'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/array-grouping.js b/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/array-grouping.js new file mode 100644 index 000000000000..7ce2097b6819 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/array-grouping.js @@ -0,0 +1,34 @@ +// |reftest| skip -- array-grouping is not supported +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype-@@unscopables +description: > + Initial value of `Symbol.unscopables` property +info: | + 22.1.3.32 Array.prototype [ @@unscopables ] + + ... + 10. Perform ! CreateDataPropertyOrThrow(unscopableList, "groupBy", true). + 11. Perform ! CreateDataPropertyOrThrow(unscopableList, "groupByToMap", true). + ... + +includes: [propertyHelper.js] +features: [Symbol.unscopables, array-grouping] +---*/ + +var unscopables = Array.prototype[Symbol.unscopables]; + +assert.sameValue(Object.getPrototypeOf(unscopables), null); + +assert.sameValue(unscopables.groupBy, true, '`groupBy` property value'); +verifyEnumerable(unscopables, 'groupBy'); +verifyWritable(unscopables, 'groupBy'); +verifyConfigurable(unscopables, 'groupBy'); + +assert.sameValue(unscopables.groupByToMap, true, '`groupByToMap` property value'); +verifyEnumerable(unscopables, 'groupByToMap'); +verifyWritable(unscopables, 'groupByToMap'); +verifyConfigurable(unscopables, 'groupByToMap'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/value.js b/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/value.js index 6de66c916452..3bd5e4fad820 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/value.js +++ b/js/src/tests/test262/built-ins/Array/prototype/Symbol.unscopables/value.js @@ -1,4 +1,3 @@ -// |reftest| skip -- array-find-from-last is not supported // Copyright (C) 2015 Mike Pennisi. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -14,17 +13,16 @@ info: | 4. Perform CreateDataProperty(unscopableList, "fill", true). 5. Perform CreateDataProperty(unscopableList, "find", true). 6. Perform CreateDataProperty(unscopableList, "findIndex", true). - 7. Perform CreateDataProperty(unscopableList, "findLast", true). - 8. Perform CreateDataProperty(unscopableList, "findLastIndex", true). - 9. Perform CreateDataProperty(unscopableList, "flat", true). - 10. Perform CreateDataProperty(unscopableList, "flatMap", true). - 11. Perform CreateDataProperty(unscopableList, "includes", true). - 12. Perform CreateDataProperty(unscopableList, "keys", true). - 13. Perform CreateDataProperty(unscopableList, "values", true). - 14. Assert: Each of the above calls returns true. - 15. Return unscopableList. + 7. Perform CreateDataProperty(unscopableList, "flat", true). + 8. Perform CreateDataProperty(unscopableList, "flatMap", true). + 9. Perform CreateDataProperty(unscopableList, "includes", true). + 10. Perform CreateDataProperty(unscopableList, "keys", true). + 11. Perform CreateDataProperty(unscopableList, "values", true). + 12. Assert: Each of the above calls returns true. + 13. Return unscopableList. + includes: [propertyHelper.js] -features: [Symbol.unscopables, array-find-from-last] +features: [Symbol.unscopables] ---*/ var unscopables = Array.prototype[Symbol.unscopables]; @@ -56,17 +54,6 @@ verifyEnumerable(unscopables, 'findIndex'); verifyWritable(unscopables, 'findIndex'); verifyConfigurable(unscopables, 'findIndex'); - -assert.sameValue(unscopables.findLast, true, '`findLast` property value'); -verifyEnumerable(unscopables, 'findLast'); -verifyWritable(unscopables, 'findLast'); -verifyConfigurable(unscopables, 'findLast'); - -assert.sameValue(unscopables.findLastIndex, true, '`findLastIndex` property value'); -verifyEnumerable(unscopables, 'findLastIndex'); -verifyWritable(unscopables, 'findLastIndex'); -verifyConfigurable(unscopables, 'findLastIndex'); - assert.sameValue(unscopables.flat, true, '`flat` property value'); verifyEnumerable(unscopables, 'flat'); verifyWritable(unscopables, 'flat'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js b/js/src/tests/test262/built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js index 3c1041af9590..7255309870d0 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js +++ b/js/src/tests/test262/built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js @@ -16,22 +16,13 @@ function concatTypedArray(type, elems, modulo) { ta_by_len[i] = items[i] = modulo === false ? i : elems % modulo; } var ta = new type(items); - assert( - compareArray([].concat(ta, ta), [ta, ta]), - 'compareArray([].concat(ta, ta), [ta, ta]) must return true' - ); + assert.compareArray([].concat(ta, ta), [ta, ta]); ta[Symbol.isConcatSpreadable] = true; - assert.compareArray([].concat(ta), items, '[].concat(new type(items)) returns items'); + assert.compareArray([].concat(ta), items); - assert( - compareArray([].concat(ta_by_len, ta_by_len), [ta_by_len, ta_by_len]), - 'compareArray([].concat(ta_by_len, ta_by_len), [ta_by_len, ta_by_len]) must return true' - ); + assert.compareArray([].concat(ta_by_len, ta_by_len), [ta_by_len, ta_by_len]); ta_by_len[Symbol.isConcatSpreadable] = true; - assert( - compareArray([].concat(ta_by_len), items), - 'compareArray([].concat(ta_by_len), items) must return true' - ); + assert.compareArray([].concat(ta_by_len), items); // TypedArray with fake `length`. ta = new type(1); @@ -43,7 +34,7 @@ function concatTypedArray(type, elems, modulo) { value: 4000 }); ta[Symbol.isConcatSpreadable] = true; - assert.compareArray([].concat(ta), expected, '[].concat(new type(1)) returns expected'); + assert.compareArray([].concat(ta), expected); } var max = [Math.pow(2, 8), Math.pow(2, 16), Math.pow(2, 32), false, false]; diff --git a/js/src/tests/test262/built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js b/js/src/tests/test262/built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js index 8b467e3f1ab3..201e0f34b3a1 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js +++ b/js/src/tests/test262/built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js @@ -16,22 +16,13 @@ function concatTypedArray(type, elems, modulo) { ta_by_len[i] = items[i] = modulo === false ? i : elems % modulo; } var ta = new type(items); - assert( - compareArray([].concat(ta, ta), [ta, ta]), - 'compareArray([].concat(ta, ta), [ta, ta]) must return true' - ); + assert.compareArray([].concat(ta, ta), [ta, ta]); ta[Symbol.isConcatSpreadable] = true; - assert.compareArray([].concat(ta), items, '[].concat(new type(items)) returns items'); + assert.compareArray([].concat(ta), items); - assert( - compareArray([].concat(ta_by_len, ta_by_len), [ta_by_len, ta_by_len]), - 'compareArray([].concat(ta_by_len, ta_by_len), [ta_by_len, ta_by_len]) must return true' - ); + assert.compareArray([].concat(ta_by_len, ta_by_len), [ta_by_len, ta_by_len]); ta_by_len[Symbol.isConcatSpreadable] = true; - assert( - compareArray([].concat(ta_by_len), items), - 'compareArray([].concat(ta_by_len), items) must return true' - ); + assert.compareArray([].concat(ta_by_len), items); // TypedArray with fake `length`. ta = new type(1); @@ -43,7 +34,7 @@ function concatTypedArray(type, elems, modulo) { value: 4000 }); ta[Symbol.isConcatSpreadable] = true; - assert.compareArray([].concat(ta), expected, '[].concat(new type(1)) returns expected'); + assert.compareArray([].concat(ta), expected); } var max = [Math.pow(2, 8), Math.pow(2, 16), Math.pow(2, 32), false, false]; [ diff --git a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T1.js index d3046067b60d..7d4bd82f3953 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T1.js @@ -16,7 +16,6 @@ var y = new Array(0, 1); var z = new Array(2, 3, 4); var arr = x.concat(y, z); -//CHECK#0 arr.getClass = Object.prototype.toString; assert.sameValue(arr.getClass(), "[object Array]", 'arr.getClass() must return "[object Array]"'); assert.sameValue(arr[0], 0, 'The value of arr[0] is expected to be 0'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T2.js index 5b83ae22e1b2..1ac86bfd21cb 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T2.js @@ -16,7 +16,6 @@ var y = new Object(); var z = new Array(1, 2); var arr = x.concat(y, z, -1, true, "NaN"); -//CHECK#0 arr.getClass = Object.prototype.toString; assert.sameValue(arr.getClass(), "[object Array]", 'arr.getClass() must return "[object Array]"'); assert.sameValue(arr[0], 0, 'The value of arr[0] is expected to be 0'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T3.js b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T3.js index 62cee3300b1f..efcd31f65d63 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T3.js @@ -14,7 +14,6 @@ description: Checking this algorithm with no items var x = [0, 1]; var arr = x.concat(); -//CHECK#0 arr.getClass = Object.prototype.toString; assert.sameValue(arr.getClass(), "[object Array]", 'arr.getClass() must return "[object Array]"'); assert.sameValue(arr[0], 0, 'The value of arr[0] is expected to be 0'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T4.js b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T4.js index 3b8f357ad647..be7c04c42e81 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A1_T4.js @@ -14,7 +14,6 @@ description: Checking this algorithm, items are [], [,] var x = [, 1]; var arr = x.concat([], [, ]); -//CHECK#0 arr.getClass = Object.prototype.toString; assert.sameValue(arr.getClass(), "[object Array]", 'arr.getClass() must return "[object Array]"'); assert.sameValue(arr[0], undefined, 'The value of arr[0] is expected to equal undefined'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A2_T1.js index 90b4405d475a..8cf2de37a266 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A2_T1.js @@ -16,7 +16,6 @@ var y = new Object(); var z = new Array(1, 2); var arr = x.concat(y, z, -1, true, "NaN"); -//CHECK#0 arr.getClass = Object.prototype.toString; assert.sameValue(arr.getClass(), "[object Array]", 'arr.getClass() must return "[object Array]"'); assert.sameValue(arr[0], x, 'The value of arr[0] is expected to equal the value of x'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A2_T2.js index b9055356f904..8d0efd6b2fae 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/concat/S15.4.4.4_A2_T2.js @@ -14,7 +14,6 @@ var x = {}; x.concat = Array.prototype.concat; var arr = x.concat(); -//CHECK#0 arr.getClass = Object.prototype.toString; assert.sameValue(arr.getClass(), "[object Array]", 'arr.getClass() must return "[object Array]"'); assert.sameValue(arr[0], x, 'The value of arr[0] is expected to equal the value of x'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/copyWithin/coerced-values-target.js b/js/src/tests/test262/built-ins/Array/prototype/copyWithin/coerced-values-target.js index 5c10b67cfe04..dac3cfd53b44 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/copyWithin/coerced-values-target.js +++ b/js/src/tests/test262/built-ins/Array/prototype/copyWithin/coerced-values-target.js @@ -55,4 +55,9 @@ assert.compareArray( '[0, 1, 2, 3].copyWithin(1.5, 0) must return [0, 0, 1, 2]' ); +assert.compareArray( + [0, 1, 2, 3].copyWithin({}, 1), [1, 2, 3, 3], + '[0, 1, 2, 3].copyWithin({}, 1) must return [1, 2, 3, 3]' +); + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/copyWithin/non-negative-target-and-start.js b/js/src/tests/test262/built-ins/Array/prototype/copyWithin/non-negative-target-and-start.js index bdbc65b571ef..da1d411abc92 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/copyWithin/non-negative-target-and-start.js +++ b/js/src/tests/test262/built-ins/Array/prototype/copyWithin/non-negative-target-and-start.js @@ -31,20 +31,24 @@ info: | includes: [compareArray.js] ---*/ -assert(compareArray( - ['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(0, 0), ['a', 'b', 'c', 'd', 'e', 'f'] -), 'compareArray( ["a", "b", "c", "d", "e", "f"].copyWithin(0, 0), ["a", "b", "c", "d", "e", "f"] ) must return true'); +assert.compareArray( + ['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(0, 0), + ['a', 'b', 'c', 'd', 'e', 'f'] +); -assert(compareArray( - ['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(0, 2), ['c', 'd', 'e', 'f', 'e', 'f'] -), 'compareArray( ["a", "b", "c", "d", "e", "f"].copyWithin(0, 2), ["c", "d", "e", "f", "e", "f"] ) must return true'); +assert.compareArray( + ['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(0, 2), + ['c', 'd', 'e', 'f', 'e', 'f'] +); -assert(compareArray( - ['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(3, 0), ['a', 'b', 'c', 'a', 'b', 'c'] -), 'compareArray( ["a", "b", "c", "d", "e", "f"].copyWithin(3, 0), ["a", "b", "c", "a", "b", "c"] ) must return true'); +assert.compareArray( + ['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(3, 0), + ['a', 'b', 'c', 'a', 'b', 'c'] +); -assert(compareArray( - [0, 1, 2, 3, 4, 5].copyWithin(1, 4), [0, 4, 5, 3, 4, 5] -), 'compareArray( [0, 1, 2, 3, 4, 5].copyWithin(1, 4), [0, 4, 5, 3, 4, 5] ) must return true'); +assert.compareArray( + [0, 1, 2, 3, 4, 5].copyWithin(1, 4), + [0, 4, 5, 3, 4, 5] +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/every/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/every/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..fc01a8b091e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/every/callbackfn-resize-arraybuffer.js @@ -0,0 +1,74 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.every +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.every.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return true; + }); + + assert.compareArray(elements, expectedElements, 'elements (shrink)'); + assert.compareArray(indices, expectedIndices, 'indices (shrink)'); + assert.compareArray(arrays, expectedArrays, 'arrays (shrink)'); + assert.sameValue(result, true, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.every.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return true; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, true, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/every/shell.js b/js/src/tests/test262/built-ins/Array/prototype/every/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/every/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/every/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/filter/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/filter/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..bfeaa226de76 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/filter/callbackfn-resize-arraybuffer.js @@ -0,0 +1,74 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.filter +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.filter.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return true; + }); + + assert.compareArray(elements, expectedElements, 'elements (shrink)'); + assert.compareArray(indices, expectedIndices, 'indices (shrink)'); + assert.compareArray(arrays, expectedArrays, 'arrays (shrink)'); + assert.compareArray(result, expectedElements, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.filter.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return true; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.compareArray(result, expectedElements, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/filter/shell.js b/js/src/tests/test262/built-ins/Array/prototype/filter/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/filter/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/filter/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/find/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/find/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..7ef357bb6529 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/find/callbackfn-resize-arraybuffer.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.find +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.find.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, undefined, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.find.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, undefined, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/find/shell.js b/js/src/tests/test262/built-ins/Array/prototype/find/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/find/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/find/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/findIndex/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/findIndex/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..fd6dbdf7f780 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/findIndex/callbackfn-resize-arraybuffer.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.findindex +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.findIndex.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, -1, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.findIndex.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, -1, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/findIndex/shell.js b/js/src/tests/test262/built-ins/Array/prototype/findIndex/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/findIndex/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/findIndex/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/findLast/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/findLast/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..0894ee74f944 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/findLast/callbackfn-resize-arraybuffer.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.findlast +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var secondElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.findLast.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(BPE); + secondElement = undefined; + expectedElements = [0]; + expectedIndices = [0]; + expectedArrays = [sample]; + } catch (_) { + secondElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [2, 1, 0]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, secondElement, 0], 'elements (shrink)'); + assert.compareArray(indices, [2, 1, 0], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, undefined, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.findLast.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, undefined, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/findLast/shell.js b/js/src/tests/test262/built-ins/Array/prototype/findLast/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/findLast/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/findLast/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/findLastIndex/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/findLastIndex/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..7434053f2105 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/findLastIndex/callbackfn-resize-arraybuffer.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.findlastindex +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var secondElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.findLastIndex.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(BPE); + secondElement = undefined; + expectedElements = [0]; + expectedIndices = [0]; + expectedArrays = [sample]; + } catch (_) { + secondElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [2, 1, 0]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, secondElement, 0], 'elements (shrink)'); + assert.compareArray(indices, [2, 1, 0], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, -1, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.findLastIndex.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, -1, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/findLastIndex/shell.js b/js/src/tests/test262/built-ins/Array/prototype/findLastIndex/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/findLastIndex/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/findLastIndex/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/forEach/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/forEach/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..2d358fa12620 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/forEach/callbackfn-resize-arraybuffer.js @@ -0,0 +1,72 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.forEach +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.forEach.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + }); + + assert.compareArray(elements, expectedElements, 'elements (shrink)'); + assert.compareArray(indices, expectedIndices, 'indices (shrink)'); + assert.compareArray(arrays, expectedArrays, 'arrays (shrink)'); + assert.sameValue(result, undefined, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.forEach.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, undefined, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/forEach/shell.js b/js/src/tests/test262/built-ins/Array/prototype/forEach/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/forEach/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/forEach/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.1_T1.js index 2128df5a9917..3fb2f8312434 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.1_T1.js @@ -7,13 +7,11 @@ esid: sec-array.prototype.join description: Checking this use new Array() and [] ---*/ -//CHECK#1 var x = new Array(); if (x.join() !== "") { throw new Test262Error('#1: x = new Array(); x.join() === "". Actual: ' + (x.join())); } -//CHECK#2 x = []; x[0] = 1; x.length = 0; diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.2_T1.js index b4c69887f930..4107dafdb2da 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.2_T1.js @@ -7,13 +7,11 @@ esid: sec-array.prototype.join description: Checking this use new Array() and [] ---*/ -//CHECK#1 var x = new Array(0, 1, 2, 3); if (x.join() !== "0,1,2,3") { throw new Test262Error('#1: x = new Array(0,1,2,3); x.join() === "0,1,2,3". Actual: ' + (x.join())); } -//CHECK#2 x = []; x[0] = 0; x[3] = 3; @@ -21,7 +19,6 @@ if (x.join() !== "0,,,3") { throw new Test262Error('#2: x = []; x[0] = 0; x[3] = 3; x.join() === "0,,,3". Actual: ' + (x.join())); } -//CHECK#3 x = []; x[0] = 0; if (x.join() !== "0") { diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.2_T2.js index 8ad0faded12a..bea80dc36e83 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.2_T2.js @@ -7,13 +7,11 @@ esid: sec-array.prototype.join description: Checking this use new Array() and [] ---*/ -//CHECK#1 var x = new Array(0, 1, 2, 3); if (x.join(undefined) !== "0,1,2,3") { throw new Test262Error('#1: x = new Array(0,1,2,3); x.join(undefined) === "0,1,2,3". Actual: ' + (x.join(undefined))); } -//CHECK#2 x = []; x[0] = 0; x[3] = 3; @@ -21,7 +19,6 @@ if (x.join(undefined) !== "0,,,3") { throw new Test262Error('#2: x = []; x[0] = 0; x[3] = 3; x.join(undefined) === "0,,,3". Actual: ' + (x.join(undefined))); } -//CHECK#3 x = []; x[0] = 0; if (x.join(undefined) !== "0") { diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.3_T1.js index 5340097adac5..23c0bf98aa51 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A1.3_T1.js @@ -7,21 +7,18 @@ esid: sec-array.prototype.join description: Checking this use new Array() and [] ---*/ -//CHECK#1 var x = []; x[0] = undefined; if (x.join() !== "") { throw new Test262Error('#1: x = []; x[0] = undefined; x.join() === "". Actual: ' + (x.join())); } -//CHECK#2 x = []; x[0] = null; if (x.join() !== "") { throw new Test262Error('#2: x = []; x[0] = null; x.join() === "". Actual: ' + (x.join())); } -//CHECK#3 x = Array(undefined, 1, null, 3); if (x.join() !== ",1,,3") { throw new Test262Error('#3: x = Array(undefined,1,null,3); x.join() === ",1,,3". Actual: ' + (x.join())); diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T1.js index d62dbc069da9..376711262697 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T1.js @@ -15,34 +15,28 @@ obj.join = Array.prototype.join; if (obj.length !== undefined) { throw new Test262Error('#0: var obj = {}; obj.length === undefined. Actual: ' + (obj.length)); } else { - //CHECK#1 if (obj.join() !== "") { throw new Test262Error('#1: var obj = {}; obj.join = Array.prototype.join; obj.join() === "". Actual: ' + (obj.join())); } - //CHECK#2 if (obj.length !== undefined) { throw new Test262Error('#2: var obj = {}; obj.join = Array.prototype.join; obj.join(); obj.length === undefined. Actual: ' + (obj.length)); } } -//CHECK#3 obj.length = undefined; if (obj.join() !== "") { throw new Test262Error('#3: var obj = {}; obj.length = undefined; obj.join = Array.prototype.join; obj.join() === ". Actual: ' + (obj.join())); } -//CHECK#4 if (obj.length !== undefined) { throw new Test262Error('#4: var obj = {}; obj.length = undefined; obj.join = Array.prototype.join; obj.join(); obj.length === undefined. Actual: ' + (obj.length)); } -//CHECK#5 obj.length = null if (obj.join() !== "") { throw new Test262Error('#5: var obj = {}; obj.length = null; obj.join = Array.prototype.join; obj.join() === "". Actual: ' + (obj.join())); } -//CHECK#6 if (obj.length !== null) { throw new Test262Error('#6: var obj = {}; obj.length = null; obj.join = Array.prototype.join; obj.join(); obj.length === null. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T2.js index 0e36a6a718ea..ef3b1004ece0 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T2.js @@ -12,33 +12,27 @@ description: If ToUint32(length) is zero, return the empty string var obj = {}; obj.join = Array.prototype.join; -//CHECK#1 obj.length = NaN; if (obj.join() !== "") { throw new Test262Error('#1: var obj = {}; obj.length = NaN; obj.join = Array.prototype.join; obj.join() === "". Actual: ' + (obj.join())); } -//CHECK#2 assert.sameValue(obj.length, NaN, "obj.length is NaN"); -//CHECK#5 obj.length = Number.NEGATIVE_INFINITY; if (obj.join() !== "") { throw new Test262Error('#5: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.join = Array.prototype.join; obj.join() === "". Actual: ' + (obj.join())); } -//CHECK#6 if (obj.length !== Number.NEGATIVE_INFINITY) { throw new Test262Error('#6: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.join = Array.prototype.join; obj.join(); obj.length === Number.NEGATIVE_INFINITY. Actual: ' + (obj.length)); } -//CHECK#7 obj.length = -0; if (obj.join() !== "") { throw new Test262Error('#7: var obj = {}; obj.length = -0; obj.join = Array.prototype.join; obj.join() === "". Actual: ' + (obj.join())); } -//CHECK#8 if (obj.length !== -0) { throw new Test262Error('#8: var obj = {}; obj.length = -0; obj.join = Array.prototype.join; obj.join(); obj.length === 0. Actual: ' + (obj.length)); } else { @@ -47,25 +41,21 @@ if (obj.length !== -0) { } } -//CHECK#9 obj.length = 0.5; if (obj.join() !== "") { throw new Test262Error('#9: var obj = {}; obj.length = 0.5; obj.join = Array.prototype.join; obj.join() === "". Actual: ' + (obj.join())); } -//CHECK#10 if (obj.length !== 0.5) { throw new Test262Error('#10: var obj = {}; obj.length = 0.5; obj.join = Array.prototype.join; obj.join(); obj.length === 0.5. Actual: ' + (obj.length)); } -//CHECK#11 var x = new Number(0); obj.length = x; if (obj.join() !== "") { throw new Test262Error('#11: var x = new Number(0); var obj = {}; obj.length = x; obj.join = Array.prototype.join; obj.join() === "". Actual: ' + (obj.join())); } -//CHECK#12 if (obj.length !== x) { throw new Test262Error('#12: var x = new Number(0); var obj = {}; obj.length = x; obj.join = Array.prototype.join; obj.join(); obj.length === x. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T3.js index 7217657f9bc7..edd94bbfb1f9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T3.js @@ -12,13 +12,11 @@ description: If ToUint32(length) is zero, return the empty string var obj = {}; obj.join = Array.prototype.join; -//CHECK#1 obj.length = 4.5; if (obj.join() !== ",,,") { throw new Test262Error('#1: var obj = {}; obj.length = 4.5; obj.join = Array.prototype.join; obj.join() === ",,,". Actual: ' + (obj.join())); } -//CHECK#2 obj[0] = undefined; obj[1] = 1; obj[2] = null; @@ -26,7 +24,6 @@ if (obj.join() !== ",1,,") { throw new Test262Error('#1: var obj = {}; obj.length = 4.5; obj[0] = undefined; obj[1] = 1; obj[2] = null; obj.join = Array.prototype.join; obj.join() === ",1,,". Actual: ' + (obj.join())); } -//CHECK#3 if (obj.length !== 4.5) { throw new Test262Error('#1: var obj = {}; obj.length = 4.5; obj[0] = undefined; obj[1] = 1; obj[2] = null; obj.join = Array.prototype.join; obj.join(); obj.length === 4.5. Actual: ' + (obj.length)); } @@ -34,14 +31,12 @@ if (obj.length !== 4.5) { var obj = {}; obj.join = Array.prototype.join; -//CHECK#4 var x = new Number(4.5); obj.length = x; if (obj.join() !== ",,,") { throw new Test262Error('#4: var obj = {}; var x = new Number(4.5); obj.length = x; obj.join = Array.prototype.join; obj.join() === ",,,". Actual: ' + (obj.join())); } -//CHECK#5 obj[0] = undefined; obj[1] = 1; obj[2] = null; @@ -49,7 +44,6 @@ if (obj.join() !== ",1,,") { throw new Test262Error('#5: var obj = {}; var x = new Number(4.5); obj.length = x; obj[0] = undefined; obj[1] = 1; obj[2] = null; obj.join = Array.prototype.join; obj.join() === ",1,,". Actual: ' + (obj.join())); } -//CHECK#6 if (obj.length !== x) { throw new Test262Error('#6: var obj = {}; var x = new Number(4.5); obj.length = x; obj[0] = undefined; obj[1] = 1; obj[2] = null; obj.join = Array.prototype.join; obj.join(); obj.length === x. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T4.js index 52a12181ec3c..a7b77ba9743f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A2_T4.js @@ -14,123 +14,82 @@ description: > var obj = {}; obj.join = Array.prototype.join; -//CHECK#1 obj.length = { - valueOf: function() { + valueOf() { return 3 } }; -if (obj.join() !== ",,") { - throw new Test262Error('#1: obj.length = {valueOf: function() {return 3}} obj.join() === ",,". Actual: ' + (obj.join())); -} +assert.sameValue(obj.join(), ",,", 'obj.join() must return ",,"'); -//CHECK#2 obj.length = { - valueOf: function() { + valueOf() { return 3 }, - toString: function() { + toString() { return 2 } }; -if (obj.join() !== ",,") { - throw new Test262Error('#2: obj.length = {valueOf: function() {return 3}, toString: function() {return 2}} obj.join() === ",,". Actual: ' + (obj.join())); -} +assert.sameValue(obj.join(), ",,", 'obj.join() must return ",,"'); -//CHECK#3 obj.length = { - valueOf: function() { + valueOf() { return 3 }, - toString: function() { + toString() { return {} } }; -if (obj.join() !== ",,") { - throw new Test262Error('#3: obj.length = {valueOf: function() {return 3}, toString: function() {return {}}} obj.join() === ",,". Actual: ' + (obj.join())); -} +assert.sameValue(obj.join(), ",,", 'obj.join() must return ",,"'); -//CHECK#4 -try { - obj.length = { - valueOf: function() { - return 3 - }, - toString: function() { - throw "error" - } - }; - if (obj.join() !== ",,") { - throw new Test262Error('#4.1: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.join() === ",". Actual: ' + (obj.join())); - } -} -catch (e) { - if (e === "error") { - throw new Test262Error('#4.2: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.join() not throw "error"'); - } else { - throw new Test262Error('#4.3: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.join() not throw Error. Actual: ' + (e)); - } -} - -//CHECK#5 obj.length = { - toString: function() { + valueOf() { + return 3 + }, + toString() { + throw new Test262Error(); + } +}; +assert.sameValue(obj.join(), ",,", 'obj.join() must return ",,"'); + +obj.length = { + toString() { return 2 } }; -if (obj.join() !== ",") { - throw new Test262Error('#5: obj.length = {toString: function() {return 2}} obj.join() === ",". Actual: ' + (obj.join())); -} +assert.sameValue(obj.join(), ",", 'obj.join() must return ","'); -//CHECK#6 obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return 2 } } -if (obj.join() !== ",") { - throw new Test262Error('#6: obj.length = {valueOf: function() {return {}}, toString: function() {return 2}} obj.join() === ",". Actual: ' + (obj.join())); -} +assert.sameValue(obj.join(), ",", 'obj.join() must return ","'); -//CHECK#7 -try { +assert.throws(Test262Error, () => { obj.length = { - valueOf: function() { - throw "error" + valueOf() { + throw new Test262Error(); }, - toString: function() { + toString() { return 2 } }; obj.join(); - throw new Test262Error('#7.1: obj.length = {valueOf: function() {throw "error"}, toString: function() {return 2}}; obj.join() throw "error". Actual: ' + (obj.join())); -} -catch (e) { - if (e !== "error") { - throw new Test262Error('#7.2: obj.length = {valueOf: function() {throw "error"}, toString: function() {return 2}}; obj.join() throw "error". Actual: ' + (e)); - } -} +}); -//CHECK#8 -try { +assert.throws(TypeError, () => { obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return {} } }; obj.join(); - throw new Test262Error('#8.1: obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.join() throw TypeError. Actual: ' + (obj.join())); -} -catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#8,2: obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.join() throw TypeError. Actual: ' + (e)); - } -} +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T1.js index 43a698a363c8..1f8dcd4d7173 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T1.js @@ -9,44 +9,36 @@ description: > undefind, NaN] ---*/ -//CHECK#0 var x = new Array(0, 1, 2, 3); if (x.join("") !== "0123") { throw new Test262Error('#0: x = new Array(0,1,2,3); x.join("") === "0123". Actual: ' + (x.join(""))); } -//CHECK#1 x = new Array(0, 1, 2, 3); if (x.join("\\") !== "0\\1\\2\\3") { throw new Test262Error('#1: x = new Array(0,1,2,3); x.join("\\") === "0\\1\\2\\3". Actual: ' + (x.join("\\"))); } -//CHECK#2 if (x.join("&") !== "0&1&2&3") { throw new Test262Error('#2: x = new Array(0,1,2,3); x.join("&") === "0&1&2&3". Actual: ' + (x.join("&"))); } -//CHECK#3 if (x.join(true) !== "0true1true2true3") { throw new Test262Error('#3: x = new Array(0,1,2,3); x.join(true) === "0true1true2true3". Actual: ' + (x.join(true))); } -//CHECK#4 if (x.join(Infinity) !== "0Infinity1Infinity2Infinity3") { throw new Test262Error('#4: x = new Array(0,1,2,3); x.join(Infinity) === "0Infinity1Infinity2Infinity3". Actual: ' + (x.join(Infinity))); } -//CHECK#5 if (x.join(null) !== "0null1null2null3") { throw new Test262Error('#3: 5 = new Array(0,1,2,3); x.join(null) === "0null1null2null3". Actual: ' + (x.join(null))); } -//CHECK#6 if (x.join(undefined) !== "0,1,2,3") { throw new Test262Error('#6: x = new Array(0,1,2,3); x.join(undefined) === "0,1,2,3". Actual: ' + (x.join(undefined))); } -//CHECK#7 if (x.join(NaN) !== "0NaN1NaN2NaN3") { throw new Test262Error('#7: x = new Array(0,1,2,3); x.join(NaN) === "0NaN1NaN2NaN3". Actual: ' + (x.join(NaN))); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T2.js index 751a2cf7ac4b..7ceea3ef984b 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T2.js @@ -10,139 +10,137 @@ description: > ---*/ var x = new Array(0, 1, 2, 3); -//CHECK#1 var object = { - valueOf: function() { + valueOf() { return "+" } }; -if (x.join(object) !== "0[object Object]1[object Object]2[object Object]3") { - throw new Test262Error('#1: var object = {valueOf: function() {return "+"}}; x.join(object) === "0[object Object]1[object Object]2[object Object]3". Actual: ' + (x.join(object))); -} -//CHECK#2 +assert.sameValue( + x.join(object), + "0[object Object]1[object Object]2[object Object]3", + 'x.join({valueOf() {return "+"}}) must return "0[object Object]1[object Object]2[object Object]3"' +); + var object = { - valueOf: function() { + valueOf() { return "+" }, - toString: function() { + toString() { return "*" } }; -if (x.join(object) !== "0*1*2*3") { - throw new Test262Error('#2: var object = {valueOf: function() {return "+"}, toString: function() {return "*"}}; x.join(object) === "0*1*2*3". Actual: ' + (x.join(object))); -} -//CHECK#3 +assert.sameValue( + x.join(object), + "0*1*2*3", + 'x.join("{valueOf() {return "+"}, toString() {return "*"}}) must return "0*1*2*3"' +); + var object = { - valueOf: function() { + valueOf() { return "+" }, - toString: function() { + toString() { return {} } }; -if (x.join(object) !== "0+1+2+3") { - throw new Test262Error('#3: var object = {valueOf: function() {return "+"}, toString: function() {return {}}}; x.join(object) === "0+1+2+3". Actual: ' + (x.join(object))); -} -//CHECK#4 +assert.sameValue( + x.join(object), + "0+1+2+3", + 'x.join({valueOf() {return "+"}, toString() {return {}}}) must return "0+1+2+3"' +); + try { var object = { - valueOf: function() { + valueOf() { throw "error" }, - toString: function() { + toString() { return "*" } }; - if (x.join(object) !== "0*1*2*3") { - throw new Test262Error('#4.1: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}}; x.join(object) === "0*1*2*3". Actual: ' + (x.join(object))); - } + + assert.sameValue( + x.join(object), + "0*1*2*3", + 'x.join("{valueOf() {throw "error"}, toString() {return "*"}}) must return "0*1*2*3"' + ); } catch (e) { - if (e === "error") { - throw new Test262Error('#4.2: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}}; x.join(object) not throw "error"'); - } else { - throw new Test262Error('#4.3: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}}; x.join(object) not throw Error. Actual: ' + (e)); - } + assert.notSameValue(e, "error", 'The value of e is not "error"'); } -//CHECK#5 var object = { - toString: function() { + toString() { return "*" } }; -if (x.join(object) !== "0*1*2*3") { - throw new Test262Error('#5: var object = {toString: function() {return "*"}}; x.join(object) === "0*1*2*3". Actual: ' + (x.join(object))); -} +assert.sameValue(x.join(object), "0*1*2*3", 'x.join({toString() {return "*"}}) must return "0*1*2*3"'); -//CHECK#6 var object = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return "*" } } -if (x.join(object) !== "0*1*2*3") { - throw new Test262Error('#6: var object = {valueOf: function() {return {}}, toString: function() {return "*"}}; x.join(object) === "0*1*2*3". Actual: ' + (x.join(object))); -} -//CHECK#7 +assert.sameValue( + x.join(object), + "0*1*2*3", + 'x.join({valueOf() {return {}}, toString() {return "*"}}) must return "0*1*2*3"' +); + try { var object = { - valueOf: function() { + valueOf() { return "+" }, - toString: function() { + toString() { throw "error" } }; x.join(object); - throw new Test262Error('#7.1: var object = {valueOf: function() {return "+"}, toString: function() {throw "error"}}; x.join(object) throw "error". Actual: ' + (x.join(object))); + throw new Test262Error('#7.1: var object = {valueOf() {return "+"}, toString() {throw "error"}}; x.join(object) throw "error". Actual: ' + (x.join(object))); } catch (e) { - if (e !== "error") { - throw new Test262Error('#7.2: var object = {valueOf: function() {return "+"}, toString: function() {throw "error"}}; x.join(object) throw "error". Actual: ' + (e)); - } + assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } -//CHECK#8 try { var object = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return {} } }; x.join(object); - throw new Test262Error('#8.1: var object = {valueOf: function() {return {}}, toString: function() {return {}}}; x.join(object) throw TypeError. Actual: ' + (x.join(object))); + throw new Test262Error('#8.1: var object = {valueOf() {return {}}, toString() {return {}}}; x.join(object) throw TypeError. Actual: ' + (x.join(object))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#8.2: var object = {valueOf: function() {return {}}, toString: function() {return {}}}; x.join(object) throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } -//CHECK#9 try { var object = { - toString: function() { + toString() { throw "error" } }; [].join(object); - throw new Test262Error('#9.1: var object = {toString: function() {throw "error"}}; [].join(object) throw "error". Actual: ' + ([].join(object))); + throw new Test262Error('#9.1: var object = {toString() {throw "error"}}; [].join(object) throw "error". Actual: ' + ([].join(object))); } catch (e) { - if (e !== "error") { - throw new Test262Error('#9.2: var object = {toString: function() {throw "error"}}; [].join(object) throw "error". Actual: ' + (e)); - } + assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T1.js index 336be1de95a3..bcea5c423972 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T1.js @@ -9,49 +9,41 @@ description: > Infinity, null, undefind, NaN] ---*/ -//CHECK#0 var x = new Array("", "", ""); if (x.join("") !== "") { throw new Test262Error('#0: var x = new Array("","",""); x.join("") === "". Actual: ' + (x.join(""))); } -//CHECK#1 var x = new Array("\\", "\\", "\\"); if (x.join("\\") !== "\\\\\\\\\\") { throw new Test262Error('#1: var x = new Array("\\","\\","\\"); x.join("\\") === "\\\\\\\\\\". Actual: ' + (x.join("\\"))); } -//CHECK#2 var x = new Array("&", "&", "&"); if (x.join("&") !== "&&&&&") { throw new Test262Error('#2: var x = new Array("&", "&", "&"); x.join("&") === "&&&&&". Actual: ' + (x.join("&"))); } -//CHECK#3 var x = new Array(true, true, true); if (x.join() !== "true,true,true") { throw new Test262Error('#3: var x = new Array(true,true,true); x.join(true,true,true) === "true,true,true". Actual: ' + (x.join(true, true, true))); } -//CHECK#4 var x = new Array(null, null, null); if (x.join() !== ",,") { throw new Test262Error('#4: var x = new Array(null,null,null); x.join(null,null,null) === ",,". Actual: ' + (x.join(null, null, null))); } -//CHECK#5 var x = new Array(undefined, undefined, undefined); if (x.join() !== ",,") { throw new Test262Error('#5: var x = new Array(undefined,undefined,undefined); x.join(undefined,undefined,undefined) === ",,". Actual: ' + (x.join(undefined, undefined, undefined))); } -//CHECK#6 var x = new Array(Infinity, Infinity, Infinity); if (x.join() !== "Infinity,Infinity,Infinity") { throw new Test262Error('#6: var x = new Array(Infinity,Infinity,Infinity); x.join(Infinity,Infinity,Infinity) === "Infinity,Infinity,Infinity". Actual: ' + (x.join(Infinity, Infinity, Infinity))); } -//CHECK#7 var x = new Array(NaN, NaN, NaN); if (x.join() !== "NaN,NaN,NaN") { throw new Test262Error('#7: var x = new Array(NaN,NaN,NaN); x.join(NaN,NaN,NaN) === "NaN,NaN,NaN". Actual: ' + (x.join(NaN, NaN, NaN))); diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T2.js index 764e962d71d3..047a76bed62f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T2.js @@ -7,18 +7,14 @@ esid: sec-array.prototype.join description: If Type(argument) is Object, evaluate ToPrimitive(argument, String) ---*/ -//CHECK#1 var object = { valueOf: function() { return "+" } }; var x = new Array(object); -if (x.join() !== "[object Object]") { - throw new Test262Error('#1: var object = {valueOf: function() {return "+"}} var x = new Array(object); x.join() === "[object Object]". Actual: ' + (x.join())); -} +assert.sameValue(x.join(), "[object Object]", 'x.join() must return "[object Object]"'); -//CHECK#2 var object = { valueOf: function() { return "+" @@ -28,11 +24,8 @@ var object = { } }; var x = new Array(object); -if (x.join() !== "*") { - throw new Test262Error('#2: var object = {valueOf: function() {return "+"}, toString: function() {return "*"}} var x = new Array(object); x.join() === "*". Actual: ' + (x.join())); -} +assert.sameValue(x.join(), "*", 'x.join() must return "*"'); -//CHECK#3 var object = { valueOf: function() { return "+" @@ -42,11 +35,8 @@ var object = { } }; var x = new Array(object); -if (x.join() !== "+") { - throw new Test262Error('#3: var object = {valueOf: function() {return "+"}, toString: function() {return {}}} var x = new Array(object); x.join() === "+". Actual: ' + (x.join())); -} +assert.sameValue(x.join(), "+", 'x.join() must return "+"'); -//CHECK#4 try { var object = { valueOf: function() { @@ -57,30 +47,20 @@ try { } }; var x = new Array(object); - if (x.join() !== "*") { - throw new Test262Error('#4.1: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}} var x = new Array(object); x.join() === "*". Actual: ' + (x.join())); - } + assert.sameValue(x.join(), "*", 'x.join() must return "*"'); } catch (e) { - if (e === "error") { - throw new Test262Error('#4.2: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}} var x = new Array(object); x.join() not throw "error"'); - } else { - throw new Test262Error('#4.3: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}} var x = new Array(object); x.join() not throw Error. Actual: ' + (e)); - } + assert.notSameValue(e, "error", 'The value of e is not "error"'); } -//CHECK#5 var object = { toString: function() { return "*" } }; var x = new Array(object); -if (x.join() !== "*") { - throw new Test262Error('#5: var object = {toString: function() {return "*"}} var x = new Array(object); x.join() === "*". Actual: ' + (x.join())); -} +assert.sameValue(x.join(), "*", 'x.join() must return "*"'); -//CHECK#6 var object = { valueOf: function() { return {} @@ -90,11 +70,8 @@ var object = { } } var x = new Array(object); -if (x.join() !== "*") { - throw new Test262Error('#6: var object = {valueOf: function() {return {}}, toString: function() {return "*"}} var x = new Array(object); x.join() === "*". Actual: ' + (x.join())); -} +assert.sameValue(x.join(), "*", 'x.join() must return "*"'); -//CHECK#7 try { var object = { valueOf: function() { @@ -109,12 +86,9 @@ try { throw new Test262Error('#7.1: var object = {valueOf: function() {return "+"}, toString: function() {throw "error"}} var x = new Array(object); x.join() throw "error". Actual: ' + (x.join())); } catch (e) { - if (e !== "error") { - throw new Test262Error('#7.2: var object = {valueOf: function() {return "+"}, toString: function() {throw "error"}} var x = new Array(object); x.join() throw "error". Actual: ' + (e)); - } + assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } -//CHECK#8 try { var object = { valueOf: function() { @@ -129,9 +103,11 @@ try { throw new Test262Error('#8.1: var object = {valueOf: function() {return {}}, toString: function() {return {}}} var x = new Array(object); x.join() throw TypeError. Actual: ' + (x.join())); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#8.2: var object = {valueOf: function() {return {}}, toString: function() {return {}}} var x = new Array(object); x.join() throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A4_T3.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A4_T3.js index b4a88c7438d8..c199dd621002 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A4_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A4_T3.js @@ -14,12 +14,10 @@ obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; -//CHECK#1 if (obj.join("") !== "") { throw new Test262Error('#1: var obj = {}; obj.join = Array.prototype.join; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.join("") === "". Actual: ' + (obj.join(""))); } -//CHECK#2 if (obj.length !== -4294967294) { throw new Test262Error('#2: var obj = {}; obj.join = Array.prototype.join; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.join(""); obj.length === -4294967294. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A5_T1.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A5_T1.js index 91dee3dfbfa4..781cb601d226 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A5_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A5_T1.js @@ -9,7 +9,6 @@ description: > of Array.prototype is Object.prototype ---*/ -//CHECK#1 Array.prototype[1] = 1; var x = [0]; x.length = 2; @@ -17,7 +16,6 @@ if (x.join() !== "0,1") { throw new Test262Error('#1: Array.prototype[1] = 1; x = [0]; x.length = 2; x.join() === "0,1". Actual: ' + (x.join())); } -//CHECK#2 Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.join = Array.prototype.join; diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A6.6.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A6.6.js index e221e014ad5e..1772e0438605 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A6.6.js +++ b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A6.6.js @@ -7,7 +7,6 @@ esid: sec-array.prototype.join description: Checking Array.prototype.join.prototype ---*/ -//CHECK#1 if (Array.prototype.join.prototype !== undefined) { throw new Test262Error('#1: Array.prototype.join.prototype === undefined. Actual: ' + (Array.prototype.join.prototype)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A6.7.js b/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A6.7.js deleted file mode 100644 index 2c036a5107ff..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/join/S15.4.4.5_A6.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The join property of Array can't be used as constructor -esid: sec-array.prototype.join -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.join(); - throw new Test262Error('#1.1: new Array.prototype.join() throw TypeError. Actual: ' + (new Array.prototype.join())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.join() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/map/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/map/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..943763074b6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/map/callbackfn-resize-arraybuffer.js @@ -0,0 +1,78 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.map +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalResult, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.map.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalResult = undefined; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalResult = 2; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + + return index; + }); + + assert.compareArray(elements, expectedElements, 'elements (shrink)'); + assert.compareArray(indices, expectedIndices, 'indices (shrink)'); + assert.compareArray(arrays, expectedArrays, 'arrays (shrink)'); + assert.compareArray(result, [0, 1, finalResult], 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.map.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + + return index; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.compareArray(result, expectedIndices, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/map/shell.js b/js/src/tests/test262/built-ins/Array/prototype/map/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/map/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/map/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A1.1_T1.js index b4bfa3311268..6463da32ccf1 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A1.1_T1.js @@ -9,19 +9,16 @@ esid: sec-array.prototype.pop description: Checking this algorithm ---*/ -//CHECK#1 var x = new Array(); var pop = x.pop(); if (pop !== undefined) { throw new Test262Error('#1: var x = new Array(); x.pop() === undefined. Actual: ' + (pop)); } -//CHECK#2 if (x.length !== 0) { throw new Test262Error('#2: var x = new Array(); x.pop(); x.length === 0. Actual: ' + (x.length)); } -//CHECK#3 var x = Array(1, 2, 3); x.length = 0; var pop = x.pop(); @@ -29,7 +26,6 @@ if (pop !== undefined) { throw new Test262Error('#2: var x = Array(1,2,3); x.length = 0; x.pop() === undefined. Actual: ' + (pop)); } -//CHECK#4 if (x.length !== 0) { throw new Test262Error('#4: var x = new Array(1,2,3); x.length = 0; x.pop(); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A1.2_T1.js index adc8affdfba5..97cab3dc1e7f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A1.2_T1.js @@ -9,29 +9,24 @@ esid: sec-array.prototype.pop description: Checking this use new Array() and [] ---*/ -//CHECK#1 var x = new Array(0, 1, 2, 3); var pop = x.pop(); if (pop !== 3) { throw new Test262Error('#1: x = new Array(0,1,2,3); x.pop() === 3. Actual: ' + (pop)); } -//CHECK#2 if (x.length !== 3) { throw new Test262Error('#2: x = new Array(0,1,2,3); x.pop(); x.length == 3'); } -//CHECK#3 if (x[3] !== undefined) { throw new Test262Error('#3: x = new Array(0,1,2,3); x.pop(); x[3] == undefined'); } -//CHECK#4 if (x[2] !== 2) { throw new Test262Error('#4: x = new Array(0,1,2,3); x.pop(); x[2] == 2'); } -//CHECK#5 x = []; x[0] = 0; x[3] = 3; @@ -40,29 +35,24 @@ if (pop !== 3) { throw new Test262Error('#5: x = []; x[0] = 0; x[3] = 3; x.pop() === 3. Actual: ' + (pop)); } -//CHECK#6 if (x.length !== 3) { throw new Test262Error('#6: x = []; x[0] = 0; x[3] = 3; x.pop(); x.length == 3'); } -//CHECK#7 if (x[3] !== undefined) { throw new Test262Error('#7: x = []; x[0] = 0; x[3] = 3; x.pop(); x[3] == undefined'); } -//CHECK#8 if (x[2] !== undefined) { throw new Test262Error('#8: x = []; x[0] = 0; x[3] = 3; x.pop(); x[2] == undefined'); } -//CHECK#9 x.length = 1; var pop = x.pop(); if (pop !== 0) { throw new Test262Error('#9: x = []; x[0] = 0; x[3] = 3; x.pop(); x.length = 1; x.pop() === 0. Actual: ' + (pop)); } -//CHECK#10 if (x.length !== 0) { throw new Test262Error('#10: x = []; x[0] = 0; x[3] = 3; x.pop(); x.length = 1; x.pop(); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T1.js index 1cb46ad88a9d..9961c4733aa5 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T1.js @@ -17,37 +17,31 @@ obj.pop = Array.prototype.pop; if (obj.length !== undefined) { throw new Test262Error('#0: var obj = {}; obj.length === undefined. Actual: ' + (obj.length)); } else { - //CHECK#1 var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#1: var obj = {}; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } - //CHECK#2 if (obj.length !== 0) { throw new Test262Error('#2: var obj = {}; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } } -//CHECK#3 obj.length = undefined; var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#3: var obj = {}; obj.length = undefined; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#4 if (obj.length !== 0) { throw new Test262Error('#4: var obj = {}; obj.length = undefined; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#5 obj.length = null var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#5: var obj = {}; obj.length = null; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#6 if (obj.length !== 0) { throw new Test262Error('#6: var obj = {}; obj.length = null; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T2.js index cb76715a4aeb..f414f4d00a3b 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T2.js @@ -14,50 +14,42 @@ description: > var obj = {}; obj.pop = Array.prototype.pop; -//CHECK#1 obj.length = NaN; var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#1: var obj = {}; obj.length = NaN; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#2 if (obj.length !== 0) { throw new Test262Error('#2: var obj = {}; obj.length = NaN; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#3 obj.length = Number.POSITIVE_INFINITY; var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#3: var obj = {}; obj.length = Number.POSITIVE_INFINITY; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#4 if (obj.length !== 9007199254740990) { throw new Test262Error('#4: var obj = {}; obj.length = Number.POSITIVE_INFINITY; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 9007199254740990. Actual: ' + (obj.length)); } -//CHECK#5 obj.length = Number.NEGATIVE_INFINITY; var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#5: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#6 if (obj.length !== 0) { throw new Test262Error('#6: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#7 obj.length = -0; var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#7: var obj = {}; obj.length = -0; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#8 if (obj.length !== 0) { throw new Test262Error('#8: var obj = {}; obj.length = -0; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } else { @@ -66,26 +58,22 @@ if (obj.length !== 0) { } } -//CHECK#9 obj.length = 0.5; var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#9: var obj = {}; obj.length = 0.5; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#10 if (obj.length !== 0) { throw new Test262Error('#10: var obj = {}; obj.length = 0.5; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#11 obj.length = new Number(0); var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#11: var obj = {}; obj.length = new Number(0); obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#12 if (obj.length !== 0) { throw new Test262Error('#12: var obj = {}; obj.length = new Number(0); obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T3.js index d951fb1c370d..74df6b350086 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T3.js @@ -14,26 +14,22 @@ description: > var obj = {}; obj.pop = Array.prototype.pop; -//CHECK#1 obj.length = 2.5; var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#1: var obj = {}; obj.length = 2.5; obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#2 if (obj.length !== 1) { throw new Test262Error('#2: var obj = {}; obj.length = 2.5; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#3 obj.length = new Number(2); var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#11: var obj = {}; obj.length = new Number(2); obj.pop = Array.prototype.pop; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#3 if (obj.length !== 1) { throw new Test262Error('#12: var obj = {}; obj.length = new Number(2); obj.pop = Array.prototype.pop; obj.pop(); obj.length === 1. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T4.js index 7246c6deabd1..d37f8024d556 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A2_T4.js @@ -14,137 +14,113 @@ description: > var obj = {}; obj.pop = Array.prototype.pop; -//CHECK#1 obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return 1 } }; var pop = obj.pop(); -if (pop !== -1) { - throw new Test262Error('#1: obj[0] = -1; obj.length = {valueOf: function() {return 1}} obj.pop() === -1. Actual: ' + (pop)); -} +assert.sameValue(pop, -1, 'The value of pop is expected to be -1'); -//CHECK#2 obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return 1 }, - toString: function() { + toString() { return 0 } }; var pop = obj.pop(); -if (pop !== -1) { - throw new Test262Error('#0: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {return 0}} obj.pop() === -1. Actual: ' + (pop)); -} +assert.sameValue(pop, -1, 'The value of pop is expected to be -1'); -//CHECK#3 obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return 1 }, - toString: function() { + toString() { return {} } }; var pop = obj.pop(); -if (pop !== -1) { - throw new Test262Error('#3: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {return {}}} obj.pop() === -1. Actual: ' + (pop)); -} +assert.sameValue(pop, -1, 'The value of pop is expected to be -1'); -//CHECK#4 try { obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return 1 }, - toString: function() { + toString() { throw "error" } }; var pop = obj.pop(); - if (pop !== -1) { - throw new Test262Error('#4.1: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {throw "error"}}; obj.pop() === ",". Actual: ' + (pop)); - } + assert.sameValue(pop, -1, 'The value of pop is expected to be -1'); } catch (e) { - if (e === "error") { - throw new Test262Error('#4.2: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {throw "error"}}; obj.pop() not throw "error"'); - } else { - throw new Test262Error('#4.3: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {throw "error"}}; obj.pop() not throw Error. Actual: ' + (e)); - } + assert.notSameValue(e, "error", 'The value of e is not "error"'); } -//CHECK#5 obj[0] = -1; obj.length = { - toString: function() { + toString() { return 0 } }; var pop = obj.pop(); -if (pop !== undefined) { - throw new Test262Error('#5: obj[0] = -1; obj.length = {toString: function() {return 0}} obj.pop() === undefined. Actual: ' + (pop)); -} +assert.sameValue(pop, undefined, 'The value of pop is expected to equal undefined'); -//CHECK#6 obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return 0 } } var pop = obj.pop(); -if (pop !== undefined) { - throw new Test262Error('#6: obj[0] = -1; obj.length = {valueOf: function() {return {}}, toString: function() {return 0}} obj.pop() === undefined. Actual: ' + (pop)); -} +assert.sameValue(pop, undefined, 'The value of pop is expected to equal undefined'); -//CHECK#7 try { obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { throw "error" }, - toString: function() { + toString() { return 0 } }; var pop = obj.pop(); - throw new Test262Error('#7.1: obj[0] = -1; obj.length = {valueOf: function() {throw "error"}, toString: function() {return 0}}; obj.pop() throw "error". Actual: ' + (pop)); + throw new Test262Error('#7.1: obj[0] = -1; obj.length = {valueOf() {throw "error"}, toString() {return 0}}; obj.pop() throw "error". Actual: ' + (pop)); } catch (e) { - if (e !== "error") { - throw new Test262Error('#7.2: obj[0] = -1; obj.length = {valueOf: function() {throw "error"}, toString: function() {return 0}}; obj.pop() throw "error". Actual: ' + (e)); - } + assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } -//CHECK#8 try { obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return {} } }; var pop = obj.pop(); - throw new Test262Error('#8.1: obj[0] = -1; obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.pop() throw TypeError. Actual: ' + (pop)); + throw new Test262Error('#8.1: obj[0] = -1; obj.length = {valueOf() {return {}}, toString() {return {}}} obj.pop() throw TypeError. Actual: ' + (pop)); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#8.2: obj[0] = -1; obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.pop() throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T1.js index 36c54d8029e5..7c0ce497dcec 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T1.js @@ -13,23 +13,19 @@ obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; -//CHECK#1 var pop = obj.pop(); if (pop !== "y") { throw new Test262Error('#1: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; obj.pop() === "y". Actual: ' + (pop)); } -//CHECK#2 if (obj.length !== 4294967295) { throw new Test262Error('#2: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; obj.pop(); obj.length === 4294967295. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== "x") { throw new Test262Error('#3: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; obj.pop(); obj[0] === "x". Actual: ' + (obj[0])); } -//CHECK#4 if (obj[4294967295] !== undefined) { throw new Test262Error('#4: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; obj.pop(); obj[4294967295] === undefined. Actual: ' + (obj[4294967295])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T2.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T2.js index a31205e8ba86..b6de632743a9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T2.js @@ -13,23 +13,19 @@ obj[0] = "x"; obj[4294967296] = "y"; obj.length = 4294967297; -//CHECK#1 var pop = obj.pop(); if (pop !== "y") { throw new Test262Error('#1: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967296] = "y"; obj.length = 4294967297; obj.pop() === "y". Actual: ' + (pop)); } -//CHECK#2 if (obj.length !== 4294967296) { throw new Test262Error('#2: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967296] = "y"; obj.length = 4294967297; obj.pop(); obj.length === 4294967296. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== "x") { throw new Test262Error('#3: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967296] = "y"; obj.length = 4294967297; obj.pop(); obj[0] === "x". Actual: ' + (obj[0])); } -//CHECK#4 if (obj[4294967296] !== undefined) { throw new Test262Error('#4: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967296] = "y"; obj.length = 4294967297; obj.pop(); obj[4294967296] === undefined. Actual: ' + (obj[4294967296])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T3.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T3.js index 3c9b8a447e8f..7086832284f1 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A3_T3.js @@ -12,18 +12,15 @@ obj.pop = Array.prototype.pop; obj[4294967294] = "x"; obj.length = -1; -//CHECK#1 var pop = obj.pop(); if (pop !== undefined) { throw new Test262Error('#1: var obj = {}; obj.pop = Array.prototype.pop; obj[4294967294] = "x"; obj.length = -1; obj.pop() === undefined. Actual: ' + (pop)); } -//CHECK#2 if (obj.length !== 0) { throw new Test262Error('#2: var obj = {}; obj.pop = Array.prototype.pop; obj[4294967294] = "x"; obj.length = -1; obj.pop(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[4294967294] !== "x") { throw new Test262Error('#3: var obj = {}; obj.pop = Array.prototype.pop; obj[4294967294] = "x"; obj.length = -1; obj.pop(); obj[4294967294] === "x". Actual: ' + (obj[4294967294])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A4_T1.js index efb27c8429dd..454bd58b985e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A4_T1.js @@ -13,13 +13,11 @@ Array.prototype[1] = 1; var x = [0]; x.length = 2; -//CHECK#1 var pop = x.pop(); if (pop !== 1) { throw new Test262Error('#1: Array.prototype[1] = 1; x = [0]; x.length = 2; x.pop() === 1. Actual: ' + (pop)); } -//CHECK#2 if (x[1] !== 1) { throw new Test262Error('#2: Array.prototype[1] = 1; x = [0]; x.length = 2; x.pop(); x[1] === 1. Actual: ' + (x[1])); } @@ -31,23 +29,19 @@ x = { 0: 0 }; -//CHECK#3 var pop = x.pop(); if (pop !== 1) { throw new Test262Error('#3: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.pop = Array.prototype.pop; x = {0:0}; x.pop() === 1. Actual: ' + (pop)); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.pop = Array.prototype.pop; x = {0:0}; x.pop(); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.pop = Array.prototype.pop; x = {0:0}; x.pop(); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 delete x.length; if (x.length !== 2) { throw new Test262Error('#7: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.pop = Array.prototype.pop; x = {0:0}; x.pop(); delete x; x.length === 2. Actual: ' + (x.length)); diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A4_T2.js index 394d32dc2701..51ed4692cfd9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A4_T2.js @@ -13,13 +13,11 @@ Array.prototype[1] = -1; var x = [0, 1]; x.length = 2; -//CHECK#1 var pop = x.pop(); if (pop !== 1) { throw new Test262Error('#1: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.pop() === 1. Actual: ' + (pop)); } -//CHECK#2 if (x[1] !== -1) { throw new Test262Error('#2: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.pop(); x[1] === -1. Actual: ' + (x[1])); } @@ -32,23 +30,19 @@ x = { 1: 1 }; -//CHECK#3 var pop = x.pop(); if (pop !== 1) { throw new Test262Error('#3: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.pop = Array.prototype.pop; x = {0:0,1:1}; x.pop() === 1. Actual: ' + (pop)); } -//CHECK#4 if (x[1] !== -1) { throw new Test262Error('#4: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.pop = Array.prototype.pop; x = {0:0,1:1}; x.pop(); x[1] === -1. Actual: ' + (x[1])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.pop = Array.prototype.pop; x = {0:0,1:1}; x.pop(); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 delete x.length; if (x.length !== 2) { throw new Test262Error('#7: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.pop = Array.prototype.pop; x = {0:0,1:1}; x.pop(); delete x; x.length === 2. Actual: ' + (x.length)); diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A5.7.js b/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A5.7.js deleted file mode 100644 index f9b473bd95e7..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/pop/S15.4.4.6_A5.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The pop property of Array can't be used as constructor -esid: sec-array.prototype.pop -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.pop(); - throw new Test262Error('#1.1: new Array.prototype.pop() throw TypeError. Actual: ' + (new Array.prototype.pop())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.pop() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-array-is-frozen.js b/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-array-is-frozen.js new file mode 100644 index 000000000000..d083e0eb196a --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-array-is-frozen.js @@ -0,0 +1,49 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.pop +description: > + A TypeError is thrown when "length" is [[Set]] on a frozen array. +info: | + Array.prototype.pop ( ) + + [...] + 4. Else, + a. Assert: len > 0. + b. Let newLen be 𝔽(len - 1). + c. Let index be ! ToString(newLen). + d. Let element be ? Get(O, index). + e. Perform ? DeletePropertyOrThrow(O, index). + f. Perform ? Set(O, "length", newLen, true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = new Array(1); +var arrayPrototypeGet0Calls = 0; + +Object.defineProperty(Array.prototype, "0", { + get() { + Object.freeze(array); + arrayPrototypeGet0Calls++; + }, +}); + +assert.throws(TypeError, function() { + array.pop(); +}); + +assert.sameValue(array.length, 1); +assert.sameValue(arrayPrototypeGet0Calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-array-length-is-non-writable.js b/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-array-length-is-non-writable.js new file mode 100644 index 000000000000..b53a73d8675a --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-array-length-is-non-writable.js @@ -0,0 +1,49 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.pop +description: > + A TypeError is thrown when "length" is [[Set]] on an array with non-writable "length". +info: | + Array.prototype.pop ( ) + + [...] + 4. Else, + a. Assert: len > 0. + b. Let newLen be 𝔽(len - 1). + c. Let index be ! ToString(newLen). + d. Let element be ? Get(O, index). + e. Perform ? DeletePropertyOrThrow(O, index). + f. Perform ? Set(O, "length", newLen, true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = new Array(1); +var arrayPrototypeGet0Calls = 0; + +Object.defineProperty(Array.prototype, "0", { + get() { + Object.defineProperty(array, "length", { writable: false }); + arrayPrototypeGet0Calls++; + }, +}); + +assert.throws(TypeError, function() { + array.pop(); +}); + +assert.sameValue(array.length, 1); +assert.sameValue(arrayPrototypeGet0Calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-zero-array-is-frozen.js b/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-zero-array-is-frozen.js new file mode 100644 index 000000000000..a4fc0439594f --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-zero-array-is-frozen.js @@ -0,0 +1,34 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.pop +description: > + A TypeError is thrown when "length" is [[Set]] on an empty frozen array. +info: | + Array.prototype.pop ( ) + + [...] + 3. If len = 0, then + a. Perform ? Set(O, "length", +0𝔽, true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +Object.freeze(array); + +assert.throws(TypeError, function() { + array.pop(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-zero-array-length-is-non-writable.js b/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-zero-array-length-is-non-writable.js new file mode 100644 index 000000000000..36664bc4953a --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/pop/set-length-zero-array-length-is-non-writable.js @@ -0,0 +1,34 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.pop +description: > + A TypeError is thrown when "length" is [[Set]] on an empty array with non-writable "length". +info: | + Array.prototype.pop ( ) + + [...] + 3. If len = 0, then + a. Perform ? Set(O, "length", +0𝔽, true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +Object.defineProperty(array, "length", { writable: false }); + +assert.throws(TypeError, function() { + array.pop(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A1_T1.js index 6c47336b1f32..e8b82b1e156e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A1_T1.js @@ -10,41 +10,34 @@ esid: sec-array.prototype.push description: Checking case when push is given no arguments or one argument ---*/ -//CHECK#1 var x = new Array(); var push = x.push(1); if (push !== 1) { throw new Test262Error('#1: x = new Array(); x.push(1) === 1. Actual: ' + (push)); } -//CHECK#2 if (x[0] !== 1) { throw new Test262Error('#2: x = new Array(); x.push(1); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#3 var push = x.push(); if (push !== 1) { throw new Test262Error('#3: x = new Array(); x.push(1); x.push() === 1. Actual: ' + (push)); } -//CHECK#4 if (x[1] !== undefined) { throw new Test262Error('#4: x = new Array(); x.push(1); x.push(); x[1] === unedfined. Actual: ' + (x[1])); } -//CHECK#5 var push = x.push(-1); if (push !== 2) { throw new Test262Error('#5: x = new Array(); x.push(1); x.push(); x.push(-1) === 2. Actual: ' + (push)); } -//CHECK#6 if (x[1] !== -1) { throw new Test262Error('#6: x = new Array(); x.push(1); x.push(-1); x[1] === -1. Actual: ' + (x[1])); } -//CHECK#7 if (x.length !== 2) { throw new Test262Error('#7: x = new Array(); x.push(1); x.push(); x.push(-1); x.length === 2. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A1_T2.js index c3c07c52ecc5..602b34e1b807 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A1_T2.js @@ -10,50 +10,41 @@ esid: sec-array.prototype.push description: Checking case when push is given many arguments ---*/ -//CHECK#1 var x = []; if (x.length !== 0) { throw new Test262Error('#1: x = []; x.length === 0. Actual: ' + (x.length)); } -//CHECK#2 x[0] = 0; var push = x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); if (push !== 6) { throw new Test262Error('#2: x = []; x[0] = 0; x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1) === 6. Actual: ' + (push)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: x = []; x[0] = 0; x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== true) { throw new Test262Error('#4: x = []; x[0] = 0; x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[1] === true. Actual: ' + (x[1])); } -//CHECK#5 if (x[2] !== Number.POSITIVE_INFINITY) { throw new Test262Error('#5: x = []; x[0] = 0; x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[2] === Number.POSITIVE_INFINITY. Actual: ' + (x[2])); } -//CHECK#6 if (x[3] !== "NaN") { throw new Test262Error('#6: x = []; x[0] = 0; x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[3] === "NaN". Actual: ' + (x[3])); } -//CHECK#7 if (x[4] !== "1") { throw new Test262Error('#7: x = []; x[0] = 0; x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[4] === "1". Actual: ' + (x[4])); } -//CHECK#8 if (x[5] !== -1) { throw new Test262Error('#8: x = []; x[0] = 0; x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[5] === -1. Actual: ' + (x[5])); } -//CHECK#9 if (x.length !== 6) { throw new Test262Error('#9: x = []; x[0] = 0; x.push(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x.length === 6. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T1.js index e1ac52d62f28..2e5e878a9211 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T1.js @@ -18,51 +18,42 @@ obj.push = Array.prototype.push; if (obj.length !== undefined) { throw new Test262Error('#0: var obj = {}; obj.length === undefined. Actual: ' + (obj.length)); } else { - //CHECK#1 var push = obj.push(-1); if (push !== 1) { throw new Test262Error('#1: var obj = {}; obj.push = Array.prototype.push; obj.push(-1) === 1. Actual: ' + (push)); } - //CHECK#2 if (obj.length !== 1) { throw new Test262Error('#2: var obj = {}; obj.push = Array.prototype.push; obj.push(-1); obj.length === 1. Actual: ' + (obj.length)); } - //CHECK#3 if (obj["0"] !== -1) { throw new Test262Error('#3: var obj = {}; obj.push = Array.prototype.push; obj.push(-1); obj["0"] === -1. Actual: ' + (obj["0"])); } } -//CHECK#4 obj.length = undefined; var push = obj.push(-4); if (push !== 1) { throw new Test262Error('#4: var obj = {}; obj.length = undefined; obj.push = Array.prototype.push; obj.push(-4) === 1. Actual: ' + (push)); } -//CHECK#5 if (obj.length !== 1) { throw new Test262Error('#5: var obj = {}; obj.length = undefined; obj.push = Array.prototype.push; obj.push(-4); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#6 if (obj["0"] !== -4) { throw new Test262Error('#6: var obj = {}; obj.length = undefined; obj.push = Array.prototype.push; obj.push(-4); obj["0"] === -4. Actual: ' + (obj["0"])); } -//CHECK#7 obj.length = null var push = obj.push(-7); if (push !== 1) { throw new Test262Error('#7: var obj = {}; obj.length = null; obj.push = Array.prototype.push; obj.push(-7) === 1. Actual: ' + (push)); } -//CHECK#8 if (obj.length !== 1) { throw new Test262Error('#8: var obj = {}; obj.length = null; obj.push = Array.prototype.push; obj.push(-7); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#9 if (obj["0"] !== -7) { throw new Test262Error('#9: var obj = {}; obj.length = null; obj.push = Array.prototype.push; obj.push(-7); obj["0"] === -7. Actual: ' + (obj["0"])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T2.js index 1001c146c665..2e35207c020e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T2.js @@ -15,103 +15,85 @@ description: > var obj = {}; obj.push = Array.prototype.push; -//CHECK#1 obj.length = NaN; var push = obj.push(-1); if (push !== 1) { throw new Test262Error('#1: var obj = {}; obj.length = NaN; obj.push = Array.prototype.push; obj.push(-1) === 1. Actual: ' + (push)); } -//CHECK#2 if (obj.length !== 1) { throw new Test262Error('#2: var obj = {}; obj.length = NaN; obj.push = Array.prototype.push; obj.push(-1); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#3 if (obj["0"] !== -1) { throw new Test262Error('#3: var obj = {}; obj.length = NaN; obj.push = Array.prototype.push; obj.push(-1); obj["0"] === -1. Actual: ' + (obj["0"])); } -//CHECK#4 obj.length = Number.POSITIVE_INFINITY; assert.throws(TypeError, function() { obj.push(-4); }); -//CHECK#5 if (obj.length !== Number.POSITIVE_INFINITY) { throw new Test262Error('#6: var obj = {}; obj.length = Number.POSITIVE_INFINITY; obj.push = Array.prototype.push; obj.push(-4); obj.length === Number.POSITIVE_INFINITY. Actual: ' + (obj.length)); } -//CHECK#6 if (obj[9007199254740991] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.length = Number.POSITIVE_INFINITY; obj.push = Array.prototype.push; obj.push(-4); obj[9007199254740991] === undefined. Actual: ' + (obj["9007199254740991"])); } -//CHECK#7 obj.length = Number.NEGATIVE_INFINITY; var push = obj.push(-7); if (push !== 1) { throw new Test262Error('#7: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.push = Array.prototype.push; obj.push(-7) === 1. Actual: ' + (push)); } -//CHECK#8 if (obj.length !== 1) { throw new Test262Error('#8: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.push = Array.prototype.push; obj.push(-7); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#9 if (obj["0"] !== -7) { throw new Test262Error('#9: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.push = Array.prototype.push; obj.push(-7); obj["0"] === -7. Actual: ' + (obj["0"])); } -//CHECK#10 obj.length = 0.5; var push = obj.push(-10); if (push !== 1) { throw new Test262Error('#10: var obj = {}; obj.length = 0.5; obj.push = Array.prototype.push; obj.push(-10) === 1. Actual: ' + (push)); } -//CHECK#11 if (obj.length !== 1) { throw new Test262Error('#11: var obj = {}; obj.length = 0.5; obj.push = Array.prototype.push; obj.push(-10); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#12 if (obj["0"] !== -10) { throw new Test262Error('#12: var obj = {}; obj.length = 0.5; obj.push = Array.prototype.push; obj.push(-10); obj["0"] === -10. Actual: ' + (obj["0"])); } -//CHECK#13 obj.length = 1.5; var push = obj.push(-13); if (push !== 2) { throw new Test262Error('#13: var obj = {}; obj.length = 1.5; obj.push = Array.prototype.push; obj.push(-13) === 2. Actual: ' + (push)); } -//CHECK#14 if (obj.length !== 2) { throw new Test262Error('#14: var obj = {}; obj.length = 1.5; obj.push = Array.prototype.push; obj.push(-13); obj.length === 2. Actual: ' + (obj.length)); } -//CHECK#15 if (obj["1"] !== -13) { throw new Test262Error('#15: var obj = {}; obj.length = 1.5; obj.push = Array.prototype.push; obj.push(-13); obj["1"] === -13. Actual: ' + (obj["1"])); } -//CHECK#16 obj.length = new Number(0); var push = obj.push(-16); if (push !== 1) { throw new Test262Error('#16: var obj = {}; obj.length = new Number(0); obj.push = Array.prototype.push; obj.push(-16) === 1. Actual: ' + (push)); } -//CHECK#17 if (obj.length !== 1) { throw new Test262Error('#17: var obj = {}; obj.length = new Number(0); obj.push = Array.prototype.push; obj.push(-16); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#18 if (obj["0"] !== -16) { throw new Test262Error('#18: var obj = {}; obj.length = new Number(0); obj.push = Array.prototype.push; obj.push(-16); obj["0"] === -16. Actual: ' + (obj["0"])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T3.js index 413de01e84dd..cec90447f009 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A2_T3.js @@ -14,132 +14,107 @@ description: > var obj = {}; obj.push = Array.prototype.push; -//CHECK#1 obj.length = { - valueOf: function() { + valueOf() { return 3 } }; var push = obj.push(); -if (push !== 3) { - throw new Test262Error('#1: obj.length = {valueOf: function() {return 3}} obj.push() === 3. Actual: ' + (push)); -} +assert.sameValue(push, 3, 'The value of push is expected to be 3'); -//CHECK#2 obj.length = { - valueOf: function() { + valueOf() { return 3 }, - toString: function() { + toString() { return 1 } }; var push = obj.push(); -if (push !== 3) { - throw new Test262Error('#0: obj.length = {valueOf: function() {return 3}, toString: function() {return 1}} obj.push() === 3. Actual: ' + (push)); -} +assert.sameValue(push, 3, 'The value of push is expected to be 3'); -//CHECK#3 obj.length = { - valueOf: function() { + valueOf() { return 3 }, - toString: function() { + toString() { return {} } }; var push = obj.push(); -if (push !== 3) { - throw new Test262Error('#1: obj.length = {valueOf: function() {return 3}, toString: function() {return {}}} obj.push() === 3. Actual: ' + (push)); -} +assert.sameValue(push, 3, 'The value of push is expected to be 3'); -//CHECK#4 try { - obj.length = { - valueOf: function() { + valueOf() { return 3 }, - toString: function() { + toString() { throw "error" } }; var push = obj.push(); - if (push !== 3) { - throw new Test262Error('#4.1: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.push() === ",". Actual: ' + (push)); - } + assert.sameValue(push, 3, 'The value of push is expected to be 3'); } catch (e) { - if (e === "error") { - throw new Test262Error('#4.2: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.push() not throw "error"'); - } else { - throw new Test262Error('#4.3: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.push() not throw Error. Actual: ' + (e)); - } + assert.notSameValue(e, "error", 'The value of e is not "error"'); } -//CHECK#5 obj.length = { - toString: function() { + toString() { return 1 } }; var push = obj.push(); -if (push !== 1) { - throw new Test262Error('#5: obj.length = {toString: function() {return 1}} obj.push() === 1. Actual: ' + (push)); -} +assert.sameValue(push, 1, 'The value of push is expected to be 1'); -//CHECK#6 obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return 1 } } var push = obj.push(); -if (push !== 1) { - throw new Test262Error('#6: obj.length = {valueOf: function() {return {}}, toString: function() {return 1}} obj.push() === 1. Actual: ' + (push)); -} +assert.sameValue(push, 1, 'The value of push is expected to be 1'); -//CHECK#7 try { obj.length = { - valueOf: function() { + valueOf() { throw "error" }, - toString: function() { + toString() { return 1 } }; var push = obj.push(); - throw new Test262Error('#7.1: obj.length = {valueOf: function() {throw "error"}, toString: function() {return 1}}; obj.push() throw "error". Actual: ' + (push)); + throw new Test262Error('#7.1: obj.length = {valueOf() {throw "error"}, toString() {return 1}}; obj.push() throw "error". Actual: ' + (push)); } catch (e) { - if (e !== "error") { - throw new Test262Error('#7.2: obj.length = {valueOf: function() {throw "error"}, toString: function() {return 1}}; obj.push() throw "error". Actual: ' + (e)); - } + assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } -//CHECK#8 try { obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return {} } }; var push = obj.push(); - throw new Test262Error('#8.1: obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.push() throw TypeError. Actual: ' + (push)); + throw new Test262Error('#8.1: obj.length = {valueOf() {return {}}, toString() {return {}}} obj.push() throw TypeError. Actual: ' + (push)); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#8.2: obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.push() throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A3.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A3.js index 4cfbfb0debcf..cd918e018034 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A3.js @@ -10,30 +10,21 @@ description: If ToUint32(length) !== length, throw RangeError var x = []; x.length = 4294967295; -//CHECK#1 var push = x.push(); -if (push !== 4294967295) { - throw new Test262Error('#1: x = []; x.length = 4294967295; x.push() === 4294967295. Actual: ' + (push)); -} +assert.sameValue(push, 4294967295, 'The value of push is expected to be 4294967295'); -//CHECK#2 try { x.push("x"); throw new Test262Error('#2.1: x = []; x.length = 4294967295; x.push("x") throw RangeError. Actual: ' + (push)); } catch (e) { - if ((e instanceof RangeError) !== true) { - throw new Test262Error('#2.2: x = []; x.length = 4294967295; x.push("x") throw RangeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof RangeError, + true, + 'The result of evaluating (e instanceof RangeError) is expected to be true' + ); } -//CHECK#3 -if (x[4294967295] !== "x") { - throw new Test262Error('#3: x = []; x.length = 4294967295; try {x.push("x")}catch(e){}; x[4294967295] === "x". Actual: ' + (x[4294967295])); -} - -//CHECK#4 -if (x.length !== 4294967295) { - throw new Test262Error('#4: x = []; x.length = 4294967295; try {x.push("x")}catch(e){}; x.length === 4294967295. Actual: ' + (x.length)); -} +assert.sameValue(x[4294967295], "x", 'The value of x[4294967295] is expected to be "x"'); +assert.sameValue(x.length, 4294967295, 'The value of x.length is expected to be 4294967295'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T1.js index 09fd1adf351a..4561b952fb23 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T1.js @@ -11,43 +11,35 @@ var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; -//CHECK#1 var push = obj.push("x", "y", "z"); if (push !== 4294967299) { throw new Test262Error('#1: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push("x", "y", "z") === 4294967299. Actual: ' + (push)); } -//CHECK#2 if (obj.length !== 4294967299) { throw new Test262Error('#2: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push("x", "y", "z"); obj.length === 4294967299. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== undefined) { throw new Test262Error('#3: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push("x", "y", "z"); obj[0] === undefined. Actual: ' + (obj[0])); } -//CHECK#4 if (obj[1] !== undefined) { throw new Test262Error('#4: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push("x", "y", "z"); obj[1] === undefined. Actual: ' + (obj[1])); } -//CHECK#5 if (obj[2] !== undefined) { throw new Test262Error('#5: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push("x", "y", "z"); obj[2] === undefined. Actual: ' + (obj[2])); } -//CHECK#6 if (obj[4294967296] !== "x") { throw new Test262Error('#6: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push("x", "y", "z"); obj[4294967296] === "x". Actual: ' + (obj[4294967296])); } -//CHECK#7 if (obj[4294967297] !== "y") { throw new Test262Error('#7: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push("x", "y", "z"); obj[4294967297] === "y". Actual: ' + (obj[4294967297])); } -//CHECK#8 if (obj[4294967298] !== "z") { throw new Test262Error('#8: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push("x", "y", "z"); obj[4294967298] === "z". Actual: ' + (obj[4294967298])); } @@ -56,13 +48,11 @@ var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; -//CHECK#9 var push = obj.push(); if (push !== 4294967296) { throw new Test262Error('#9: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push() === 4294967296. Actual: ' + (push)); } -//CHECK#10 if (obj.length !== 4294967296) { throw new Test262Error('#10: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967296; obj.push(); obj.length === 4294967296. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T2.js index 8e9b20968416..4beecec82a50 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T2.js @@ -11,28 +11,23 @@ var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967295; -//CHECK#1 var push = obj.push("x", "y", "z"); if (push !== 4294967298) { throw new Test262Error('#1: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967295; obj.push("x", "y", "z") === 4294967298. Actual: ' + (push)); } -//CHECK#2 if (obj.length !== 4294967298) { throw new Test262Error('#2: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967295; obj.push("x", "y", "z"); obj.length === 4294967298. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[4294967295] !== "x") { throw new Test262Error('#3: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967295; obj.push("x", "y", "z"); obj[4294967295] === "x". Actual: ' + (obj[4294967295])); } -//CHECK#4 if (obj[4294967296] !== "y") { throw new Test262Error('#4: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967295; obj.push("x", "y", "z"); obj[4294967296] === "y". Actual: ' + (obj[4294967296])); } -//CHECK#5 if (obj[4294967297] !== "z") { throw new Test262Error('#5: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967295; obj.push("x", "y", "z"); obj[4294967297] === "z". Actual: ' + (obj[4294967297])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T3.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T3.js index 943ac158e5fa..54fd4df676e7 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A4_T3.js @@ -11,43 +11,35 @@ var obj = {}; obj.push = Array.prototype.push; obj.length = -1; -//CHECK#1 var push = obj.push("x", "y", "z"); if (push !== 3) { throw new Test262Error('#1: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z") === 3. Actual: ' + (push)); } -//CHECK#2 if (obj.length !== 3) { throw new Test262Error('#2: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z"); obj.length === 3. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[4294967295] !== undefined) { throw new Test262Error('#3: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z"); obj[4294967295] === undefined. Actual: ' + (obj[4294967295])); } -//CHECK#4 if (obj[4294967296] !== undefined) { throw new Test262Error('#4: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z"); obj[4294967296] === undefined. Actual: ' + (obj[4294967296])); } -//CHECK#5 if (obj[4294967297] !== undefined) { throw new Test262Error('#5: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z"); obj[4294967297] === undefined. Actual: ' + (obj[4294967297])); } -//CHECK#6 if (obj[0] !== "x") { throw new Test262Error('#3: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z"); obj[0] === "x". Actual: ' + (obj[0])); } -//CHECK#7 if (obj[1] !== "y") { throw new Test262Error('#4: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z"); obj[1] === "y". Actual: ' + (obj[1])); } -//CHECK#8 if (obj[2] !== "z") { throw new Test262Error('#5: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z"); obj[2] === "z". Actual: ' + (obj[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A5_T1.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A5_T1.js index 57f221a6fcea..d124babebf3f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A5_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A5_T1.js @@ -16,29 +16,24 @@ var x = { 0: 0 }; -//CHECK#1 var push = x.push(1); if (push !== 2) { throw new Test262Error('#1: Object.prototype[1] = 1; Object.prototype.length = -1; Object.prototype.push = Array.prototype.push; x = {0:0}; x.push(1) === 2. Actual: ' + (push)); } -//CHECK#2 if (x.length !== 2) { throw new Test262Error('#2: Object.prototype[1] = 1; Object.prototype.length = -1; Object.prototype.push = Array.prototype.push; x = {0:0}; x.push(1); x.length === 2. Actual: ' + (x.length)); } -//CHECK#3 if (x[1] !== 1) { throw new Test262Error('#3: Object.prototype[1] = 1; Object.prototype.length = -1; Object.prototype.push = Array.prototype.push; x = {0:0}; x.push(1); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#4 delete x[1]; if (x[1] !== -1) { throw new Test262Error('#4: Object.prototype[1] = 1; Object.prototype.length = -1; Object.prototype.push = Array.prototype.push; x = {0:0}; x.push(1); delete x[1]; x[1] === -1. Actual: ' + (x[1])); } -//CHECK#5 delete x.length; if (x.length !== 1) { throw new Test262Error('#5: Object.prototype[1] = 1; Object.prototype.length = -1; Object.prototype.push = Array.prototype.push; x = {0:0}; delete x; x.push(1); x.length === 1. Actual: ' + (x.length)); diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A6.7.js b/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A6.7.js deleted file mode 100644 index 6b5c8a659d5c..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/push/S15.4.4.7_A6.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The push property of Array can't be used as constructor -esid: sec-array.prototype.push -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.push(); - throw new Test262Error('#1.1: new Array.prototype.push() throw TypeError. Actual: ' + (new Array.prototype.push())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.push() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/set-length-array-is-frozen.js b/js/src/tests/test262/built-ins/Array/prototype/push/set-length-array-is-frozen.js new file mode 100644 index 000000000000..09aa72f52fb6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/push/set-length-array-is-frozen.js @@ -0,0 +1,47 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.push +description: > + A TypeError is thrown when "length" is [[Set]] on a frozen array. +info: | + Array.prototype.push ( ...items ) + + [...] + 5. For each element E of items, do + a. Perform ? Set(O, ! ToString(𝔽(len)), E, true). + b. Set len to len + 1. + 6. Perform ? Set(O, "length", 𝔽(len), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +var arrayPrototypeSet0Calls = 0; + +Object.defineProperty(Array.prototype, "0", { + set(_val) { + Object.freeze(array); + arrayPrototypeSet0Calls++; + }, +}); + +assert.throws(TypeError, function() { + array.push(1); +}); + +assert(!array.hasOwnProperty(0)); +assert.sameValue(array.length, 0); +assert.sameValue(arrayPrototypeSet0Calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/set-length-array-length-is-non-writable.js b/js/src/tests/test262/built-ins/Array/prototype/push/set-length-array-length-is-non-writable.js new file mode 100644 index 000000000000..4e8ba1d82138 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/push/set-length-array-length-is-non-writable.js @@ -0,0 +1,47 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.push +description: > + A TypeError is thrown when "length" is [[Set]] on an array with non-writable "length". +info: | + Array.prototype.push ( ...items ) + + [...] + 5. For each element E of items, do + a. Perform ? Set(O, ! ToString(𝔽(len)), E, true). + b. Set len to len + 1. + 6. Perform ? Set(O, "length", 𝔽(len), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +var arrayPrototypeSet0Calls = 0; + +Object.defineProperty(Array.prototype, "0", { + set(_val) { + Object.defineProperty(array, "length", { writable: false }); + arrayPrototypeSet0Calls++; + }, +}); + +assert.throws(TypeError, function() { + array.push(1); +}); + +assert(!array.hasOwnProperty(0)); +assert.sameValue(array.length, 0); +assert.sameValue(arrayPrototypeSet0Calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/set-length-zero-array-is-frozen.js b/js/src/tests/test262/built-ins/Array/prototype/push/set-length-zero-array-is-frozen.js new file mode 100644 index 000000000000..a2bb89fa1fb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/push/set-length-zero-array-is-frozen.js @@ -0,0 +1,38 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.push +description: > + A TypeError is thrown when "length" is [[Set]] on an empty frozen array. +info: | + Array.prototype.push ( ...items ) + + [...] + 2. Let len be ? LengthOfArrayLike(O). + [...] + 6. Perform ? Set(O, "length", 𝔽(len), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +Object.freeze(array); + +assert.throws(TypeError, function() { + array.push(); +}); + +assert(!array.hasOwnProperty(0)); +assert.sameValue(array.length, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/push/set-length-zero-array-length-is-non-writable.js b/js/src/tests/test262/built-ins/Array/prototype/push/set-length-zero-array-length-is-non-writable.js new file mode 100644 index 000000000000..43527e8569d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/push/set-length-zero-array-length-is-non-writable.js @@ -0,0 +1,38 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.push +description: > + A TypeError is thrown when "length" is [[Set]] on an empty array with non-writable "length". +info: | + Array.prototype.push ( ...items ) + + [...] + 2. Let len be ? LengthOfArrayLike(O). + [...] + 6. Perform ? Set(O, "length", 𝔽(len), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +Object.defineProperty(array, "length", { writable: false }); + +assert.throws(TypeError, function() { + array.push(); +}); + +assert(!array.hasOwnProperty(0)); +assert.sameValue(array.length, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/reduce/15.4.4.21-9-8.js b/js/src/tests/test262/built-ins/Array/prototype/reduce/15.4.4.21-9-8.js index fe64670a6d92..bfee2b441791 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reduce/15.4.4.21-9-8.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reduce/15.4.4.21-9-8.js @@ -25,7 +25,7 @@ Object.defineProperty(obj, "0", { configurable: true }); -Array.prototype.reduce.call(obj, function() {}, "initialValue"); +Array.prototype.reduce.call(obj, callbackfn, "initialValue"); assert.sameValue(accessed, false, 'accessed'); assert.sameValue(callbackAccessed, false, 'callbackAccessed'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/reduce/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/reduce/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..cb630d0d2654 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/reduce/callbackfn-resize-arraybuffer.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.reduce +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 3}); + var sample = new TA(buffer); + var expectedPrevs, expectedNexts, expectedIndices, expectedArrays; + var prevs, nexts, indices, arrays, result; + + prevs = []; + nexts = []; + indices = []; + arrays = []; + result = Array.prototype.reduce.call(sample, function(prev, next, index, array) { + if (prevs.length === 0) { + try { + buffer.resize(2 * BPE); + expectedPrevs = [262, 0]; + expectedNexts = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + expectedPrevs = [262, 0, 1]; + expectedNexts = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + prevs.push(prev); + nexts.push(next); + indices.push(index); + arrays.push(array); + return index; + }, 262); + + assert.compareArray(prevs, expectedPrevs, 'prevs (shrink)'); + assert.compareArray(nexts, expectedNexts, 'nexts (shrink)'); + assert.compareArray(indices, expectedIndices, 'indices (shrink)'); + assert.compareArray(arrays, expectedArrays, 'arrays (shrink)'); + assert.sameValue(result, expectedIndices[expectedIndices.length - 1], 'result (shrink)'); + + prevs = []; + nexts = []; + indices = []; + arrays = []; + result = Array.prototype.reduce.call(sample, function(prev, next, index, array) { + if (prevs.length === 0) { + try { + buffer.resize(3 * BPE); + } catch (_) {} + } + + prevs.push(prev); + nexts.push(next); + indices.push(index); + arrays.push(array); + return index; + }, 262); + + assert.compareArray(prevs, expectedPrevs, 'prevs (grow)'); + assert.compareArray(nexts, expectedNexts, 'nexts (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, expectedIndices[expectedIndices.length - 1], 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/reduce/shell.js b/js/src/tests/test262/built-ins/Array/prototype/reduce/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reduce/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reduce/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/reduceRight/15.4.4.22-9-8.js b/js/src/tests/test262/built-ins/Array/prototype/reduceRight/15.4.4.22-9-8.js index c1d94d48706f..6ff99c27d005 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reduceRight/15.4.4.22-9-8.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reduceRight/15.4.4.22-9-8.js @@ -9,9 +9,10 @@ description: > ---*/ var accessed = false; +var callbackAccessed = false; function callbackfn() { - accessed = true; + callbackAccessed = true; } var obj = { @@ -26,8 +27,9 @@ Object.defineProperty(obj, "5", { configurable: true }); -Array.prototype.reduceRight.call(obj, function() {}, "initialValue"); +Array.prototype.reduceRight.call(obj, callbackfn, "initialValue"); assert.sameValue(accessed, false, 'accessed'); +assert.sameValue(callbackAccessed, false, 'callbackAccessed'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/reduceRight/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/reduceRight/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..dc7d665dadc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/reduceRight/callbackfn-resize-arraybuffer.js @@ -0,0 +1,81 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.reduceright +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 3}); + var sample = new TA(buffer); + var expectedPrevsShrink, expectedNextsShrink, expectedIndicesShrink, expectedArraysShrink; + var expectedPrevsGrow, expectedNextsGrow, expectedIndicesGrow, expectedArraysGrow; + var prevs, nexts, indices, arrays, result; + + prevs = []; + nexts = []; + indices = []; + arrays = []; + result = Array.prototype.reduceRight.call(sample, function(prev, next, index, array) { + if (prevs.length === 0) { + try { + buffer.resize(BPE); + expectedPrevsShrink = [262, 2]; + expectedNextsShrink = [0, 0]; + expectedIndicesShrink = [2, 0]; + expectedArraysShrink = [sample, sample]; + expectedPrevsGrow = [262]; + expectedNextsGrow = [0]; + expectedIndicesGrow = [0]; + expectedArraysGrow = [sample]; + } catch (_) { + expectedPrevsShrink = expectedPrevsGrow = [262, 2, 1]; + expectedNextsShrink = expectedNextsGrow = [0, 0, 0]; + expectedIndicesShrink = expectedIndicesGrow = [2, 1, 0]; + expectedArraysShrink = expectedArraysGrow = [sample, sample, sample]; + } + } + + prevs.push(prev); + nexts.push(next); + indices.push(index); + arrays.push(array); + return index; + }, 262); + + assert.compareArray(prevs, expectedPrevsShrink, 'prevs (shrink)'); + assert.compareArray(nexts, expectedNextsShrink, 'nexts (shrink)'); + assert.compareArray(indices, expectedIndicesShrink, 'indices (shrink)'); + assert.compareArray(arrays, expectedArraysShrink, 'arrays (shrink)'); + assert.sameValue(result, 0, 'result (shrink)'); + + prevs = []; + nexts = []; + indices = []; + arrays = []; + result = Array.prototype.reduceRight.call(sample, function(prev, next, index, array) { + if (prevs.length === 0) { + try { + buffer.resize(3 * BPE); + } catch (_) {} + } + + prevs.push(prev); + nexts.push(next); + indices.push(index); + arrays.push(array); + return index; + }, 262); + + assert.compareArray(prevs, expectedPrevsGrow, 'prevs (grow)'); + assert.compareArray(nexts, expectedNextsGrow, 'nexts (grow)'); + assert.compareArray(indices, expectedIndicesGrow, 'indices (grow)'); + assert.compareArray(arrays, expectedArraysGrow, 'arrays (grow)'); + assert.sameValue(result, expectedIndicesGrow[expectedIndicesGrow.length - 1], 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/reduceRight/shell.js b/js/src/tests/test262/built-ins/Array/prototype/reduceRight/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reduceRight/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reduceRight/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T1.js index 6d69e1476c67..c3c857081c78 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T1.js @@ -9,14 +9,12 @@ esid: sec-array.prototype.reverse description: Checking case when reverse is given no arguments or one argument ---*/ -//CHECK#1 var x = []; var reverse = x.reverse(); if (reverse !== x) { throw new Test262Error('#1: x = []; x.reverse() === x. Actual: ' + (reverse)); } -//CHECK#2 x = []; x[0] = 1; var reverse = x.reverse(); @@ -24,24 +22,20 @@ if (reverse !== x) { throw new Test262Error('#2: x = []; x[0] = 1; x.reverse() === x. Actual: ' + (reverse)); } -//CHECK#3 x = new Array(1, 2); var reverse = x.reverse(); if (reverse !== x) { throw new Test262Error('#3: x = new Array(1,2); x.reverse() === x. Actual: ' + (reverse)); } -//CHECK#4 if (x[0] !== 2) { throw new Test262Error('#4: x = new Array(1,2); x.reverse(); x[0] === 2. Actual: ' + (x[0])); } -//CHECK#5 if (x[1] !== 1) { throw new Test262Error('#5: x = new Array(1,2); x.reverse(); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#6 if (x.length !== 2) { throw new Test262Error('#6: x = new Array(1,2); x.reverse(); x.length === 2. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T2.js index 264cad314867..17d693192f4e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T2.js @@ -9,7 +9,6 @@ esid: sec-array.prototype.reverse description: Checking this algorithm, elements are objects and primitives ---*/ -//CHECK#1 var x = []; x[0] = true; x[2] = Infinity; @@ -23,52 +22,42 @@ if (reverse !== x) { throw new Test262Error('#1: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse() === x. Actual: ' + (reverse)); } -//CHECK#2 if (x[0] !== "-1") { throw new Test262Error('#2: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[0] === "-1". Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== "NaN") { throw new Test262Error('#3: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[1] === "NaN". Actual: ' + (x[1])); } -//CHECK#4 if (x[2] !== undefined) { throw new Test262Error('#4: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[2] === undefined. Actual: ' + (x[2])); } -//CHECK#5 if (x[3] !== undefined) { throw new Test262Error('#5: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[3] === undefined. Actual: ' + (x[3])); } -//CHECK#6 if (x[4] !== undefined) { throw new Test262Error('#6: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[4] === undefined. Actual: ' + (x[4])); } -//CHECK#7 if (x[5] !== undefined) { throw new Test262Error('#7: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[5] === undefined. Actual: ' + (x[5])); } -//CHECK#8 if (x[6] !== undefined) { throw new Test262Error('#8: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[6] === undefined. Actual: ' + (x[6])); } -//CHECK#9 if (x[7] !== Infinity) { throw new Test262Error('#9: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[7] === Infinity. Actual: ' + (x[7])); } -//CHECK#10 if (x[8] !== undefined) { throw new Test262Error('#10: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[8] === undefined. Actual: ' + (x[8])); } -//CHECK#11 if (x[9] !== true) { throw new Test262Error('#11: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x[9] === true. Actual: ' + (x[9])); } @@ -80,47 +69,38 @@ if (reverse !== x) { throw new Test262Error('#1: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse() === x. Actual: ' + (reverse)); } -//CHECK#12 if (x[0] !== undefined) { throw new Test262Error('#12: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#13 if (x[1] !== Infinity) { throw new Test262Error('#13: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[1] === Infinity. Actual: ' + (x[1])); } -//CHECK#14 if (x[2] !== undefined) { throw new Test262Error('#14: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[2] === undefined. Actual: ' + (x[2])); } -//CHECK#15 if (x[3] !== undefined) { throw new Test262Error('#15: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[3] === undefined. Actual: ' + (x[3])); } -//CHECK#16 if (x[4] !== undefined) { throw new Test262Error('#16: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[4] === undefined. Actual: ' + (x[4])); } -//CHECK#17 if (x[5] !== undefined) { throw new Test262Error('#17: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[5] === undefined. Actual: ' + (x[5])); } -//CHECK#18 if (x[6] !== undefined) { throw new Test262Error('#18: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[6] === undefined. Actual: ' + (x[6])); } -//CHECK#19 if (x[7] !== "NaN") { throw new Test262Error('#19: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[7] === "NaN". Actual: ' + (x[7])); } -//CHECK#20 if (x[8] !== "-1") { throw new Test262Error('#20: x = []; x[0] = true; x[2] = Infinity; x[4] = undefined; x[5] = undefined; x[8] = "NaN"; x[9] = "-1"; x.reverse(); x.length = 9; x.reverse(); x[8] === "-1". Actual: ' + (x[8])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T1.js index 87490cf3cdeb..be4e477e02b5 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T1.js @@ -11,7 +11,6 @@ description: > primitives, length is integer ---*/ -//CHECK#1 var obj = {}; obj.length = 10; obj.reverse = Array.prototype.reverse; @@ -28,52 +27,42 @@ if (reverse !== obj) { throw new Test262Error('#1: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse() === obj. Actual: ' + (reverse)); } -//CHECK#2 if (obj[0] !== "-1") { throw new Test262Error('#2: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[0] === "-1". Actual: ' + (obj[0])); } -//CHECK#3 if (obj[1] !== "NaN") { throw new Test262Error('#3: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[1] === "NaN". Actual: ' + (obj[1])); } -//CHECK#4 if (obj[2] !== undefined) { throw new Test262Error('#4: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[2] === undefined. Actual: ' + (obj[2])); } -//CHECK#5 if (obj[3] !== undefined) { throw new Test262Error('#5: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[3] === undefined. Actual: ' + (obj[3])); } -//CHECK#6 if (obj[4] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[4] === undefined. Actual: ' + (obj[4])); } -//CHECK#7 if (obj[5] !== undefined) { throw new Test262Error('#7: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[5] === undefined. Actual: ' + (obj[5])); } -//CHECK#8 if (obj[6] !== undefined) { throw new Test262Error('#8: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[6] === undefined. Actual: ' + (obj[6])); } -//CHECK#9 if (obj[7] !== Infinity) { throw new Test262Error('#9: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[7] === Infinity. Actual: ' + (obj[7])); } -//CHECK#10 if (obj[8] !== undefined) { throw new Test262Error('#10: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[8] === undefined. Actual: ' + (obj[8])); } -//CHECK#11 if (obj[9] !== true) { throw new Test262Error('#11: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[9] === true. Actual: ' + (obj[9])); } @@ -85,47 +74,38 @@ if (reverse !== obj) { throw new Test262Error('#1: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse() === obj. Actual: ' + (reverse)); } -//CHECK#12 if (obj[0] !== undefined) { throw new Test262Error('#12: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[0] === undefined. Actual: ' + (obj[0])); } -//CHECK#13 if (obj[1] !== Infinity) { throw new Test262Error('#13: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[1] === Infinity. Actual: ' + (obj[1])); } -//CHECK#14 if (obj[2] !== undefined) { throw new Test262Error('#14: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[2] === undefined. Actual: ' + (obj[2])); } -//CHECK#15 if (obj[3] !== undefined) { throw new Test262Error('#15: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[3] === undefined. Actual: ' + (obj[3])); } -//CHECK#16 if (obj[4] !== undefined) { throw new Test262Error('#16: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[4] === undefined. Actual: ' + (obj[4])); } -//CHECK#17 if (obj[5] !== undefined) { throw new Test262Error('#17: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[5] === undefined. Actual: ' + (obj[5])); } -//CHECK#18 if (obj[6] !== undefined) { throw new Test262Error('#18: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[6] === undefined. Actual: ' + (obj[6])); } -//CHECK#19 if (obj[7] !== "NaN") { throw new Test262Error('#19: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[7] === "NaN". Actual: ' + (obj[7])); } -//CHECK#20 if (obj[8] !== "-1") { throw new Test262Error('#20: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = 9; obj.reverse(); obj[8] === "-1". Actual: ' + (obj[8])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T2.js index e7e71b5deb4f..0b61f0aeed19 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T2.js @@ -11,7 +11,6 @@ description: > primitives, length is not integer ---*/ -//CHECK#1 var obj = {}; obj.length = 10.5; obj.reverse = Array.prototype.reverse; @@ -28,52 +27,42 @@ if (reverse !== obj) { throw new Test262Error('#1: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse() === obj. Actual: ' + (reverse)); } -//CHECK#2 if (obj[0] !== "-1") { throw new Test262Error('#2: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[0] === "-1". Actual: ' + (obj[0])); } -//CHECK#3 if (obj[1] !== "NaN") { throw new Test262Error('#3: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[1] === "NaN". Actual: ' + (obj[1])); } -//CHECK#4 if (obj[2] !== undefined) { throw new Test262Error('#4: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[2] === undefined. Actual: ' + (obj[2])); } -//CHECK#5 if (obj[3] !== undefined) { throw new Test262Error('#5: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[3] === undefined. Actual: ' + (obj[3])); } -//CHECK#6 if (obj[4] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[4] === undefined. Actual: ' + (obj[4])); } -//CHECK#7 if (obj[5] !== undefined) { throw new Test262Error('#7: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[5] === undefined. Actual: ' + (obj[5])); } -//CHECK#8 if (obj[6] !== undefined) { throw new Test262Error('#8: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[6] === undefined. Actual: ' + (obj[6])); } -//CHECK#9 if (obj[7] !== Infinity) { throw new Test262Error('#9: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[7] === Infinity. Actual: ' + (obj[7])); } -//CHECK#10 if (obj[8] !== undefined) { throw new Test262Error('#10: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[8] === undefined. Actual: ' + (obj[8])); } -//CHECK#11 if (obj[9] !== true) { throw new Test262Error('#11: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[9] === true. Actual: ' + (obj[9])); } @@ -85,47 +74,38 @@ if (reverse !== obj) { throw new Test262Error('#1: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse() === obj. Actual: ' + (reverse)); } -//CHECK#12 if (obj[0] !== undefined) { throw new Test262Error('#12: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[0] === undefined. Actual: ' + (obj[0])); } -//CHECK#13 if (obj[1] !== Infinity) { throw new Test262Error('#13: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[1] === Infinity. Actual: ' + (obj[1])); } -//CHECK#14 if (obj[2] !== undefined) { throw new Test262Error('#14: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[2] === undefined. Actual: ' + (obj[2])); } -//CHECK#15 if (obj[3] !== undefined) { throw new Test262Error('#15: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[3] === undefined. Actual: ' + (obj[3])); } -//CHECK#16 if (obj[4] !== undefined) { throw new Test262Error('#16: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[4] === undefined. Actual: ' + (obj[4])); } -//CHECK#17 if (obj[5] !== undefined) { throw new Test262Error('#17: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[5] === undefined. Actual: ' + (obj[5])); } -//CHECK#18 if (obj[6] !== undefined) { throw new Test262Error('#18: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[6] === undefined. Actual: ' + (obj[6])); } -//CHECK#19 if (obj[7] !== "NaN") { throw new Test262Error('#19: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[7] === "NaN". Actual: ' + (obj[7])); } -//CHECK#20 if (obj[8] !== "-1") { throw new Test262Error('#20: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = 10.5; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new Number(9.5); obj.reverse(); obj[8] === "-1". Actual: ' + (obj[8])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T3.js index a6d2023fc078..0afd7860c5fc 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A2_T3.js @@ -11,7 +11,6 @@ description: > primitives, length is string ---*/ -//CHECK#1 var obj = {}; obj.length = "10"; obj.reverse = Array.prototype.reverse; @@ -28,52 +27,42 @@ if (reverse !== obj) { throw new Test262Error('#1: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse() === obj. Actual: ' + (reverse)); } -//CHECK#2 if (obj[0] !== "-1") { throw new Test262Error('#2: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[0] === "-1". Actual: ' + (obj[0])); } -//CHECK#3 if (obj[1] !== "NaN") { throw new Test262Error('#3: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[1] === "NaN". Actual: ' + (obj[1])); } -//CHECK#4 if (obj[2] !== undefined) { throw new Test262Error('#4: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[2] === undefined. Actual: ' + (obj[2])); } -//CHECK#5 if (obj[3] !== undefined) { throw new Test262Error('#5: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[3] === undefined. Actual: ' + (obj[3])); } -//CHECK#6 if (obj[4] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[4] === undefined. Actual: ' + (obj[4])); } -//CHECK#7 if (obj[5] !== undefined) { throw new Test262Error('#7: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[5] === undefined. Actual: ' + (obj[5])); } -//CHECK#8 if (obj[6] !== undefined) { throw new Test262Error('#8: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[6] === undefined. Actual: ' + (obj[6])); } -//CHECK#9 if (obj[7] !== Infinity) { throw new Test262Error('#9: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[7] === Infinity. Actual: ' + (obj[7])); } -//CHECK#10 if (obj[8] !== undefined) { throw new Test262Error('#10: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[8] === undefined. Actual: ' + (obj[8])); } -//CHECK#11 if (obj[9] !== true) { throw new Test262Error('#11: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj[9] === true. Actual: ' + (obj[9])); } @@ -85,47 +74,38 @@ if (reverse !== obj) { throw new Test262Error('#1: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse() === obj. Actual: ' + (reverse)); } -//CHECK#12 if (obj[0] !== undefined) { throw new Test262Error('#12: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[0] === undefined. Actual: ' + (obj[0])); } -//CHECK#13 if (obj[1] !== Infinity) { throw new Test262Error('#13: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[1] === Infinity. Actual: ' + (obj[1])); } -//CHECK#14 if (obj[2] !== undefined) { throw new Test262Error('#14: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[2] === undefined. Actual: ' + (obj[2])); } -//CHECK#15 if (obj[3] !== undefined) { throw new Test262Error('#15: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[3] === undefined. Actual: ' + (obj[3])); } -//CHECK#16 if (obj[4] !== undefined) { throw new Test262Error('#16: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[4] === undefined. Actual: ' + (obj[4])); } -//CHECK#17 if (obj[5] !== undefined) { throw new Test262Error('#17: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[5] === undefined. Actual: ' + (obj[5])); } -//CHECK#18 if (obj[6] !== undefined) { throw new Test262Error('#18: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[6] === undefined. Actual: ' + (obj[6])); } -//CHECK#19 if (obj[7] !== "NaN") { throw new Test262Error('#19: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[7] === "NaN". Actual: ' + (obj[7])); } -//CHECK#20 if (obj[8] !== "-1") { throw new Test262Error('#20: var obj = {}; obj.reverse = Array.prototype.reverse; obj.length = "10"; obj[0] = true; obj[2] = Infinity; obj[4] = undefined; obj[5] = undefined; obj[8] = "NaN"; obj[9] = "-1"; obj.reverse(); obj.length = new String("9"); obj.reverse(); obj[8] === "-1". Actual: ' + (obj[8])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A3_T3.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A3_T3.js index 102ddd43d398..6f757b571b15 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A3_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A3_T3.js @@ -14,28 +14,23 @@ obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; -//CHECK#1 var reverse = obj.reverse(); if (reverse !== obj) { throw new Test262Error('#1: var obj = {}; obj.reverse = Array.prototype.reverse; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.reverse() === obj. Actual: ' + (reverse)); } -//CHECK#2 if (obj.length !== -4294967294) { throw new Test262Error('#2: var obj = {}; obj.reverse = Array.prototype.reverse; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.reverse(); obj.length === -4294967294. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== "x") { throw new Test262Error('#3: var obj = {}; obj.reverse = Array.prototype.reverse; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.reverse(); obj[0] === "x". Actual: ' + (obj[0])); } -//CHECK#4 if (obj[1] !== "y") { throw new Test262Error('#4: var obj = {}; obj.reverse = Array.prototype.reverse; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.reverse(); obj[1] === "y". Actual: ' + (obj[1])); } -//CHECK#5 if (obj[2] !== "z") { throw new Test262Error('#5: var obj = {}; obj.reverse = Array.prototype.reverse; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.reverse(); obj[2] === "z". Actual: ' + (obj[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A4_T1.js index 1b80ce07e679..21f59fcf5203 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A4_T1.js @@ -14,24 +14,20 @@ var x = [0]; x.length = 2; x.reverse(); -//CHECK#1 if (x[0] !== 1) { throw new Test262Error('#1: Array.prototype[1] = 1; x = [0]; x.length = 2; x.reverse(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#2 if (x[1] !== 0) { throw new Test262Error('#2: Array.prototype[1] = 1; x = [0]; x.length = 2; x.reverse(); x[1] === 0. Actual: ' + (x[1])); } x.length = 0; -//CHECK#3 if (x[0] !== undefined) { throw new Test262Error('#3: Array.prototype[1] = 1; x = [0]; x.length = 2; x.reverse(); x.length = 0; x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: Array.prototype[1] = 1; x = [0]; x.length = 2; x.reverse(); x.length = 0; x[1] === 1. Actual: ' + (x[1])); } @@ -44,12 +40,10 @@ x = { }; x.reverse(); -//CHECK#5 if (x[0] !== 1) { throw new Test262Error('#5: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.reverse = Array.prototype.reverse; x = {0:0}; x.reverse(); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== 0) { throw new Test262Error('#6: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.reverse = Array.prototype.reverse; x = {0:0}; x.reverse(); x[1] === 0. Actual: ' + (x[1])); } @@ -57,12 +51,10 @@ if (x[1] !== 0) { delete x[0]; delete x[1]; -//CHECK#7 if (x[0] !== undefined) { throw new Test262Error('#7: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.reverse = Array.prototype.reverse; x = {0:0}; x.reverse(); delete x[0]; delete x[1]; x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== 1) { throw new Test262Error('#8: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.reverse = Array.prototype.reverse; x = {0:0}; x.reverse(); delete x[0]; delete x[1]; x[1] === 1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A4_T2.js index 72952f189448..f71c23a26276 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A4_T2.js @@ -14,24 +14,20 @@ var x = [0, 1]; x.length = 2; x.reverse(); -//CHECK#1 if (x[0] !== 1) { throw new Test262Error('#1: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.reverse(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#2 if (x[1] !== 0) { throw new Test262Error('#2: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.reverse(); x[1] === 0. Actual: ' + (x[1])); } x.length = 0; -//CHECK#3 if (x[0] !== undefined) { throw new Test262Error('#3: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.reverse(); x.length = 0; x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== -1) { throw new Test262Error('#4: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.reverse(); x.length = 0; x[1] === -1. Actual: ' + (x[1])); } @@ -45,12 +41,10 @@ x = { }; x.reverse(); -//CHECK#5 if (x[0] !== 1) { throw new Test262Error('#5: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.reverse = Array.prototype.reverse; x = {0:0,1:1}; x.reverse(); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== 0) { throw new Test262Error('#6: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.reverse = Array.prototype.reverse; x = {0:0,1:1}; x.reverse(); x[1] === 0. Actual: ' + (x[1])); } @@ -58,12 +52,10 @@ if (x[1] !== 0) { delete x[0]; delete x[1]; -//CHECK#7 if (x[0] !== undefined) { throw new Test262Error('#7: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.reverse = Array.prototype.reverse; x = {0:0,1:1}; x.reverse(); delete x[0]; delete x[1]; x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== -1) { throw new Test262Error('#8: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.reverse = Array.prototype.reverse; x = {0:0,1:1}; x.reverse(); delete x[0]; delete x[1]; x[1] === -1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A5.7.js b/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A5.7.js deleted file mode 100644 index bc3a1ebf857d..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/reverse/S15.4.4.8_A5.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The reverse property of Array can't be used as constructor -esid: sec-array.prototype.reverse -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.reverse(); - throw new Test262Error('#1.1: new Array.prototype.reverse() throw TypeError. Actual: ' + (new Array.prototype.reverse())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.reverse() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A1.1_T1.js index bbd2007202bb..1f70e9b7357e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A1.1_T1.js @@ -9,19 +9,16 @@ esid: sec-array.prototype.shift description: Checking this algorithm ---*/ -//CHECK#1 var x = new Array(); var shift = x.shift(); if (shift !== undefined) { throw new Test262Error('#1: var x = new Array(); x.shift() === undefined. Actual: ' + (shift)); } -//CHECK#2 if (x.length !== 0) { throw new Test262Error('#2: var x = new Array(); x.shift(); x.length === 0. Actual: ' + (x.length)); } -//CHECK#3 var x = Array(1, 2, 3); x.length = 0; var shift = x.shift(); @@ -29,7 +26,6 @@ if (shift !== undefined) { throw new Test262Error('#2: var x = Array(1,2,3); x.length = 0; x.shift() === undefined. Actual: ' + (shift)); } -//CHECK#4 if (x.length !== 0) { throw new Test262Error('#4: var x = new Array(1,2,3); x.length = 0; x.shift(); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A1.2_T1.js index 4ee5e667018e..a0e9c13392d3 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A1.2_T1.js @@ -9,29 +9,24 @@ esid: sec-array.prototype.shift description: Checking this use new Array() and [] ---*/ -//CHECK#1 var x = new Array(0, 1, 2, 3); var shift = x.shift(); if (shift !== 0) { throw new Test262Error('#1: x = new Array(0,1,2,3); x.shift() === 0. Actual: ' + (shift)); } -//CHECK#2 if (x.length !== 3) { throw new Test262Error('#2: x = new Array(0,1,2,3); x.shift(); x.length == 3'); } -//CHECK#3 if (x[0] !== 1) { throw new Test262Error('#3: x = new Array(0,1,2,3); x.shift(); x[0] == 1'); } -//CHECK#4 if (x[1] !== 2) { throw new Test262Error('#4: x = new Array(0,1,2,3); x.shift(); x[1] == 2'); } -//CHECK#5 x = []; x[0] = 0; x[3] = 3; @@ -40,29 +35,24 @@ if (shift !== 0) { throw new Test262Error('#5: x = []; x[0] = 0; x[3] = 3; x.shift() === 0. Actual: ' + (shift)); } -//CHECK#6 if (x.length !== 3) { throw new Test262Error('#6: x = []; x[0] = 0; x[3] = 3; x.shift(); x.length == 3'); } -//CHECK#7 if (x[0] !== undefined) { throw new Test262Error('#7: x = []; x[0] = 0; x[3] = 3; x.shift(); x[0] == undefined'); } -//CHECK#8 if (x[12] !== undefined) { throw new Test262Error('#8: x = []; x[0] = 0; x[3] = 3; x.shift(); x[1] == undefined'); } -//CHECK#9 x.length = 1; var shift = x.shift(); if (shift !== undefined) { throw new Test262Error('#9: x = []; x[0] = 0; x[3] = 3; x.shift(); x.length = 1; x.shift() === undefined. Actual: ' + (shift)); } -//CHECK#10 if (x.length !== 0) { throw new Test262Error('#10: x = []; x[0] = 0; x[3] = 3; x.shift(); x.length = 1; x.shift(); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T1.js index 23c8a7757dc7..29f2f4f311c3 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T1.js @@ -17,37 +17,31 @@ obj.shift = Array.prototype.shift; if (obj.length !== undefined) { throw new Test262Error('#0: var obj = {}; obj.length === undefined. Actual: ' + (obj.length)); } else { - //CHECK#1 var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#1: var obj = {}; obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } - //CHECK#2 if (obj.length !== 0) { throw new Test262Error('#2: var obj = {}; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } } -//CHECK#3 obj.length = undefined; var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#3: var obj = {}; obj.length = undefined; obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#4 if (obj.length !== 0) { throw new Test262Error('#4: var obj = {}; obj.length = undefined; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#5 obj.length = null var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#5: var obj = {}; obj.length = null; obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#6 if (obj.length !== 0) { throw new Test262Error('#6: var obj = {}; obj.length = null; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T2.js index aad7476c95b8..cbe2c1864454 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T2.js @@ -14,38 +14,32 @@ description: > var obj = {}; obj.shift = Array.prototype.shift; -//CHECK#1 obj.length = NaN; var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#1: var obj = {}; obj.length = NaN; obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#2 if (obj.length !== 0) { throw new Test262Error('#2: var obj = {}; obj.length = NaN; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#5 obj.length = Number.NEGATIVE_INFINITY; var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#5: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#6 if (obj.length !== 0) { throw new Test262Error('#6: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#7 obj.length = -0; var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#7: var obj = {}; obj.length = -0; obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#8 if (obj.length !== 0) { throw new Test262Error('#8: var obj = {}; obj.length = -0; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } else { @@ -54,26 +48,22 @@ if (obj.length !== 0) { } } -//CHECK#9 obj.length = 0.5; var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#9: var obj = {}; obj.length = 0.5; obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#10 if (obj.length !== 0) { throw new Test262Error('#10: var obj = {}; obj.length = 0.5; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#11 obj.length = new Number(0); var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#11: var obj = {}; obj.length = new Number(0); obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#12 if (obj.length !== 0) { throw new Test262Error('#12: var obj = {}; obj.length = new Number(0); obj.shift = Array.prototype.shift; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T3.js index 2862d841d851..13d371b6eecc 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T3.js @@ -14,26 +14,22 @@ description: > var obj = {}; obj.shift = Array.prototype.shift; -//CHECK#1 obj.length = 2.5; var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#1: var obj = {}; obj.length = 2.5; obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#2 if (obj.length !== 1) { throw new Test262Error('#2: var obj = {}; obj.length = 2.5; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#3 obj.length = new Number(2); var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#11: var obj = {}; obj.length = new Number(2); obj.shift = Array.prototype.shift; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#3 if (obj.length !== 1) { throw new Test262Error('#12: var obj = {}; obj.length = new Number(2); obj.shift = Array.prototype.shift; obj.shift(); obj.length === 1. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T4.js index 8a777ce2d39c..1f315396cd11 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T4.js @@ -16,37 +16,31 @@ obj["0"] = 0; obj["3"] = 3; obj.shift = Array.prototype.shift; -//CHECK#1 obj.length = 4; var shift = obj.shift(); if (shift !== 0) { throw new Test262Error('#1: var obj = {}; obj["0"] = 0; obj["3"] = 3; obj.length = 4; obj.shift = Array.prototype.shift; obj.shift() === 0. Actual: ' + (shift)); } -//CHECK#2 if (obj.length !== 3) { throw new Test262Error('#2: var obj = {}; obj["0"] = 0; obj["3"] = 3; obj.length = 4; obj.shift = Array.prototype.shift; obj.shift(); obj.length === 3. Actual: ' + (obj.length)); } -//CHECK#3 var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#3: var obj = {}; obj["0"] = 0; obj["3"] = 3; obj.length = 4; obj.shift = Array.prototype.shift; obj.shift(); obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#4 if (obj.length !== 2) { throw new Test262Error('#4: var obj = {}; obj["0"] = 0; obj["3"] = 3; obj.length = 4; obj.shift = Array.prototype.shift; obj.shift(); obj.shift(); obj.length === 2. Actual: ' + (obj.length)); } -//CHECK#5 obj.length = 1; var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#5: var obj = {}; obj["0"] = 0; obj["3"] = 3; obj.length = 4; obj.shift = Array.prototype.shift; obj.shift(); obj.shift(); obj.length = 1; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#6 if (obj.length !== 0) { throw new Test262Error('#6: var obj = {}; obj["0"] = 0; obj["3"] = 3; obj.length = 4; obj.shift = Array.prototype.shift; obj.shift(); obj.shift(); obj.length = 1; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T5.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T5.js index 916b27c89cf5..76b01bbe576d 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A2_T5.js @@ -14,137 +14,113 @@ description: > var obj = {}; obj.shift = Array.prototype.shift; -//CHECK#1 obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return 1 } }; var shift = obj.shift(); -if (shift !== -1) { - throw new Test262Error('#1: obj[0] = -1; obj.length = {valueOf: function() {return 1}} obj.shift() === -1. Actual: ' + (shift)); -} +assert.sameValue(shift, -1, 'The value of shift is expected to be -1'); -//CHECK#2 obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return 1 }, - toString: function() { + toString() { return 0 } }; var shift = obj.shift(); -if (shift !== -1) { - throw new Test262Error('#0: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {return 0}} obj.shift() === -1. Actual: ' + (shift)); -} +assert.sameValue(shift, -1, 'The value of shift is expected to be -1'); -//CHECK#3 obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return 1 }, - toString: function() { + toString() { return {} } }; var shift = obj.shift(); -if (shift !== -1) { - throw new Test262Error('#3: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {return {}}} obj.shift() === -1. Actual: ' + (shift)); -} +assert.sameValue(shift, -1, 'The value of shift is expected to be -1'); -//CHECK#4 try { obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return 1 }, - toString: function() { + toString() { throw "error" } }; var shift = obj.shift(); - if (shift !== -1) { - throw new Test262Error('#4.1: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {throw "error"}}; obj.shift() === ",". Actual: ' + (shift)); - } + assert.sameValue(shift, -1, 'The value of shift is expected to be -1'); } catch (e) { - if (e === "error") { - throw new Test262Error('#4.2: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {throw "error"}}; obj.shift() not throw "error"'); - } else { - throw new Test262Error('#4.3: obj[0] = -1; obj.length = {valueOf: function() {return 1}, toString: function() {throw "error"}}; obj.shift() not throw Error. Actual: ' + (e)); - } + assert.notSameValue(e, "error", 'The value of e is not "error"'); } -//CHECK#5 obj[0] = -1; obj.length = { - toString: function() { + toString() { return 0 } }; var shift = obj.shift(); -if (shift !== undefined) { - throw new Test262Error('#5: obj[0] = -1; obj.length = {toString: function() {return 0}} obj.shift() === undefined. Actual: ' + (shift)); -} +assert.sameValue(shift, undefined, 'The value of shift is expected to equal undefined'); -//CHECK#6 obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return 0 } } var shift = obj.shift(); -if (shift !== undefined) { - throw new Test262Error('#6: obj[0] = -1; obj.length = {valueOf: function() {return {}}, toString: function() {return 0}} obj.shift() === undefined. Actual: ' + (shift)); -} +assert.sameValue(shift, undefined, 'The value of shift is expected to equal undefined'); -//CHECK#7 try { obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { throw "error" }, - toString: function() { + toString() { return 0 } }; var shift = obj.shift(); - throw new Test262Error('#7.1: obj[0] = -1; obj.length = {valueOf: function() {throw "error"}, toString: function() {return 0}}; obj.shift() throw "error". Actual: ' + (shift)); + throw new Test262Error('#7.1: obj[0] = -1; obj.length = {valueOf() {throw "error"}, toString() {return 0}}; obj.shift() throw "error". Actual: ' + (shift)); } catch (e) { - if (e !== "error") { - throw new Test262Error('#7.2: obj[0] = -1; obj.length = {valueOf: function() {throw "error"}, toString: function() {return 0}}; obj.shift() throw "error". Actual: ' + (e)); - } + assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } -//CHECK#8 try { obj[0] = -1; obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return {} } }; var shift = obj.shift(); - throw new Test262Error('#8.1: obj[0] = -1; obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.shift() throw TypeError. Actual: ' + (shift)); + throw new Test262Error('#8.1: obj[0] = -1; obj.length = {valueOf() {return {}}, toString() {return {}}} obj.shift() throw TypeError. Actual: ' + (shift)); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#8.2: obj[0] = -1; obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.shift() throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A3_T3.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A3_T3.js index c4f3a9e08020..70d9a86cd0cd 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A3_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A3_T3.js @@ -13,23 +13,19 @@ obj[0] = "x"; obj[1] = "y"; obj.length = -4294967294; -//CHECK#1 var shift = obj.shift(); if (shift !== undefined) { throw new Test262Error('#1: var obj = {}; obj.shift = Array.prototype.shift; obj[0] = "x"; obj[1] = "y"; obj.length = -4294967294; obj.shift() === undefined. Actual: ' + (shift)); } -//CHECK#2 if (obj.length !== 0) { throw new Test262Error('#2: var obj = {}; obj.shift = Array.prototype.shift; obj[0] = "x"; obj[1] = "y"; obj.length = -4294967294; obj.shift(); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== "x") { throw new Test262Error('#3: var obj = {}; obj.shift = Array.prototype.shift; obj[0] = "x"; obj[1] = "y"; obj.length = -4294967294; obj.shift(); obj[0] === "x". Actual: ' + (obj[0])); } -//CHECK#4 if (obj[1] !== "y") { throw new Test262Error('#4: var obj = {}; obj.shift = Array.prototype.shift; obj[0] = "x" obj[1] = "y"; obj.length = -4294967294; obj.shift(); obj[1] === "y". Actual: ' + (obj[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A4_T1.js index 0cc52648bd01..8865e88e73f3 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A4_T1.js @@ -13,18 +13,15 @@ Array.prototype[1] = 1; var x = [0]; x.length = 2; -//CHECK#1 var shift = x.shift(); if (shift !== 0) { throw new Test262Error('#1: Array.prototype[1] = 1; x = [0]; x.length = 2; x.shift() === 0. Actual: ' + (shift)); } -//CHECK#2 if (x[0] !== 1) { throw new Test262Error('#2: Array.prototype[1] = 1; x = [0]; x.length = 2; x.shift(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== 1) { throw new Test262Error('#3: Array.prototype[1] = 1; x = [0]; x.length = 2; x.shift(); x[1] === 1. Actual: ' + (x[1])); } @@ -36,28 +33,23 @@ x = { 0: 0 }; -//CHECK#4 var shift = x.shift(); if (shift !== 0) { throw new Test262Error('#4: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0}; x.shift() === 0. Actual: ' + (shift)); } -//CHECK#5 if (x[0] !== 1) { throw new Test262Error('#5: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0}; x.shift(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== 1) { throw new Test262Error('#6: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0}; x.shift(); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#7 if (x.length !== 1) { throw new Test262Error('#7: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0}; x.shift(); x.length === 1. Actual: ' + (x.length)); } -//CHECK#8 delete x.length; if (x.length !== 2) { throw new Test262Error('#8: Object.prototype[1] = 1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0}; x.shift(); delete x; x.length === 2. Actual: ' + (x.length)); diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A4_T2.js index 34614cb643c9..def860e1777f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A4_T2.js @@ -13,18 +13,15 @@ Array.prototype[1] = -1; var x = [0, 1]; x.length = 2; -//CHECK#1 var shift = x.shift(); if (shift !== 0) { throw new Test262Error('#1: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.shift() === 0. Actual: ' + (shift)); } -//CHECK#2 if (x[0] !== 1) { throw new Test262Error('#2: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.shift(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== -1) { throw new Test262Error('#3: Array.prototype[1] = -1; x = [0,1]; x.length = 2; x.shift(); x[1] === -1. Actual: ' + (x[1])); } @@ -37,28 +34,23 @@ x = { 1: 1 }; -//CHECK#4 var shift = x.shift(); if (shift !== 0) { throw new Test262Error('#4: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0,1:1}; x.shift() === 0. Actual: ' + (shift)); } -//CHECK#5 if (x[0] !== 1) { throw new Test262Error('#5: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0,1:1}; x.shift(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== -1) { throw new Test262Error('#6: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0,1:1}; x.shift(); x[1] === -1. Actual: ' + (x[1])); } -//CHECK#7 if (x.length !== 1) { throw new Test262Error('#7: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0,1:1}; x.shift(); x.length === 1. Actual: ' + (x.length)); } -//CHECK#8 delete x.length; if (x.length !== 2) { throw new Test262Error('#8: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.shift = Array.prototype.shift; x = {0:0,1:1}; x.shift(); delete x; x.length === 2. Actual: ' + (x.length)); diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A5.7.js b/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A5.7.js deleted file mode 100644 index af2e5aeda191..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/shift/S15.4.4.9_A5.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The shift property of Array can't be used as constructor -esid: sec-array.prototype.shift -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.shift(); - throw new Test262Error('#1.1: new Array.prototype.shift() throw TypeError. Actual: ' + (new Array.prototype.shift())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.shift() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-array-is-frozen.js b/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-array-is-frozen.js new file mode 100644 index 000000000000..30064e098dce --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-array-is-frozen.js @@ -0,0 +1,45 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.shift +description: > + A TypeError is thrown when "length" is [[Set]] on a frozen array. +info: | + Array.prototype.shift ( ) + + [...] + 4. Let first be ? Get(O, "0"). + [...] + 8. Perform ? Set(O, "length", 𝔽(len - 1), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = new Array(1); +var arrayPrototypeGet0Calls = 0; + +Object.defineProperty(Array.prototype, "0", { + get() { + Object.freeze(array); + arrayPrototypeGet0Calls++; + }, +}); + +assert.throws(TypeError, function() { + array.shift(); +}); + +assert.sameValue(array.length, 1); +assert.sameValue(arrayPrototypeGet0Calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-array-length-is-non-writable.js b/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-array-length-is-non-writable.js new file mode 100644 index 000000000000..2094475bd9af --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-array-length-is-non-writable.js @@ -0,0 +1,45 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.shift +description: > + A TypeError is thrown when "length" is [[Set]] on an array with non-writable "length". +info: | + Array.prototype.shift ( ) + + [...] + 4. Let first be ? Get(O, "0"). + [...] + 8. Perform ? Set(O, "length", 𝔽(len - 1), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = new Array(1); +var arrayPrototypeGet0Calls = 0; + +Object.defineProperty(Array.prototype, "0", { + get() { + Object.defineProperty(array, "length", { writable: false }); + arrayPrototypeGet0Calls++; + }, +}); + +assert.throws(TypeError, function() { + array.shift(); +}); + +assert.sameValue(array.length, 1); +assert.sameValue(arrayPrototypeGet0Calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-zero-array-is-frozen.js b/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-zero-array-is-frozen.js new file mode 100644 index 000000000000..6e5a16be2dff --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-zero-array-is-frozen.js @@ -0,0 +1,34 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.shift +description: > + A TypeError is thrown when "length" is [[Set]] on an empty frozen array. +info: | + Array.prototype.shift ( ) + + [...] + 3. If len = 0, then + a. Perform ? Set(O, "length", +0𝔽, true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +Object.freeze(array); + +assert.throws(TypeError, function() { + array.shift(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-zero-array-length-is-non-writable.js b/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-zero-array-length-is-non-writable.js new file mode 100644 index 000000000000..d7ee7f8f6e45 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/shift/set-length-zero-array-length-is-non-writable.js @@ -0,0 +1,34 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.shift +description: > + A TypeError is thrown when "length" is [[Set]] on an empty array with non-writable "length". +info: | + Array.prototype.shift ( ) + + [...] + 3. If len = 0, then + a. Perform ? Set(O, "length", +0𝔽, true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +Object.defineProperty(array, "length", { writable: false }); + +assert.throws(TypeError, function() { + array.shift(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T1.js index c62a6fb40f04..08b9e8f6ea60 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T1.js @@ -12,33 +12,27 @@ description: length > end > start = 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(0, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(0,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(0,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(0,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(0,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(0,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(0,3); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T2.js index fc353c665876..e2ad4f11030c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T2.js @@ -12,18 +12,15 @@ description: length > end = start > 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(3, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(3,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(3,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(3,3); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T3.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T3.js index 785c21d19d29..098fe5df6adf 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T3.js @@ -12,18 +12,15 @@ description: length > start > end > 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(4, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(4,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(4,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(4,3); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T4.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T4.js index 9aaeaba49608..2a60f0819c7a 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T4.js @@ -12,18 +12,15 @@ description: length = end = start > 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(5, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(5,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(5,5); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(5,5); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T5.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T5.js index c79a7bd5b5a0..52276cb43146 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T5.js @@ -12,28 +12,23 @@ description: length = end > start > 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(3, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(3,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 2) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(3,5); arr.length === 2. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 3) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(3,5); arr[0] === 3. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 4) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(3,5); arr[1] === 4. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[3] !== undefined) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(3,5); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T6.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T6.js index 90f85850e7f4..c33acf360c97 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T6.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T6.js @@ -12,28 +12,23 @@ description: length > end > start > 0; var x = [0, 1, 2, 3, 4]; var arr = x.slice(2, 4); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(2,4); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 2) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(2,4); arr.length === 2. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 2) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(2,4); arr[0] === 2. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 3) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(2,4); arr[1] === 3. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[3] !== undefined) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(2,4); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T7.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T7.js index 935084943df2..608a2d1dfef2 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T7.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.1_T7.js @@ -12,28 +12,23 @@ description: end > length > start > 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(3, 6); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(3,6); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 2) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(3,6); arr.length === 2. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 3) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(3,6); arr[0] === 3. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 4) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(3,6); arr[1] === 4. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[3] !== undefined) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(3,6); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T1.js index 484cc83f8bfe..cf4b16b79dc0 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T1.js @@ -12,23 +12,19 @@ description: length > end = abs(start), start < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(-3, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-3,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 1) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-3,3); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 2) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-3,3); arr[0] === 2. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== undefined) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(-3,3); arr[1] === undefined. Actual: ' + (arr[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T2.js index 565740523aa0..2c37d6d9b6c2 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T2.js @@ -12,23 +12,19 @@ description: length = end > abs(start), start < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(-1, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-1,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 1) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-1,5); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 4) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-1,5); arr[0] === 4. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== undefined) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(-1,5); arr[1] === undefined. Actual: ' + (arr[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T3.js index 9390a31d2758..dc5a28a18f39 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T3.js @@ -12,23 +12,19 @@ description: abs(start) = length > end > 0, start < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(-5, 1); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-5,1); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 1) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-5,1); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-5,1); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== undefined) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(-5,1); arr[1] === undefined. Actual: ' + (arr[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T4.js index ceaf7fdf7ad5..3cabccfb4669 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T4.js @@ -12,43 +12,35 @@ description: abs(start) > length = end > 0, start < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(-9, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-9,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 5) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-9,5); arr.length === 5. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-9,5); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(-9,5); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(-9,5); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(-9,5); arr[3] === 3. Actual: ' + (arr[3])); } -//CHECK#7 if (arr[4] !== 4) { throw new Test262Error('#7: var x = [0,1,2,3,4]; var arr = x.slice(-9,5); arr[4] === 4. Actual: ' + (arr[4])); } -//CHECK#8 if (arr[5] !== undefined) { throw new Test262Error('#8: var x = [0,1,2,3,4]; var arr = x.slice(-9,5); arr[5] === undefined. Actual: ' + (arr[5])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T1.js index 3a6ef180a1fd..8ba48c3fbf1c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T1.js @@ -12,33 +12,27 @@ description: length > abs(end) > start = 0, end < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(0, -2); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(0,-2); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(0,-2); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(0,-2); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(0,-2); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(0,-2); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(0,-2); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T2.js index 6d583123f683..d9cd34fae4a9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T2.js @@ -12,18 +12,15 @@ description: length > abs(end) > start > 0, end < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(1, -4); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(1,-4); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(1,-4); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(1,-4); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T3.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T3.js index 7820564d8313..cee2aa722a78 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T3.js @@ -12,18 +12,15 @@ description: length = abs(end) > start = 0, end < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(0, -5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(0,-5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(0,-5); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(0,-5); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T4.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T4.js index df9352898cc9..b8e5c2de02db 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.3_T4.js @@ -12,18 +12,15 @@ description: abs(end) > length > start > 0, end < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(4, -9); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(4,-9); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(4,-9); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(4,-9); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T1.js index f2a7fb7f1946..4d3497d8c367 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T1.js @@ -12,33 +12,27 @@ description: -length = start < end < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(-5, -2); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-5,-2); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-5,-2); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-5,-2); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(-5,-2); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(-5,-2); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(-5,-2); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T2.js index 6b8b7578bee0..dc5edeb65b68 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T2.js @@ -12,28 +12,23 @@ description: -length < start < end < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(-3, -1); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-3,-1); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 2) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-3,-1); arr.length === 2. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 2) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-3,-1); arr[0] === 2. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 3) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(-3,-1); arr[1] === 3. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== undefined) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(-3,-1); arr[2] === undefined. Actual: ' + (arr[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T3.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T3.js index be10bb9164df..2ad1794dc56a 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T3.js @@ -12,38 +12,31 @@ description: start < -length < end < 0 var x = [0, 1, 2, 3, 4]; var arr = x.slice(-9, -1); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-9,-1); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 4) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-9,-1); arr.length === 4. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-9,-1); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(-9,-1); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(-9,-1); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(-9,-1); arr[3] === 3. Actual: ' + (arr[3])); } -//CHECK#7 if (arr[4] !== undefined) { throw new Test262Error('#7: var x = [0,1,2,3,4]; var arr = x.slice(-9,-1); arr[4] === undefined. Actual: ' + (arr[4])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T4.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T4.js index 3650c5556492..559654a7a682 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.4_T4.js @@ -12,18 +12,15 @@ description: start = end < -length var x = [0, 1, 2, 3, 4]; var arr = x.slice(-6, -6); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-6,-6); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-6,-6); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-6,-6); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.5_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.5_T1.js index d0c8602aa6a6..8003dd6aa088 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.5_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.5_T1.js @@ -10,28 +10,23 @@ description: end === undefined var x = [0, 1, 2, 3, 4]; var arr = x.slice(3, undefined); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(3, undefined); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 2) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(3, undefined); arr.length === 2. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 3) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(3, undefined); arr[0] === 3. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 4) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(3, undefined); arr[1] === 4. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== undefined) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(3, undefined); arr[2] === undefined. Actual: ' + (arr[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.5_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.5_T2.js index 2c8504d31dac..38fdc5e779eb 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.5_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A1.5_T2.js @@ -10,28 +10,23 @@ description: end is absent var x = [0, 1, 2, 3, 4]; var arr = x.slice(-2); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(-2); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 2) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(-2); arr.length === 2. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 3) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(-2); arr[0] === 3. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 4) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(-2); arr[1] === 4. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== undefined) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(-2); arr[2] === undefined. Actual: ' + (arr[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T1.js index d6088fd682a4..58e07e8b4911 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T1.js @@ -10,28 +10,23 @@ description: start is not integer var x = [0, 1, 2, 3, 4]; var arr = x.slice(2.5, 4); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(2.5,4); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 2) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(2.5,4); arr.length === 2. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 2) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(2.5,4); arr[0] === 2. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 3) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(2.5,4); arr[1] === 3. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[3] !== undefined) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(2.5,4); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T2.js index 315d414d8f9b..61501fa6a96c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T2.js @@ -10,33 +10,27 @@ description: start = NaN var x = [0, 1, 2, 3, 4]; var arr = x.slice(NaN, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(NaN,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(NaN,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(NaN,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(NaN,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(NaN,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(NaN,3); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T3.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T3.js index 1a57a515fd7f..184c6a3d50c4 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T3.js @@ -10,18 +10,15 @@ description: start = Infinity var x = [0, 1, 2, 3, 4]; var arr = x.slice(Number.POSITIVE_INFINITY, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(Number.POSITIVE_INFINITY,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(Number.POSITIVE_INFINITY,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(Number.POSITIVE_INFINITY,3); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T4.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T4.js index 43e7d76d3f32..c68293a53f8c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T4.js @@ -10,33 +10,27 @@ description: start = -Infinity var x = [0, 1, 2, 3, 4]; var arr = x.slice(Number.NEGATIVE_INFINITY, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(Number.NEGATIVE_INFINITY,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(Number.NEGATIVE_INFINITY,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(Number.NEGATIVE_INFINITY,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(Number.NEGATIVE_INFINITY,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(Number.NEGATIVE_INFINITY,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(Number.NEGATIVE_INFINITY,3); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T5.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T5.js index 1d230eea7ce4..5516c0de6dbb 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.1_T5.js @@ -17,33 +17,27 @@ var arr = x.slice({ } }, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T1.js index a31edac37143..3ce7f0e68bf4 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T1.js @@ -10,28 +10,23 @@ description: end is not integer var x = [0, 1, 2, 3, 4]; var arr = x.slice(2, 4.5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(2,4.5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 2) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(2,4.5); arr.length === 2. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 2) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(2,4.5); arr[0] === 2. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 3) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(2,4.5); arr[1] === 3. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[3] !== undefined) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(2,4.5); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T2.js index 25c30c9e8fc0..a875da047b0f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T2.js @@ -10,18 +10,15 @@ description: end = NaN var x = [0, 1, 2, 3, 4]; var arr = x.slice(0, NaN); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(0,NaN); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(0,NaN); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(0,NaN); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T3.js index ded3d4c963ea..3cad37ddbef4 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T3.js @@ -10,43 +10,35 @@ description: end = Infinity var x = [0, 1, 2, 3, 4]; var arr = x.slice(0, Number.POSITIVE_INFINITY); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.POSITIVE_INFINITY); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 5) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.POSITIVE_INFINITY); arr.length === 5. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.POSITIVE_INFINITY); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.POSITIVE_INFINITY); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.POSITIVE_INFINITY); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.POSITIVE_INFINITY); arr[3] === 3. Actual: ' + (arr[3])); } -//CHECK#7 if (arr[4] !== 4) { throw new Test262Error('#7: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.POSITIVE_INFINITY); arr[4] === 4. Actual: ' + (arr[4])); } -//CHECK#8 if (arr[5] !== undefined) { throw new Test262Error('#8: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.POSITIVE_INFINITY); arr[5] === undefined. Actual: ' + (arr[5])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T4.js index 810fa057d4dd..14a9bbe26b9f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T4.js @@ -10,18 +10,15 @@ description: end = -Infinity var x = [0, 1, 2, 3, 4]; var arr = x.slice(0, Number.NEGATIVE_INFINITY); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.NEGATIVE_INFINITY); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.NEGATIVE_INFINITY); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(0,Number.NEGATIVE_INFINITY); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T5.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T5.js index 9f93ece0f0bc..a5d20c21c3a9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T5.js @@ -17,33 +17,27 @@ var arr = x.slice(0, { } }); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3,4]; var arr = x.slice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3,4]; var arr = x.slice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3,4]; var arr = x.slice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3,4]; var arr = x.slice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3,4]; var arr = x.slice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var x = [0,1,2,3,4]; var arr = x.slice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T1.js index 64138fef0ad8..2eedb258f974 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T1.js @@ -21,33 +21,27 @@ obj[4] = 4; obj.length = 5; var arr = obj.slice(0, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,3); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T2.js index 367b5bda3952..017c5e5bc6bb 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T2.js @@ -21,33 +21,27 @@ obj[4] = 4; obj.length = 5; var arr = obj.slice(-5, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,3); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T3.js index 3b95fb3da414..739b23457cb9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T3.js @@ -21,33 +21,27 @@ obj[4] = 4; obj.length = 5; var arr = obj.slice(0, -2); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,-2); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,-2); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,-2); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,-2); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,-2); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(0,-2); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T4.js index 76a300cf1687..2b70862d78ae 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T4.js @@ -21,33 +21,27 @@ obj[4] = 4; obj.length = 5; var arr = obj.slice(-5, -2); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,-2); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,-2); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,-2); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,-2); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,-2); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(-5,-2); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T5.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T5.js index 93ccb6592225..5adbd4e740a7 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T5.js @@ -19,33 +19,27 @@ obj[4] = 4; obj.length = 5; var arr = obj.slice(2); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 2) { throw new Test262Error('#3: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2); arr[0] === 2. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 3) { throw new Test262Error('#4: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2); arr[1] === 3. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 4) { throw new Test262Error('#5: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2); arr[2] === 4. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T6.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T6.js index f916d0871012..1646ec69827a 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T6.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A2_T6.js @@ -19,33 +19,27 @@ obj[4] = 4; obj.length = 5; var arr = obj.slice(2, undefined); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2, undefined); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2, undefined); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 2) { throw new Test262Error('#3: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2, undefined); arr[0] === 2. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 3) { throw new Test262Error('#4: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2, undefined); arr[1] === 3. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 4) { throw new Test262Error('#5: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2, undefined); arr[2] === 4. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = 0; obj[1] = 1; obj[2] = 2; obj[3] = 3; obj[4] = 4; obj.length = 5; var arr = obj.slice(2, undefined); arr[3] === undefined. Actual: ' + (arr[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T1.js index c54c692cbbd9..882be8b71b4b 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T1.js @@ -7,19 +7,13 @@ esid: sec-array.prototype.slice description: length = 4294967296 ---*/ -var obj = {}; -obj.slice = Array.prototype.slice; -obj[0] = "x"; -obj[4294967295] = "y"; -obj.length = 4294967296; - -try { - var arr = obj.slice(0, 4294967296); - throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.slice(0,4294967296); lead to throwing exception.'); -} catch (e) { - if (!(e instanceof RangeError)) { - throw new Test262Error('#1.1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.slice(0,4294967296); lead to throwing exception. Exception is instance of RangeError. Actual: exception is ' + e); - } -} +assert.throws(RangeError, () => { + var obj = {}; + obj.slice = Array.prototype.slice; + obj[0] = "x"; + obj[4294967295] = "y"; + obj.length = 4294967296; + obj.slice(0, 4294967296); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T2.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T2.js index eb491fa5ff00..45d225c6b7ee 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T2.js @@ -7,19 +7,13 @@ esid: sec-array.prototype.slice description: length = 4294967297 ---*/ -var obj = {}; -obj.slice = Array.prototype.slice; -obj[0] = "x"; -obj[4294967296] = "y"; -obj.length = 4294967297; - -try { - var arr = obj.slice(0, 4294967297); - throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = "x"; obj[4294967296] = "y"; obj.length = 4294967297; var arr = obj.slice(0,4294967297); lead to throwing exception.'); -} catch (e) { - if (!(e instanceof RangeError)) { - throw new Test262Error('#1.1: var obj = {}; obj.slice = Array.prototype.slice; obj[0] = "x"; obj[4294967296] = "y"; obj.length = 4294967297; var arr = obj.slice(0,4294967297); lead to throwing exception. Exception is instance of RangeError. Actual: exception is ' + e); - } -} +assert.throws(RangeError, () => { + var obj = {}; + obj.slice = Array.prototype.slice; + obj[0] = "x"; + obj[4294967296] = "y"; + obj.length = 4294967297; + obj.slice(0, 4294967297); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T3.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T3.js index 76bd3e980815..876eb9c4f9b0 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A3_T3.js @@ -13,12 +13,10 @@ obj[4294967294] = "x"; obj.length = -1; var arr = obj.slice(4294967294, 4294967295); -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var obj = {}; obj.slice = Array.prototype.slice; obj[4294967294] = "x"; obj.length = 4294967295; var arr = obj.slice(4294967294,4294967295); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== undefined) { throw new Test262Error('#3: var obj = {}; obj.slice = Array.prototype.slice; obj[4294967294] = "x"; obj.length = 4294967295; var arr = obj.slice(4294967294,4294967295); arr[0] === undefined. Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A4_T1.js index 2e34c2a54d66..210f014a9612 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A4_T1.js @@ -12,17 +12,14 @@ var x = [0]; x.length = 2; var arr = x.slice(); -//CHECK#1 if (arr[0] !== 0) { throw new Test262Error('#1: Array.prototype[1] = 1; x = [0]; x.length = 2; var arr = x.slice(); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#2 if (arr[1] !== 1) { throw new Test262Error('#2: Array.prototype[1] = 1; x = [0]; x.length = 2; var arr = x.slice(); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#3 if (arr.hasOwnProperty('1') !== true) { throw new Test262Error('#3: Array.prototype[1] = 1; x = [0]; x.length = 2; var arr = x.slice(); arr.hasOwnProperty(\'1\') === true. Actual: ' + (arr.hasOwnProperty('1'))); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A5.7.js b/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A5.7.js deleted file mode 100644 index 5e169afed29a..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/slice/S15.4.4.10_A5.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The slice property of Array can't be used as constructor -esid: sec-array.prototype.slice -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.slice(); - throw new Test262Error('#1.1: new Array.prototype.slice() throw TypeError. Actual: ' + (new Array.prototype.slice())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.slice() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/some/callbackfn-resize-arraybuffer.js b/js/src/tests/test262/built-ins/Array/prototype/some/callbackfn-resize-arraybuffer.js new file mode 100644 index 000000000000..49c6da008d3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/some/callbackfn-resize-arraybuffer.js @@ -0,0 +1,74 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.some +description: TypedArray instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.some.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (shrink)'); + assert.compareArray(indices, expectedIndices, 'indices (shrink)'); + assert.compareArray(arrays, expectedArrays, 'arrays (shrink)'); + assert.sameValue(result, false, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = Array.prototype.some.call(sample, function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, false, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/some/shell.js b/js/src/tests/test262/built-ins/Array/prototype/some/shell.js index e69de29bb2d1..e9580b311369 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/some/shell.js +++ b/js/src/tests/test262/built-ins/Array/prototype/some/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.1_T1.js index a6bf8bf0d2e3..af681151b3c5 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.1_T1.js @@ -12,17 +12,14 @@ description: If comparefn is undefined, use SortCompare operator var x = new Array(2); x.sort(); -//CHECK#1 if (x.length !== 2) { throw new Test262Error('#1: var x = new Array(2); x.sort(); x.length === 2. Actual: ' + (x.length)); } -//CHECK#2 if (x[0] !== undefined) { throw new Test262Error('#2: var x = new Array(2); x.sort(); x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== undefined) { throw new Test262Error('#3: var x = new Array(2); x.sort(); x[1] === undefined. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.2_T1.js index 768a2f1c821c..95ccc2f4c9a9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.2_T1.js @@ -14,17 +14,14 @@ var x = new Array(2); x[1] = 1; x.sort(); -//CHECK#1 if (x.length !== 2) { throw new Test262Error('#1: var x = new Array(2); x[1] = 1; x.sort(); x.length === 2. Actual: ' + (x.length)); } -//CHECK#2 if (x[0] !== 1) { throw new Test262Error('#2: var x = new Array(2); x[1] = 1; x.sort(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== undefined) { throw new Test262Error('#3: var x = new Array(2); x[1] = 1; x.sort(); x[1] === undefined. Actual: ' + (x[1])); } @@ -33,17 +30,14 @@ var x = new Array(2); x[0] = 1; x.sort(); -//CHECK#4 if (x.length !== 2) { throw new Test262Error('#4: var x = new Array(2); x[0] = 1; x.sort(); x.length === 2. Actual: ' + (x.length)); } -//CHECK#5 if (x[0] !== 1) { throw new Test262Error('#5: var x = new Array(2); x[0] = 1; x.sort(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== undefined) { throw new Test262Error('#6: var x = new Array(2); x[0] = 1; x.sort(); x[1] === undefined. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.2_T2.js index b3c24c207317..5c106742173c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.2_T2.js @@ -20,17 +20,14 @@ var x = new Array(2); x[1] = 1; x.sort(myComparefn); -//CHECK#1 if (x.length !== 2) { throw new Test262Error('#1: var x = new Array(2); x[1] = 1; x.sort(myComparefn); x.length === 2. Actual: ' + (x.length)); } -//CHECK#2 if (x[0] !== 1) { throw new Test262Error('#2: var x = new Array(2); x[1] = 1; x.sort(myComparefn); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== undefined) { throw new Test262Error('#3: var x = new Array(2); x[1] = 1; x.sort(myComparefn); x[1] === undefined. Actual: ' + (x[1])); } @@ -39,17 +36,14 @@ var x = new Array(2); x[0] = 1; x.sort(myComparefn); -//CHECK#4 if (x.length !== 2) { throw new Test262Error('#4: var x = new Array(2); x[0] = 1; x.sort(myComparefn); x.length === 2. Actual: ' + (x.length)); } -//CHECK#5 if (x[0] !== 1) { throw new Test262Error('#5: var x = new Array(2); x[0] = 1; x.sort(myComparefn); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== undefined) { throw new Test262Error('#6: var x = new Array(2); x[0] = 1; x.sort(myComparefn); x[1] === undefined. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.3_T1.js index 8cb2cfabb542..6a6d33050654 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.3_T1.js @@ -12,17 +12,14 @@ description: If comparefn is undefined, use SortCompare operator var x = new Array(undefined, undefined); x.sort(); -//CHECK#1 if (x.length !== 2) { throw new Test262Error('#1: var x = new Array(undefined, undefined); x.sort(); x.length === 2. Actual: ' + (x.length)); } -//CHECK#2 if (x[0] !== undefined) { throw new Test262Error('#2: var x = new Array(undefined, undefined); x.sort(); x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== undefined) { throw new Test262Error('#3: var x = new Array(undefined, undefined); x.sort(); x[1] === undefined. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T1.js index d352c45ce8da..425c2361dd01 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T1.js @@ -12,17 +12,14 @@ description: If comparefn is undefined, use SortCompare operator var x = new Array(undefined, 1); x.sort(); -//CHECK#1 if (x.length !== 2) { throw new Test262Error('#1: var x = new Array(undefined, 1); x.sort(); x.length === 2. Actual: ' + (x.length)); } -//CHECK#2 if (x[0] !== 1) { throw new Test262Error('#2: var x = new Array(undefined, 1); x.sort(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== undefined) { throw new Test262Error('#3: var x = new Array(undefined, 1); x.sort(); x[1] === undefined. Actual: ' + (x[1])); } @@ -30,17 +27,14 @@ if (x[1] !== undefined) { var x = new Array(1, undefined); x.sort(); -//CHECK#4 if (x.length !== 2) { throw new Test262Error('#4: var x = new Array(1, undefined); x.sort(); x.length === 2. Actual: ' + (x.length)); } -//CHECK#5 if (x[0] !== 1) { throw new Test262Error('#5: var x = new Array(1, undefined); x.sort(); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== undefined) { throw new Test262Error('#6: var x = new Array(1, undefined); x.sort(); x[1] === undefined. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T2.js index 117b1647759a..c0ab63090a3e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T2.js @@ -18,17 +18,14 @@ var myComparefn = function(x, y) { var x = new Array(undefined, 1); x.sort(myComparefn); -//CHECK#1 if (x.length !== 2) { throw new Test262Error('#1: var x = new Array(undefined, 1); x.sort(myComparefn); x.length === 2. Actual: ' + (x.length)); } -//CHECK#2 if (x[0] !== 1) { throw new Test262Error('#2: var x = new Array(undefined, 1); x.sort(myComparefn); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== undefined) { throw new Test262Error('#3: var x = new Array(undefined, 1); x.sort(myComparefn); x[1] === undefined. Actual: ' + (x[1])); } @@ -36,17 +33,14 @@ if (x[1] !== undefined) { var x = new Array(1, undefined); x.sort(myComparefn); -//CHECK#4 if (x.length !== 2) { throw new Test262Error('#4: var x = new Array(1, undefined); x.sort(myComparefn); x.length === 2. Actual: ' + (x.length)); } -//CHECK#5 if (x[0] !== 1) { throw new Test262Error('#5: var x = new Array(1, undefined); x.sort(myComparefn); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== undefined) { throw new Test262Error('#6: var x = new Array(1, undefined); x.sort(myComparefn); x[1] === undefined. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.5_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.5_T1.js index 546f9f318c46..250933dd96f0 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.5_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A1.5_T1.js @@ -10,17 +10,14 @@ description: Checking sort() and sort(undefined) var x = new Array(1, 0); x.sort(); -//CHECK#1 if (x.length !== 2) { throw new Test262Error('#1: var x = new Array(1,0); x.sort(); x.length === 2. Actual: ' + (x.length)); } -//CHECK#2 if (x[0] !== 0) { throw new Test262Error('#2: var x = new Array(1,0); x.sort(); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== 1) { throw new Test262Error('#3: var x = new Array(1,0); x.sort(); x[1] === 1. Actual: ' + (x[1])); } @@ -28,17 +25,14 @@ if (x[1] !== 1) { var x = new Array(1, 0); x.sort(undefined); -//CHECK#4 if (x.length !== 2) { throw new Test262Error('#4: var x = new Array(1,0); x.sort(undefined); x.length === 2. Actual: ' + (x.length)); } -//CHECK#5 if (x[0] !== 0) { throw new Test262Error('#5: var x = new Array(1,0); x.sort(undefined); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== 1) { throw new Test262Error('#6: var x = new Array(1,0); x.sort(undefined); x[1] === 1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T1.js index 4c37ee88816c..b4c988eec510 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T1.js @@ -13,7 +13,6 @@ description: Checking ENGLISH ALPHABET var alphabetR = ["z", "y", "x", "w", "v", "u", "t", "s", "r", "q", "p", "o", "n", "M", "L", "K", "J", "I", "H", "G", "F", "E", "D", "C", "B", "A"]; var alphabet = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]; -//CHECK#1 alphabetR.sort(); var result = true; for (var i = 0; i < 26; i++) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T2.js index 7492dbe0191d..e6e8ac1fc88e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T2.js @@ -13,7 +13,6 @@ description: Checking RUSSIAN ALPHABET var alphabetR = ["ё", "я", "ю", "э", "ь", "ы", "ъ", "щ", "ш", "ч", "ц", "х", "ф", "у", "т", "с", "р", "П", "О", "Н", "М", "Л", "К", "Й", "И", "З", "Ж", "Е", "Д", "Г", "В", "Б", "А"]; var alphabet = ["А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "р", "с", "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ъ", "ы", "ь", "э", "ю", "я", "ё"]; -//CHECK#1 alphabetR.sort(); var result = true; for (var i = 0; i < 26; i++) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T3.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T3.js index cf1670bc8afc..d68d37b1344c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T3.js @@ -21,7 +21,6 @@ var obj = { var alphabetR = [undefined, 2, 1, "X", -1, "a", true, obj, NaN, Infinity]; var alphabet = [-1, obj, 1, 2, Infinity, NaN, "X", "a", true, undefined]; -//CHECK#1 alphabetR.sort(); var result = true; for (var i = 0; i < 10; i++) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T1.js index 775d8a44dc31..0473e9f88135 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T1.js @@ -18,7 +18,6 @@ var myComparefn = function(x, y) { return 0; } -//CHECK#1 alphabet.sort(myComparefn); var result = true; for (var i = 0; i < 26; i++) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T2.js index d0c3434be020..4c719c957fe4 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T2.js @@ -18,7 +18,6 @@ var myComparefn = function(x, y) { return 0; } -//CHECK#1 alphabet.sort(myComparefn); var result = true; for (var i = 0; i < 26; i++) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T3.js index 026293f1ba8c..3eef7ab2be80 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T3.js @@ -26,7 +26,6 @@ var myComparefn = function(x, y) { return 0; } -//CHECK#1 alphabetR.sort(myComparefn); var result = true; for (var i = 0; i < 10; i++) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A3_T1.js index dce4746d04c8..7add56c4b532 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A3_T1.js @@ -35,13 +35,11 @@ var alphabet = [-1, obj, 1, 2, Infinity, NaN, "X", "a", true, undefined]; alphabetR.sort(); -//CHECK#0 alphabetR.getClass = Object.prototype.toString; if (alphabetR.getClass() !== "[object " + "Object" + "]") { throw new Test262Error('#0: alphabetR.sort() is Object object, not Array object'); } -//CHECK#1 var result = true; for (var i = 0; i < 10; i++) { if (!(isNaN(alphabetR[i]) && isNaN(alphabet[i]))) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A3_T2.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A3_T2.js index 7f8102c63c5a..34b9e54b68f9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A3_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A3_T2.js @@ -43,13 +43,11 @@ var myComparefn = function(x, y) { alphabetR.sort(myComparefn); -//CHECK#0 alphabetR.getClass = Object.prototype.toString; if (alphabetR.getClass() !== "[object " + "Object" + "]") { throw new Test262Error('#0: alphabetR.sort() is Object object, not Array object'); } -//CHECK#1 var result = true; for (var i = 0; i < 10; i++) { if (!(isNaN(alphabetR[i]) && isNaN(alphabet[i]))) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A4_T3.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A4_T3.js index 8db1e0e03b73..75938b93c1dd 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A4_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A4_T3.js @@ -14,27 +14,22 @@ obj[1] = "y"; obj[2] = "x"; obj.length = -4294967294; -//CHECK#1 if (obj.sort() !== obj) { throw new Test262Error('#1: var obj = {}; obj.sort = Array.prototype.sort; obj[0] = "z"; obj[1] = "y"; obj[2] = "x"; obj.length = -4294967294; obj.sort() === obj. Actual: ' + (obj.sort())); } -//CHECK#2 if (obj.length !== -4294967294) { throw new Test262Error('#2: var obj = {}; obj.sort = Array.prototype.sort; obj[0] = "z"; obj[1] = "y"; obj[2] = "x"; obj.length = -4294967294; obj.sort(); obj.length === -4294967294. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== "z") { throw new Test262Error('#3: var obj = {}; obj.sort = Array.prototype.sort; obj[0] = "z"; obj[1] = "y"; obj[2] = "x"; obj.length = -4294967294; obj.sort(); obj[0] === "z". Actual: ' + (obj[0])); } -//CHECK#4 if (obj[1] !== "y") { throw new Test262Error('#4: var obj = {}; obj.sort = Array.prototype.sort; obj[0] = "z"; obj[1] = "y"; obj[2] = "x"; obj.length = -4294967294; obj.sort(); obj[1] === "y". Actual: ' + (obj[1])); } -//CHECK#5 if (obj[2] !== "x") { throw new Test262Error('#5: var obj = {}; obj.sort = Array.prototype.sort; obj[0] = "z"; obj[1] = "y"; obj[2] = "x"; obj.length = -4294967294; obj.sort(); obj[2] === "x". Actual: ' + (obj[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A5_T1.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A5_T1.js index 0ab41124f68e..18eaabaf4057 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A5_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A5_T1.js @@ -7,18 +7,12 @@ esid: sec-array.prototype.sort description: comparefn function throw "error" ---*/ -//CHECK#1 -var myComparefn = function(x, y) { - throw "error"; -} -var x = [1, 0]; -try { - x.sort(myComparefn) - throw new Test262Error('#1.1: Array.sort should not eat exceptions'); -} catch (e) { - if (e !== "error") { - throw new Test262Error('#1.2: Array.sort should not eat exceptions'); +assert.throws(Test262Error, () => { + var myComparefn = function(x, y) { + throw new Test262Error(); } -} + var x = [1, 0]; + x.sort(myComparefn); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A6_T2.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A6_T2.js index f99f913829aa..1b75ec229a04 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A6_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A6_T2.js @@ -14,24 +14,20 @@ var x = [1, 0]; x.length = 2; x.sort(); -//CHECK#1 if (x[0] !== 0) { throw new Test262Error('#1: Array.prototype[1] = -1; x = [1,0]; x.length = 2; x.sort(); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#2 if (x[1] !== 1) { throw new Test262Error('#2: Array.prototype[1] = -1; x = [1,0]; x.length = 2; x.sort(); x[1] === 1. Actual: ' + (x[1])); } x.length = 0; -//CHECK#3 if (x[0] !== undefined) { throw new Test262Error('#3: Array.prototype[1] = -1; x = [1,0]; x.length = 2; x.sort(); x.length = 0; x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== -1) { throw new Test262Error('#4: Array.prototype[1] = -1; x = [1,0]; x.length = 2; x.sort(); x.length = 0; x[1] === -1. Actual: ' + (x[1])); } @@ -45,12 +41,10 @@ x = { }; x.sort(); -//CHECK#5 if (x[0] !== 0) { throw new Test262Error('#5: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.sort = Array.prototype.sort; x = {0:1,1:0}; x.sort(); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== 1) { throw new Test262Error('#6: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.sort = Array.prototype.sort; x = {0:1,1:0}; x.sort(); x[1] === 1. Actual: ' + (x[1])); } @@ -58,12 +52,10 @@ if (x[1] !== 1) { delete x[0]; delete x[1]; -//CHECK#7 if (x[0] !== undefined) { throw new Test262Error('#7: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.sort = Array.prototype.sort; x = {0:1,1:0}; x.sort(); delete x[0]; delete x[1]; x[0] === undefined. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== -1) { throw new Test262Error('#8: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.sort = Array.prototype.sort; x = {0:1,1:0}; x.sort(); delete x[0]; delete x[1]; x[1] === -1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A7.7.js b/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A7.7.js deleted file mode 100644 index 2218e55b8e65..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/sort/S15.4.4.11_A7.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The sort property of Array can't be used as constructor -esid: sec-array.prototype.sort -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.sort(); - throw new Test262Error('#1.1: new Array.prototype.sort() throw TypeError. Actual: ' + (new Array.prototype.sort())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.sort() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T1.js index c1f9ea1691a3..fc6c0a0eb04e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T1.js @@ -12,38 +12,31 @@ description: length > deleteCount > start = 0, itemCount = 0 var x = [0, 1, 2, 3]; var arr = x.splice(0, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(0,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(0,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(0,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(0,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(0,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(0,3); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 3) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(0,3); x[0] === 3. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T2.js index a9150a78433b..acab980a908a 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T2.js @@ -12,48 +12,39 @@ description: length > deleteCount > start = 0, itemCount > 0 var x = [0, 1, 2, 3]; var arr = x.splice(0, 3, 4, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); x.length === 3. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 4) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); x[0] === 4. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== 5) { throw new Test262Error('#8: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); x[1] === 5. Actual: ' + (x[1])); } -//CHECK#9 if (x[2] !== 3) { throw new Test262Error('#9: var x = [0,1,2,3]; var arr = x.splice(0,3,4,5); x[2] === 3. Actual: ' + (x[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T3.js index 50c2f4a60d9d..a69ab334f154 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T3.js @@ -12,38 +12,31 @@ description: length = deleteCount > start = 0 var x = [0, 1, 2, 3]; var arr = x.splice(0, 4); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(0,4); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 4) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(0,4); arr.length === 4. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(0,4); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(0,4); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(0,4); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(0,4); arr[3] === 3. Actual: ' + (arr[3])); } -//CHECK#7 if (x.length !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(0,4); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T4.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T4.js index ff9ab6f85dbd..760b4cb0d133 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T4.js @@ -12,48 +12,39 @@ description: length > deleteCount > start > 0, itemCount > 0 var x = [0, 1, 2, 3]; var arr = x.splice(1, 3, 4, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 1) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 2) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); arr[1] === 2. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 3) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); arr[2] === 3. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); x.length === 3. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== 4) { throw new Test262Error('#8: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); x[1] === 4. Actual: ' + (x[1])); } -//CHECK#9 if (x[2] !== 5) { throw new Test262Error('#9: var x = [0,1,2,3]; var arr = x.splice(1,3,4,5); x[2] === 5. Actual: ' + (x[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T5.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T5.js index 748e046e9a7d..0d214530242d 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T5.js @@ -12,38 +12,31 @@ description: deleteCount > length > start = 0, itemCount = 0 var x = [0, 1, 2, 3]; var arr = x.splice(0, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(0,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 4) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(0,5); arr.length === 4. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(0,5); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(0,5); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(0,5); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(0,5); arr[3] === 3. Actual: ' + (arr[3])); } -//CHECK#7 if (x.length !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(0,5); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T6.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T6.js index 7b11811f3171..3daeb79c6125 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T6.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T6.js @@ -12,48 +12,39 @@ description: length = deleteCount > start > 0, itemCount > 0 var x = [0, 1, 2, 3]; var arr = x.splice(1, 4, 4, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 1) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 2) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); arr[1] === 2. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 3) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); arr[2] === 3. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); x.length === 3. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== 4) { throw new Test262Error('#8: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); x[1] === 4. Actual: ' + (x[1])); } -//CHECK#9 if (x[2] !== 5) { throw new Test262Error('#9: var x = [0,1,2,3]; var arr = x.splice(1,4,4,5); x[2] === 5. Actual: ' + (x[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T1.js index 03d2905c3f1c..fae73a4f3487 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T1.js @@ -12,28 +12,23 @@ description: -length = start < deleteCount < 0, itemCount = 0 var x = [0, 1]; var arr = x.splice(-2, -1); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(-2,-1); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(-2,-1); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 2) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(-2,-1); x.length === 2. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(-2,-1); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(-2,-1); x[1] === 1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T2.js index 6b2c36dd70b2..a9f5127015c4 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T2.js @@ -12,28 +12,23 @@ description: -length < start = deleteCount < 0, itemCount = 0 var x = [0, 1]; var arr = x.splice(-1, -1); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(-1,-1); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(-1,-1); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 2) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(-1,-1); x.length === 2. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(-1,-1); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(-1,-1); x[1] === 1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T3.js index 13ed2ec195e8..6b8d6f5bfd53 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T3.js @@ -12,38 +12,31 @@ description: -length = start < deleteCount < 0, itemCount > 0 var x = [0, 1]; var arr = x.splice(-2, -1, 2, 3); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(-2,-1,2,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(-2,-1,2,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 4) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(-2,-1,2,3); x.length === 4. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 2) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(-2,-1,2,3); x[0] === 2. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 3) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(-2,-1,2,3); x[1] === 3. Actual: ' + (x[1])); } -//CHECK#5 if (x[2] !== 0) { throw new Test262Error('#5: var x = [0,1]; var arr = x.splice(-2,-1,2,3); x[2] === 0. Actual: ' + (x[2])); } -//CHECK#6 if (x[3] !== 1) { throw new Test262Error('#6: var x = [0,1]; var arr = x.splice(-2,-1,2,3); x[3] === 1. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T4.js index b1857228852f..e3be864ac8b4 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T4.js @@ -12,38 +12,31 @@ description: -length < start = deleteCount < 0, itemCount > 0 var x = [0, 1]; var arr = x.splice(-1, -1, 2, 3); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(-1,-1,2,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(-1,-1,2,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 4) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(-1,-1,2,3); x.length === 4. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(-1,-1,2,3); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 2) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(-1,-1,2,3); x[1] === 2. Actual: ' + (x[1])); } -//CHECK#5 if (x[2] !== 3) { throw new Test262Error('#5: var x = [0,1]; var arr = x.splice(-1,-1,2,3); x[2] === 3. Actual: ' + (x[2])); } -//CHECK#6 if (x[3] !== 1) { throw new Test262Error('#6: var x = [0,1]; var arr = x.splice(-1,-1,2,3); x[3] === 1. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T5.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T5.js index 7c6c8a6de92c..e1e0b56e320d 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T5.js @@ -12,38 +12,31 @@ description: start < -length < deleteCount < 0, itemCount > 0 var x = [0, 1]; var arr = x.splice(-3, -1, 2, 3); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(-3,-1,2,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(-3,-1,2,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 4) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(-3,-1,2,3); x.length === 4. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 2) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(-3,-1,2,3); x[0] === 2. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 3) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(-3,-1,2,3); x[1] === 3. Actual: ' + (x[1])); } -//CHECK#5 if (x[2] !== 0) { throw new Test262Error('#5: var x = [0,1]; var arr = x.splice(-3,-1,2,3); x[2] === 0. Actual: ' + (x[2])); } -//CHECK#6 if (x[3] !== 1) { throw new Test262Error('#6: var x = [0,1]; var arr = x.splice(-3,-1,2,3); x[3] === 1. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T1.js index 4c30d9ee4b30..5183980022ef 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T1.js @@ -12,28 +12,23 @@ description: -length < deleteCount < start = 0, itemCount = 0 var x = [0, 1]; var arr = x.splice(0, -1); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(0,-1); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(0,-1); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 2) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(0,-1); x.length === 2. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(0,-1); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(0,-1); x[1] === 1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T2.js index 728fb34ffce7..4d85c4b251be 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T2.js @@ -12,28 +12,23 @@ description: -length = -start < deleteCount < 0, itemCount = 0 var x = [0, 1]; var arr = x.splice(2, -1); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(2,-1); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(2,-1); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 2) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(2,-1); x.length === 2. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(2,-1); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(2,-1); x[1] === 1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T3.js index 8991245365f0..627753cd2463 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T3.js @@ -12,38 +12,31 @@ description: -length < deleteCount < start = 0, itemCount > 0 var x = [0, 1]; var arr = x.splice(0, -1, 2, 3); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(0,-1,2,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(0,-1,2,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 4) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(0,-1,2,3); x.length === 4. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 2) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(0,-1,2,3); x[0] === 2. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 3) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(0,-1,2,3); x[1] === 3. Actual: ' + (x[1])); } -//CHECK#5 if (x[2] !== 0) { throw new Test262Error('#5: var x = [0,1]; var arr = x.splice(0,-1,2,3); x[2] === 0. Actual: ' + (x[2])); } -//CHECK#6 if (x[3] !== 1) { throw new Test262Error('#6: var x = [0,1]; var arr = x.splice(0,-1,2,3); x[3] === 1. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T4.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T4.js index 0f52dac9a0a3..83e32eabadae 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T4.js @@ -12,38 +12,31 @@ description: -length = -start < deleteCount < 0, itemCount > 0 var x = [0, 1]; var arr = x.splice(2, -1, 2, 3); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(2,-1,2,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(2,-1,2,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 4) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(2,-1,2,3); x.length === 4. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(2,-1,2,3); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(2,-1,2,3); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#5 if (x[2] !== 2) { throw new Test262Error('#5: var x = [0,1]; var arr = x.splice(2,-1,2,3); x[2] === 2. Actual: ' + (x[2])); } -//CHECK#6 if (x[3] !== 3) { throw new Test262Error('#6: var x = [0,1]; var arr = x.splice(2,-1,2,3); x[3] === 3. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T5.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T5.js index d717c4b242ff..8e9c337f199b 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.3_T5.js @@ -12,38 +12,31 @@ description: -start < -length < deleteCount < 0, itemCount > 0 var x = [0, 1]; var arr = x.splice(3, -1, 2, 3); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(3,-1,2,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(3,-1,2,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 4) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(3,-1,2,3); x.length === 4. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(3,-1,2,3); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(3,-1,2,3); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#5 if (x[2] !== 2) { throw new Test262Error('#5: var x = [0,1]; var arr = x.splice(3,-1,2,3); x[2] === 2. Actual: ' + (x[2])); } -//CHECK#6 if (x[3] !== 3) { throw new Test262Error('#6: var x = [0,1]; var arr = x.splice(3,-1,2,3); x[3] === 3. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T1.js index e4d8e5d9091f..192c5d3d42e5 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T1.js @@ -12,38 +12,31 @@ description: length = -start > deleteCount > 0, itemCount = 0 var x = [0, 1, 2, 3]; var arr = x.splice(-4, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(-4,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(-4,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(-4,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(-4,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(-4,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(-4,3); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 3) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(-4,3); x[0] === 3. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T2.js index 632234140936..2b9c02509d16 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T2.js @@ -12,48 +12,39 @@ description: length = -start > deleteCount > 0, itemCount > 0 var x = [0, 1, 2, 3]; var arr = x.splice(-4, 3, 4, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); x.length === 3. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 4) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); x[0] === 4. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== 5) { throw new Test262Error('#8: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); x[1] === 5. Actual: ' + (x[1])); } -//CHECK#9 if (x[2] !== 3) { throw new Test262Error('#9: var x = [0,1,2,3]; var arr = x.splice(-4,3,4,5); x[2] === 3. Actual: ' + (x[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T3.js index 72090ad7ece1..61d50324c93d 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T3.js @@ -12,38 +12,31 @@ description: -start > length = deleteCount > 0, itemCount = 0 var x = [0, 1, 2, 3]; var arr = x.splice(-5, 4); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(-5,4); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 4) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(-5,4); arr.length === 4. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(-5,4); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(-5,4); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(-5,4); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(-5,4); arr[3] === 3. Actual: ' + (arr[3])); } -//CHECK#7 if (x.length !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(-5,4); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T4.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T4.js index d778a50fd4f1..14927ad334e6 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T4.js @@ -12,48 +12,39 @@ description: length > -start = deleteCount > 0, itemCount > 0 var x = [0, 1, 2, 3]; var arr = x.splice(-3, 3, 4, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 1) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 2) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); arr[1] === 2. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 3) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); arr[2] === 3. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); x.length === 3. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== 4) { throw new Test262Error('#8: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); x[1] === 4. Actual: ' + (x[1])); } -//CHECK#9 if (x[2] !== 5) { throw new Test262Error('#9: var x = [0,1,2,3]; var arr = x.splice(-3,3,4,5); x[2] === 5. Actual: ' + (x[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T5.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T5.js index 8f4ff32ca6b6..1ed94192ce66 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T5.js @@ -12,38 +12,31 @@ description: -start > deleteCount > length > 0, itemCount = 0 var x = [0, 1, 2, 3]; var arr = x.splice(-9, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(-9,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 4) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(-9,5); arr.length === 4. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(-9,5); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(-9,5); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(-9,5); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(-9,5); arr[3] === 3. Actual: ' + (arr[3])); } -//CHECK#7 if (x.length !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(-9,5); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T6.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T6.js index 57d61443524a..afae2a1210b5 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T6.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.4_T6.js @@ -12,48 +12,39 @@ description: length = deleteCount > -start > 0, itemCount > 0 var x = [0, 1, 2, 3]; var arr = x.splice(-3, 4, 4, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 1) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 2) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); arr[1] === 2. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 3) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); arr[2] === 3. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); x.length === 3. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#8 if (x[1] !== 4) { throw new Test262Error('#8: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); x[1] === 4. Actual: ' + (x[1])); } -//CHECK#9 if (x[2] !== 5) { throw new Test262Error('#9: var x = [0,1,2,3]; var arr = x.splice(-3,4,4,5); x[2] === 5. Actual: ' + (x[2])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.5_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.5_T1.js index b14d01e93b81..7819ebeb2fcd 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.5_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.5_T1.js @@ -10,38 +10,31 @@ description: start === undefined, end === undefined var x = [0, 1, 2, 3]; var arr = x.splice(undefined, undefined); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(undefined, undefined); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(undefined, undefined); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (x.length !== 4) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(undefined, undefined); x.length === 4. Actual: ' + (x.length)); } -//CHECK#4 if (x[0] !== 0) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(undefined, undefined); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#5 if (x[1] !== 1) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(undefined, undefined); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#6 if (x[2] !== 2) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(undefined, undefined); x[2] === 2. Actual: ' + (x[2])); } -//CHECK#7 if (x[3] !== 3) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(undefined, undefined); x[3] === 3. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.5_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.5_T2.js index 15477b590249..f53fab64b1b3 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.5_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A1.5_T2.js @@ -10,38 +10,31 @@ description: end === undefined var x = [0, 1, 2, 3]; var arr = x.splice(1, undefined); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(1,undefined); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(1,undefined); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (x.length !== 4) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(1,undefined); x.length === 4. Actual: ' + (x.length)); } -//CHECK#4 if (x[0] !== 0) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(1,undefined); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#5 if (x[1] !== 1) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(1,undefined); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#6 if (x[2] !== 2) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(1,undefined); x[2] === 2. Actual: ' + (x[2])); } -//CHECK#7 if (x[3] !== 3) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(1,undefined); x[3] === 3. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T1.js index f383acc25fce..eaab7b5b1145 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T1.js @@ -10,38 +10,31 @@ description: start is not integer var x = [0, 1, 2, 3]; var arr = x.splice(1.5, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(1.5,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(1.5,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 1) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(1.5,3); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 2) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(1.5,3); arr[1] === 2. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 3) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(1.5,3); arr[2] === 3. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(1.5,3); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(1.5,3); x[0] === 0. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T2.js index 0fc10f0be092..ad657a6c37f5 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T2.js @@ -10,38 +10,31 @@ description: start = NaN var x = [0, 1, 2, 3]; var arr = x.splice(NaN, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(NaN,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(NaN,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(NaN,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(NaN,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(NaN,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(NaN,3); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 3) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(NaN,3); x[0] === 3. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T3.js index 069c167b8a4b..0940f78ef557 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T3.js @@ -10,33 +10,27 @@ description: start = Infinity var x = [0, 1, 2, 3]; var arr = x.splice(Number.POSITIVE_INFINITY, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(Number.POSITIVE_INFINITY,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 0) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(Number.POSITIVE_INFINITY,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var x = x.splice(Number.POSITIVE_INFINITY,3); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var x = x.splice(Number.POSITIVE_INFINITY,3); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#5 if (x[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var x = x.splice(Number.POSITIVE_INFINITY,3); x[2] === 2. Actual: ' + (x[2])); } -//CHECK#6 if (x[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var x = x.splice(Number.POSITIVE_INFINITY,3); x[3] === 3. Actual: ' + (x[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T4.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T4.js index 0a11d253f4e6..50ce7b402acc 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T4.js @@ -10,38 +10,31 @@ description: start = -Infinity var x = [0, 1, 2, 3]; var arr = x.splice(Number.NEGATIVE_INFINITY, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(Number.NEGATIVE_INFINITY,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(Number.NEGATIVE_INFINITY,3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(Number.NEGATIVE_INFINITY,3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(Number.NEGATIVE_INFINITY,3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(Number.NEGATIVE_INFINITY,3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(Number.NEGATIVE_INFINITY,3); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 3) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(Number.NEGATIVE_INFINITY,3); x[0] === 3. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T5.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T5.js index c70470ccbc26..c4d40fc37026 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.1_T5.js @@ -17,38 +17,31 @@ var arr = x.splice({ } }, 3); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice({valueOf: function() {return 0}, toString: function() {return 3}},3); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice({valueOf: function() {return 0}, toString: function() {return 3}},3); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 3) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice({valueOf: function() {return 0}, toString: function() {return 3}},3); x[0] === 3. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T1.js index f6a5024a3dd1..81ab211c69b9 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T1.js @@ -10,38 +10,31 @@ description: deleteCount is not integer var x = [0, 1, 2, 3]; var arr = x.splice(1, 3.5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(1,3.5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(1,3.5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 1) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(1,3.5); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 2) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(1,3.5); arr[1] === 2. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 3) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(1,3.5); arr[2] === 3. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(1,3.5); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(1,3.5); x[0] === 0. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T2.js index 859e8f687056..735374b032ab 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T2.js @@ -10,28 +10,23 @@ description: deleteCount = NaN var x = [0, 1]; var arr = x.splice(0, NaN); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(0,NaN); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(0,NaN); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 2) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(0,NaN); x.length === 2. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(0,NaN); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(0,NaN); x[1] === 1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T3.js index 22c00f70c06d..26b991deda41 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T3.js @@ -10,38 +10,31 @@ description: deleteCount = Infinity var x = [0, 1, 2, 3]; var arr = x.splice(0, Number.POSITIVE_INFINITY); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(0,Number.POSITIVE_INFINITY); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 4) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(0,Number.POSITIVE_INFINITY); arr.length === 4. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(0,Number.POSITIVE_INFINITY); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(0,Number.POSITIVE_INFINITY); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(0,Number.POSITIVE_INFINITY); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (arr[3] !== 3) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(0,Number.POSITIVE_INFINITY); arr[3] === 3. Actual: ' + (arr[3])); } -//CHECK#7 if (x.length !== 0) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(0,Number.POSITIVE_INFINITY); x.length === 0. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T4.js index ba2d83ca2384..a644625c9073 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T4.js @@ -10,28 +10,23 @@ description: deleteCount = -Infinity var x = [0, 1]; var arr = x.splice(0, Number.NEGATIVE_INFINITY); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var x = [0,1]; var arr = x.splice(0,Number.NEGATIVE_INFINITY); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var x = [0,1]; var arr = x.splice(0,Number.NEGATIVE_INFINITY); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (x.length !== 2) { throw new Test262Error('#2: var x = [0,1]; var arr = x.splice(0,Number.NEGATIVE_INFINITY); x.length === 2. Actual: ' + (x.length)); } -//CHECK#3 if (x[0] !== 0) { throw new Test262Error('#3: var x = [0,1]; var arr = x.splice(0,Number.NEGATIVE_INFINITY); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#4 if (x[1] !== 1) { throw new Test262Error('#4: var x = [0,1]; var arr = x.splice(0,Number.NEGATIVE_INFINITY); x[1] === 1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T5.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T5.js index 97bf48bba3d3..94c5ddcb7371 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T5.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2.2_T5.js @@ -17,38 +17,31 @@ var arr = x.splice(0, { } }); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var x = [0,1,2,3]; var arr = x.splice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var x = [0,1,2,3]; var arr = x.splice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var x = [0,1,2,3]; var arr = x.splice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var x = [0,1,2,3]; var arr = x.splice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var x = [0,1,2,3]; var arr = x.splice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (x.length !== 1) { throw new Test262Error('#6: var x = [0,1,2,3]; var arr = x.splice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); x.length === 1. Actual: ' + (x.length)); } -//CHECK#7 if (x[0] !== 3) { throw new Test262Error('#7: var x = [0,1,2,3]; var arr = x.splice(0,{valueOf: function() {return 3}, toString: function() {return 0}}); x[0] === 3. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T1.js index 99865e166027..dfaffa940984 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T1.js @@ -21,53 +21,43 @@ obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0, 3, 4, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (obj.length !== 3) { throw new Test262Error('#6: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); obj.length === 3. Actual: ' + (obj.length)); } -//CHECK#7 if (obj[0] !== 4) { throw new Test262Error('#7: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); obj[0] === 4. Actual: ' + (obj[0])); } -//CHECK#8 if (obj[1] !== 5) { throw new Test262Error('#8: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); obj[1] === 5. Actual: ' + (obj[1])); } -//CHECK#9 if (obj[2] !== 3) { throw new Test262Error('#9: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); obj[2] === 3. Actual: ' + (obj[2])); } -//CHECK#10 if (obj[3] !== undefined) { throw new Test262Error('#10: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(0,3,4,5); obj[3] === undefined. Actual: ' + (obj[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T2.js index 9b53a3fce9d1..1bb4505470e6 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T2.js @@ -19,43 +19,35 @@ obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2, -1, 2, 3); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2,-1,2,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2,-1,2,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (obj.length !== 4) { throw new Test262Error('#2: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2,-1,2,3); obj.length === 4. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== 2) { throw new Test262Error('#3: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2,-1,2,3); obj[0] === 2. Actual: ' + (obj[0])); } -//CHECK#4 if (obj[1] !== 3) { throw new Test262Error('#4: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2,-1,2,3); obj[1] === 3. Actual: ' + (obj[1])); } -//CHECK#5 if (obj[2] !== 0) { throw new Test262Error('#5: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2,-1,2,3); obj[2] === 0. Actual: ' + (obj[2])); } -//CHECK#6 if (obj[3] !== 1) { throw new Test262Error('#6: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2,-1,2,3); obj[3] === 1. Actual: ' + (obj[3])); } -//CHECK#7 if (obj[4] !== undefined) { throw new Test262Error('#7: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(-2,-1,2,3); obj[4] === undefined. Actual: ' + (obj[4])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T3.js index f7e6e15f72d2..b884daa1e7cd 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T3.js @@ -19,43 +19,35 @@ obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0, -1, 2, 3); -//CHECK#0 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#0: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0,-1,2,3); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0,-1,2,3); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (obj.length !== 4) { throw new Test262Error('#2: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0,-1,2,3); obj.length === 4. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== 2) { throw new Test262Error('#3: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0,-1,2,3); obj[0] === 2. Actual: ' + (obj[0])); } -//CHECK#4 if (obj[1] !== 3) { throw new Test262Error('#4: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0,-1,2,3); obj[1] === 3. Actual: ' + (obj[1])); } -//CHECK#5 if (obj[2] !== 0) { throw new Test262Error('#5: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0,-1,2,3); obj[2] === 0. Actual: ' + (obj[2])); } -//CHECK#6 if (obj[3] !== 1) { throw new Test262Error('#6: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0,-1,2,3); obj[3] === 1. Actual: ' + (obj[3])); } -//CHECK#7 if (obj[4] !== undefined) { throw new Test262Error('#7: var obj = {0:0,1:1}; obj.length = 2; obj.splice = Array.prototype.splice; var arr = obj.splice(0,-1,2,3); obj[4] === undefined. Actual: ' + (obj[4])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T4.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T4.js index 2f04099ec54c..b1c9b0a1713f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A2_T4.js @@ -21,53 +21,43 @@ obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4, 3, 4, 5); -//CHECK#1 arr.getClass = Object.prototype.toString; if (arr.getClass() !== "[object " + "Array" + "]") { throw new Test262Error('#1: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); arr is Array object. Actual: ' + (arr.getClass())); } -//CHECK#2 if (arr.length !== 3) { throw new Test262Error('#2: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); arr.length === 3. Actual: ' + (arr.length)); } -//CHECK#3 if (arr[0] !== 0) { throw new Test262Error('#3: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); arr[0] === 0. Actual: ' + (arr[0])); } -//CHECK#4 if (arr[1] !== 1) { throw new Test262Error('#4: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); arr[1] === 1. Actual: ' + (arr[1])); } -//CHECK#5 if (arr[2] !== 2) { throw new Test262Error('#5: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); arr[2] === 2. Actual: ' + (arr[2])); } -//CHECK#6 if (obj.length !== 3) { throw new Test262Error('#6: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); obj.length === 3. Actual: ' + (obj.length)); } -//CHECK#7 if (obj[0] !== 4) { throw new Test262Error('#7: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); obj[0] === 4. Actual: ' + (obj[0])); } -//CHECK#8 if (obj[1] !== 5) { throw new Test262Error('#8: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); obj[1] === 5. Actual: ' + (obj[1])); } -//CHECK#9 if (obj[2] !== 3) { throw new Test262Error('#9: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); obj[2] === 3. Actual: ' + (obj[2])); } -//CHECK#10 if (obj[3] !== undefined) { throw new Test262Error('#10: var obj = {0:0,1:1,2:2,3:3}; obj.length = 4; obj.splice = Array.prototype.splice; var arr = obj.splice(-4,3,4,5); obj[3] === undefined. Actual: ' + (obj[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js index c77b3b34dd12..50ae36021e71 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js @@ -14,27 +14,22 @@ obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.splice(4294967295, 1); -//CHECK#1 if (arr.length !== 1) { throw new Test262Error('#1: var obj = {}; obj.splice = Array.prototype.splice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.splice(4294967295,1); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#2 if (obj.length !== 4294967295) { throw new Test262Error('#2: var obj = {}; obj.splice = Array.prototype.splice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.splice(4294967295,1); obj.length === 4294967295. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== "x") { throw new Test262Error('#3: var obj = {}; obj.splice = Array.prototype.splice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.splice(4294967295,1); obj[0] === "x". Actual: ' + (obj[0])); } -//CHECK#4 if (obj[4294967295] !== undefined) { throw new Test262Error('#4: var obj = {}; obj.splice = Array.prototype.splice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.splice(4294967295,1); obj[4294967295] === undefined. Actual: ' + (obj[4294967295])); } -//CHECK#5 if (arr[0] !== "y") { throw new Test262Error('#5: var obj = {}; obj.splice = Array.prototype.splice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.splice(4294967295,1); arr[0] === "y". Actual: ' + (arr[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A3_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A3_T3.js index 2b00047cdea9..89591be5df8e 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A3_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A3_T3.js @@ -13,22 +13,18 @@ obj[4294967294] = "x"; obj.length = -1; var arr = obj.splice(4294967294, 1); -//CHECK#1 if (arr.length !== 0) { throw new Test262Error('#1: var obj = {}; obj.splice = Array.prototype.splice; obj[4294967294] = "x"; obj.length = -1; var arr = obj.splice(4294967294,1); arr.length === 0. Actual: ' + (arr.length)); } -//CHECK#2 if (arr[0] !== undefined) { throw new Test262Error('#2: var obj = {}; obj.splice = Array.prototype.splice; obj[4294967294] = "x"; obj.length = 1; var arr = obj.splice(4294967294,1); arr[0] === undefined. Actual: ' + (arr[0])); } -//CHECK#3 if (obj.length !== 0) { throw new Test262Error('#3: var obj = {}; obj.splice = Array.prototype.splice; obj[4294967294] = "x"; obj.length = 1; var arr = obj.splice(4294967294,1); obj.length === 0. Actual: ' + (obj.length)); } -//CHECK#4 if (obj[4294967294] !== "x") { throw new Test262Error('#4: var obj = {}; obj.splice = Array.prototype.splice; obj[4294967294] = "x"; obj.length = 1; var arr = obj.splice(4294967294,1); obj[4294967294] === "x". Actual: ' + (obj[4294967294])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T1.js index 888701c4fff7..212c097720b5 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T1.js @@ -13,32 +13,26 @@ Array.prototype[1] = -1; var x = [0, 1]; var arr = x.splice(1, 1); -//CHECK#1 if (arr.length !== 1) { throw new Test262Error('#1: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#2 if (arr[0] !== 1) { throw new Test262Error('#2: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#3 if (arr[1] !== -1) { throw new Test262Error('#3: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1); arr[1] === -1. Actual: ' + (arr[1])); } -//CHECK#4 if (x.length !== 1) { throw new Test262Error('#4: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1); x.length === 1. Actual: ' + (x.length)); } -//CHECK#5 if (x[0] !== 0) { throw new Test262Error('#5: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== -1) { throw new Test262Error('#6: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1); x[1] === -1. Actual: ' + (x[1])); } @@ -53,32 +47,26 @@ x = { }; var arr = x.splice(1, 1); -//CHECK#7 if (arr.length !== 1) { throw new Test262Error('#7: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#8 if (arr[0] !== 1) { throw new Test262Error('#8: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#9 if (arr[1] !== -1) { throw new Test262Error('#9: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1); arr[1] === -1. Actual: ' + (arr[1])); } -//CHECK#10 if (x.length !== 1) { throw new Test262Error('#10: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1); x.length === 1. Actual: ' + (x.length)); } -//CHECK#11 if (x[0] !== 0) { throw new Test262Error('#11: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#12 if (x[1] !== -1) { throw new Test262Error('#12: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1); x[1] === -1. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T2.js index 3595737917ad..e086d7f42ece 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T2.js @@ -13,32 +13,26 @@ Array.prototype[1] = -1; var x = [0, 1]; var arr = x.splice(1, 1, 2); -//CHECK#1 if (arr.length !== 1) { throw new Test262Error('#1: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1,2); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#2 if (arr[0] !== 1) { throw new Test262Error('#2: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1,2); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#3 if (arr[1] !== -1) { throw new Test262Error('#3: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1,2); arr[1] === -1. Actual: ' + (arr[1])); } -//CHECK#4 if (x.length !== 2) { throw new Test262Error('#4: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1,2); x.length === 2. Actual: ' + (x.length)); } -//CHECK#5 if (x[0] !== 0) { throw new Test262Error('#5: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1,2); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#6 if (x[1] !== 2) { throw new Test262Error('#6: Array.prototype[1] = -1; x = [0,1]; var arr = x.splice(1,1,2); x[1] === 2. Actual: ' + (x[1])); } @@ -53,32 +47,26 @@ x = { }; var arr = x.splice(1, 1, 2); -//CHECK#7 if (arr.length !== 1) { throw new Test262Error('#7: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1,2); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#8 if (arr[0] !== 1) { throw new Test262Error('#8: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1,2); arr[0] === 1. Actual: ' + (arr[0])); } -//CHECK#9 if (arr[1] !== -1) { throw new Test262Error('#9: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1,2); arr[1] === -1. Actual: ' + (arr[1])); } -//CHECK#10 if (x.length !== 2) { throw new Test262Error('#10: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1,2); x.length === 2. Actual: ' + (x.length)); } -//CHECK#11 if (x[0] !== 0) { throw new Test262Error('#11: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1,2); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#12 if (x[1] !== 2) { throw new Test262Error('#12: Object.prototype[1] = -1; Object.prototype.length = 2; Object.prototype.splice = Array.prototype.splice; x = {0:0, 1:1}; var arr = x.splice(1,1,2); x[1] === 2. Actual: ' + (x[1])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T3.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T3.js index aab3b1027489..e4ea0ce90478 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A4_T3.js @@ -14,29 +14,24 @@ var x = []; x.length = 1; var arr = x.splice(0, 1); -//CHECK#1 if (arr.length !== 1) { throw new Test262Error('#1: Array.prototype[0] = -1; x = []; x.length = 1; var arr = x.splice(0,1); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#2 if (arr[0] !== -1) { throw new Test262Error('#2: Array.prototype[0] = -1; x = []; x.length = 1; var arr = x.splice(0,1); arr[0] === -1. Actual: ' + (arr[0])); } delete arr[0]; -//CHECK#3 if (arr[0] !== -1) { throw new Test262Error('#3: Array.prototype[0] = -1; x = []; x.length = 1; var arr = x.splice(0,1); delete arr[0]; arr[0] === -1. Actual: ' + (arr[0])); } -//CHECK#4 if (x.length !== 0) { throw new Test262Error('#4: Array.prototype[0] = -1; x = []; x.length = 1; var arr = x.splice(0,1); x.length === 0. Actual: ' + (x.length)); } -//CHECK#5 if (x[0] !== -1) { throw new Test262Error('#5: Array.prototype[0] = -1; x = []; x.length = 1; var arr = x.splice(0,1); x[0] === -1. Actual: ' + (x[0])); } @@ -47,29 +42,24 @@ Object.prototype.splice = Array.prototype.splice; x = {}; var arr = x.splice(0, 1); -//CHECK#6 if (arr.length !== 1) { throw new Test262Error('#6: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.splice = Array.prototype.splice; x = {}; var arr = x.splice(0,1); arr.length === 1. Actual: ' + (arr.length)); } -//CHECK#7 if (arr[0] !== -1) { throw new Test262Error('#7: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.splice = Array.prototype.splice; x = {}; var arr = x.splice(0,1); arr[0] === -1. Actual: ' + (arr[0])); } delete arr[0]; -//CHECK#8 if (arr[0] !== -1) { throw new Test262Error('#8: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.splice = Array.prototype.splice; x = {}; var arr = x.splice(0,1); delete arr[0]; arr[0] === -1. Actual: ' + (arr[0])); } -//CHECK#9 if (x.length !== 0) { throw new Test262Error('#9: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.splice = Array.prototype.splice; x = {}; var arr = x.splice(0,1); x.length === 0. Actual: ' + (x.length)); } -//CHECK#10 if (x[0] !== -1) { throw new Test262Error('#10: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.splice = Array.prototype.splice; x = {}; var arr = x.splice(0,1); x[0] === -1. Actual: ' + (x[0])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A5.7.js b/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A5.7.js deleted file mode 100644 index 6d40a0bc5379..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/splice/S15.4.4.12_A5.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The splice property of Array can't be used as constructor -esid: sec-array.prototype.splice -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.splice(); - throw new Test262Error('#1.1: new Array.prototype.splice() throw TypeError. Actual: ' + (new Array.prototype.splice())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.splice() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A1_T1.js index e87dfd789c9c..1a068ed5ac24 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A1_T1.js @@ -21,7 +21,6 @@ var obj = { var arr = [undefined, obj, null, obj, obj]; arr.toLocaleString(); -//CHECK#1 if (n !== 3) { throw new Test262Error('#1: var n = 0; var obj = {toLocaleString: function() {n++}}; var arr = [undefined, obj, null, obj, obj]; arr.toLocaleString(); n === 3. Actual: ' + (n)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A3_T1.js index 58ed1a12b2ea..a7f0796792a5 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A3_T1.js @@ -8,7 +8,6 @@ es5id: 15.4.4.3_A3_T1 description: "[[Prototype]] of Array instance is Array.prototype" ---*/ -//CHECK#1 var n = 0; var obj = { toLocaleString: function() { diff --git a/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A4.7.js b/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A4.7.js deleted file mode 100644 index 0a84fea0b542..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A4.7.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-array.prototype.tolocalestring -info: The toLocaleString property of Array can't be used as constructor -es5id: 15.4.4.3_A4.7 -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.toLocaleString(); - throw new Test262Error('#1.1: new Array.prototype.toLocaleString() throw TypeError. Actual: ' + (new Array.prototype.toLocaleString())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.toLocaleString() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T1.js index 253a5db609a1..37a3adeced2f 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T1.js @@ -10,7 +10,6 @@ es5id: 15.4.4.2_A1_T1 description: If Result(2) is zero, return the empty string ---*/ -//CHECK#1 var x = new Array(); if (x.toString() !== x.join()) { throw new Test262Error('#1.1: x = new Array(); x.toString() === x.join(). Actual: ' + (x.toString())); @@ -20,7 +19,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#2 x = []; x[0] = 1; x.length = 0; diff --git a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T2.js index f2fa1dabf44f..8a6b4f74ad44 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T2.js @@ -14,7 +14,6 @@ description: > the separator ---*/ -//CHECK#1 var x = new Array(0, 1, 2, 3); if (x.toString() !== x.join()) { throw new Test262Error('#1.1: x = new Array(0,1,2,3); x.toString() === x.join(). Actual: ' + (x.toString())); @@ -24,7 +23,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#2 x = []; x[0] = 0; x[3] = 3; @@ -36,7 +34,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#3 x = Array(undefined, 1, null, 3); if (x.toString() !== x.join()) { throw new Test262Error('#3.1: x = Array(undefined,1,null,3); x.toString() === x.join(). Actual: ' + (x.toString())); @@ -46,7 +43,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#4 x = []; x[0] = 0; if (x.toString() !== x.join()) { diff --git a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T3.js b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T3.js index 9936b43a21e9..2671bc767c87 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T3.js @@ -10,7 +10,6 @@ es5id: 15.4.4.2_A1_T3 description: Operator use ToString from array arguments ---*/ -//CHECK#0 var x = new Array("", "", ""); if (x.toString() !== x.join()) { throw new Test262Error('#0.1: var x = new Array("","",""); x.toString() === x.join(). Actual: ' + (x.toString())); @@ -20,7 +19,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#1 var x = new Array("\\", "\\", "\\"); if (x.toString() !== x.join()) { throw new Test262Error('#1.1: var x = new Array("\\","\\","\\"); x.toString() === x.join(). Actual: ' + (x.toString())); @@ -30,7 +28,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#2 var x = new Array("&", "&", "&"); if (x.toString() !== x.join()) { throw new Test262Error('#2.1: var x = new Array("&", "&", "&"); x.toString() === x.join(). Actual: ' + (x.toString())); @@ -40,7 +37,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#3 var x = new Array(true, true, true); if (x.toString() !== x.join()) { throw new Test262Error('#3.1: var x = new Array(true,true,true); x.toString(true,true,true) === x.join(). Actual: ' + (x.toString(true, true, true))); @@ -50,7 +46,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#4 var x = new Array(null, null, null); if (x.toString() !== x.join()) { throw new Test262Error('#4.1: var x = new Array(null,null,null); x.toString(null,null,null) === x.join(). Actual: ' + (x.toString(null, null, null))); @@ -60,7 +55,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#5 var x = new Array(undefined, undefined, undefined); if (x.toString() !== x.join()) { throw new Test262Error('#5.1: var x = new Array(undefined,undefined,undefined); x.toString(undefined,undefined,undefined) === x.join(). Actual: ' + (x.toString(undefined, undefined, undefined))); @@ -70,7 +64,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#6 var x = new Array(Infinity, Infinity, Infinity); if (x.toString() !== x.join()) { throw new Test262Error('#6.1: var x = new Array(Infinity,Infinity,Infinity); x.toString(Infinity,Infinity,Infinity) === x.join(). Actual: ' + (x.toString(Infinity, Infinity, Infinity))); @@ -80,7 +73,6 @@ if (x.toString() !== x.join()) { } } -//CHECK#7 var x = new Array(NaN, NaN, NaN); if (x.toString() !== x.join()) { throw new Test262Error('#7.1: var x = new Array(NaN,NaN,NaN); x.toString(NaN,NaN,NaN) === x.join(). Actual: ' + (x.toString(NaN, NaN, NaN))); diff --git a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T4.js b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T4.js index 99879af7e502..edf9e63a9b86 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T4.js +++ b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A1_T4.js @@ -10,155 +10,91 @@ es5id: 15.4.4.2_A1_T4 description: If Type(value) is Object, evaluate ToPrimitive(value, String) ---*/ -//CHECK#1 var object = { - valueOf: function() { + valueOf() { return "+" } }; var x = new Array(object); -if (x.toString() !== x.join()) { - throw new Test262Error('#1.1: var object = {valueOf: function() {return "+"}} var x = new Array(object); x.toString() === x.join(). Actual: ' + (x.toString())); -} else { - if (x.toString() !== "[object Object]") { - throw new Test262Error('#1.2: var object = {valueOf: function() {return "+"}} var x = new Array(object); x.toString() === "[object Object]". Actual: ' + (x.toString())); - } -} +assert.sameValue(x.toString(), x.join(), 'x.toString() must return the same value returned by x.join()'); -//CHECK#2 var object = { - valueOf: function() { + valueOf() { return "+" }, - toString: function() { + toString() { return "*" } }; var x = new Array(object); -if (x.toString() !== x.join()) { - throw new Test262Error('#2.1: var object = {valueOf: function() {return "+"}, toString: function() {return x.join()}} var x = new Array(object); x.toString() === "*". Actual: ' + (x.toString())); -} else { - if (x.toString() !== "*") { - throw new Test262Error('#2.2: var object = {valueOf: function() {return "+"}, toString: function() {return "*"}} var x = new Array(object); x.toString() === "*". Actual: ' + (x.toString())); - } -} +assert.sameValue(x.toString(), x.join(), 'x.toString() must return the same value returned by x.join()'); -//CHECK#3 var object = { - valueOf: function() { + valueOf() { return "+" }, - toString: function() { + toString() { return {} } }; var x = new Array(object); -if (x.toString() !== x.join()) { - throw new Test262Error('#3.1: var object = {valueOf: function() {return x.join()}, toString: function() {return {}}} var x = new Array(object); x.toString() === "+". Actual: ' + (x.toString())); -} else { - if (x.toString() !== "+") { - throw new Test262Error('#3.2: var object = {valueOf: function() {return "+"}, toString: function() {return {}}} var x = new Array(object); x.toString() === "+". Actual: ' + (x.toString())); - } -} +assert.sameValue(x.toString(), x.join(), 'x.toString() must return the same value returned by x.join()'); -//CHECK#4 -try { - var object = { - valueOf: function() { - throw "error" - }, - toString: function() { - return "*" - } - }; - var x = new Array(object); - if (x.toString() !== x.join()) { - throw new Test262Error('#4.1: var object = {valueOf: function() {throw "error"}, toString: function() {return x.join()}} var x = new Array(object); x.toString() === "*". Actual: ' + (x.toString())); - } else { - if (x.toString() !== "*") { - throw new Test262Error('#4.2: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}} var x = new Array(object); x.toString() === "*". Actual: ' + (x.toString())); - } - } -} -catch (e) { - if (e === "error") { - throw new Test262Error('#4.3: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}} var x = new Array(object); x.toString() not throw "error"'); - } else { - throw new Test262Error('#4.4: var object = {valueOf: function() {throw "error"}, toString: function() {return "*"}} var x = new Array(object); x.toString() not throw Error. Actual: ' + (e)); - } -} - -//CHECK#5 var object = { - toString: function() { + valueOf() { + throw "error" + }, + toString() { return "*" } }; var x = new Array(object); -if (x.toString() !== x.join()) { - throw new Test262Error('#5.1: var object = {toString: function() {return x.join()}} var x = new Array(object); x.toString() === "*". Actual: ' + (x.toString())); -} else { - if (x.toString() !== "*") { - throw new Test262Error('#5.2: var object = {toString: function() {return "*"}} var x = new Array(object); x.toString() === "*". Actual: ' + (x.toString())); - } -} +assert.sameValue(x.toString(), x.join(), 'x.toString() must return the same value returned by x.join()'); + -//CHECK#6 var object = { - valueOf: function() { + toString() { + return "*" + } +}; +var x = new Array(object); +assert.sameValue(x.toString(), x.join(), 'x.toString() must return the same value returned by x.join()'); + +var object = { + valueOf() { return {} }, - toString: function() { + toString() { return "*" } } var x = new Array(object); -if (x.toString() !== x.join()) { - throw new Test262Error('#6.1: var object = {valueOf: function() {return {}}, toString: function() {return x.join()}} var x = new Array(object); x.toString() === "*". Actual: ' + (x.toString())); -} else { - if (x.toString() !== "*") { - throw new Test262Error('#6.2: var object = {valueOf: function() {return {}}, toString: function() {return "*"}} var x = new Array(object); x.toString() === "*". Actual: ' + (x.toString())); - } -} +assert.sameValue(x.toString(), x.join(), 'x.toString() must return the same value returned by x.join()'); -//CHECK#7 -try { +assert.throws(Test262Error, () => { var object = { - valueOf: function() { + valueOf() { return "+" }, - toString: function() { - throw "error" + toString() { + throw new Test262Error(); } }; var x = new Array(object); x.toString(); - throw new Test262Error('#7.1: var object = {valueOf: function() {return "+"}, toString: function() {throw "error"}} var x = new Array(object); x.toString() throw "error". Actual: ' + (x.toString())); -} -catch (e) { - if (e !== "error") { - throw new Test262Error('#7.2: var object = {valueOf: function() {return "+"}, toString: function() {throw "error"}} var x = new Array(object); x.toString() throw "error". Actual: ' + (e)); - } -} +}); -//CHECK#8 -try { +assert.throws(TypeError, () => { var object = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return {} } }; var x = new Array(object); x.toString(); - throw new Test262Error('#8.1: var object = {valueOf: function() {return {}}, toString: function() {return {}}} var x = new Array(object); x.toString() throw TypeError. Actual: ' + (x.toString())); -} -catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#8.2: var object = {valueOf: function() {return {}}, toString: function() {return {}}} var x = new Array(object); x.toString() throw TypeError. Actual: ' + (e)); - } -} +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A3_T1.js b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A3_T1.js index 11f6ec896f98..9c7b41558f46 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A3_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A3_T1.js @@ -8,7 +8,6 @@ es5id: 15.4.4.2_A3_T1 description: "[[Prototype]] of Array instance is Array.prototype" ---*/ -//CHECK#1 Array.prototype[1] = 1; var x = [0]; x.length = 2; diff --git a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A4.7.js b/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A4.7.js deleted file mode 100644 index f48022de974e..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/toString/S15.4.4.2_A4.7.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-array.prototype.tostring -info: The toString property of Array can't be used as constructor -es5id: 15.4.4.2_A4.7 -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.toString(); - throw new Test262Error('#1.1: new Array.prototype.toString() throw TypeError. Actual: ' + (new Array.prototype.toString())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.toString() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T1.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T1.js index e39b7c990921..121386346c14 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T1.js @@ -10,46 +10,38 @@ esid: sec-array.prototype.unshift description: Checking case when unsift is given no arguments or one argument ---*/ -//CHECK#1 var x = new Array(); var unshift = x.unshift(1); if (unshift !== 1) { throw new Test262Error('#1: x = new Array(); x.unshift(1) === 1. Actual: ' + (unshift)); } -//CHECK#2 if (x[0] !== 1) { throw new Test262Error('#2: x = new Array(); x.unshift(1); x[0] === 1. Actual: ' + (x[0])); } -//CHECK#3 var unshift = x.unshift(); if (unshift !== 1) { throw new Test262Error('#3: x = new Array(); x.unshift(1); x.unshift() === 1. Actual: ' + (unshift)); } -//CHECK#4 if (x[1] !== undefined) { throw new Test262Error('#4: x = new Array(); x.unshift(1); x.unshift(); x[1] === unedfined. Actual: ' + (x[1])); } -//CHECK#5 var unshift = x.unshift(-1); if (unshift !== 2) { throw new Test262Error('#5: x = new Array(); x.unshift(1); x.unshift(); x.unshift(-1) === 2. Actual: ' + (unshift)); } -//CHECK#6 if (x[0] !== -1) { throw new Test262Error('#6: x = new Array(); x.unshift(1); x.unshift(-1); x[0] === -1. Actual: ' + (x[0])); } -//CHECK#7 if (x[1] !== 1) { throw new Test262Error('#7: x = new Array(); x.unshift(1); x.unshift(-1); x[1] === 1. Actual: ' + (x[1])); } -//CHECK#8 if (x.length !== 2) { throw new Test262Error('#8: x = new Array(); x.unshift(1); x.unshift(); x.unshift(-1); x.length === 2. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T2.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T2.js index ced3a6c6fba0..be04543498ff 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T2.js @@ -10,50 +10,41 @@ esid: sec-array.prototype.unshift description: Checking case when unsift is given many arguments ---*/ -//CHECK#1 var x = []; if (x.length !== 0) { throw new Test262Error('#1: x = []; x.length === 0. Actual: ' + (x.length)); } -//CHECK#2 x[0] = 0; var unshift = x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); if (unshift !== 6) { throw new Test262Error('#2: x = []; x[0] = 0; x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1) === 6. Actual: ' + (unshift)); } -//CHECK#3 if (x[5] !== 0) { throw new Test262Error('#3: x = []; x[0] = 0; x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[5] === 0. Actual: ' + (x[5])); } -//CHECK#4 if (x[0] !== true) { throw new Test262Error('#4: x = []; x[0] = 0; x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[0] === true. Actual: ' + (x[0])); } -//CHECK#5 if (x[1] !== Number.POSITIVE_INFINITY) { throw new Test262Error('#5: x = []; x[0] = 0; x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[1] === Number.POSITIVE_INFINITY. Actual: ' + (x[1])); } -//CHECK#6 if (x[2] !== "NaN") { throw new Test262Error('#6: x = []; x[0] = 0; x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[2] === "NaN". Actual: ' + (x[2])); } -//CHECK#7 if (x[3] !== "1") { throw new Test262Error('#7: x = []; x[0] = 0; x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[3] === "1". Actual: ' + (x[3])); } -//CHECK#8 if (x[4] !== -1) { throw new Test262Error('#8: x = []; x[0] = 0; x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x[4] === -1. Actual: ' + (x[4])); } -//CHECK#9 if (x.length !== 6) { throw new Test262Error('#9: x = []; x[0] = 0; x.unshift(true, Number.POSITIVE_INFINITY, "NaN", "1", -1); x.length === 6. Actual: ' + (x.length)); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T1.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T1.js index 91faf96fc3b5..272764f70ddd 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T1.js @@ -18,51 +18,42 @@ obj.unshift = Array.prototype.unshift; if (obj.length !== undefined) { throw new Test262Error('#0: var obj = {}; obj.length === undefined. Actual: ' + (obj.length)); } else { - //CHECK#1 - var unshift = obj.unshift(-1); + var unshift = obj.unshift(-1); if (unshift !== 1) { throw new Test262Error('#1: var obj = {}; obj.unshift = Array.prototype.unshift; obj.unshift(-1) === 1. Actual: ' + (unshift)); } - //CHECK#2 - if (obj.length !== 1) { + if (obj.length !== 1) { throw new Test262Error('#2: var obj = {}; obj.unshift = Array.prototype.unshift; obj.unshift(-1); obj.length === 1. Actual: ' + (obj.length)); } - //CHECK#3 - if (obj["0"] !== -1) { + if (obj["0"] !== -1) { throw new Test262Error('#3: var obj = {}; obj.unshift = Array.prototype.unshift; obj.unshift(-1); obj["0"] === -1. Actual: ' + (obj["0"])); } } -//CHECK#4 obj.length = undefined; var unshift = obj.unshift(-4); if (unshift !== 1) { throw new Test262Error('#4: var obj = {}; obj.length = undefined; obj.unshift = Array.prototype.unshift; obj.unshift(-4) === 1. Actual: ' + (unshift)); } -//CHECK#5 if (obj.length !== 1) { throw new Test262Error('#5: var obj = {}; obj.length = undefined; obj.unshift = Array.prototype.unshift; obj.unshift(-4); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#6 if (obj["0"] !== -4) { throw new Test262Error('#6: var obj = {}; obj.length = undefined; obj.unshift = Array.prototype.unshift; obj.unshift(-4); obj["0"] === -4. Actual: ' + (obj["0"])); } -//CHECK#7 obj.length = null var unshift = obj.unshift(-7); if (unshift !== 1) { throw new Test262Error('#7: var obj = {}; obj.length = null; obj.unshift = Array.prototype.unshift; obj.unshift(-7) === 1. Actual: ' + (unshift)); } -//CHECK#8 if (obj.length !== 1) { throw new Test262Error('#8: var obj = {}; obj.length = null; obj.unshift = Array.prototype.unshift; obj.unshift(-7); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#9 if (obj["0"] !== -7) { throw new Test262Error('#9: var obj = {}; obj.length = null; obj.unshift = Array.prototype.unshift; obj.unshift(-7); obj["0"] === -7. Actual: ' + (obj["0"])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T2.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T2.js index 0f76bb2dc58a..152ab6e2478d 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T2.js @@ -15,87 +15,72 @@ description: > var obj = {}; obj.unshift = Array.prototype.unshift; -//CHECK#1 obj.length = NaN; var unshift = obj.unshift(-1); if (unshift !== 1) { throw new Test262Error('#1: var obj = {}; obj.length = NaN; obj.unshift = Array.prototype.unshift; obj.unshift(-1) === 1. Actual: ' + (unshift)); } -//CHECK#2 if (obj.length !== 1) { throw new Test262Error('#2: var obj = {}; obj.length = NaN; obj.unshift = Array.prototype.unshift; obj.unshift(-1); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#3 if (obj["0"] !== -1) { throw new Test262Error('#3: var obj = {}; obj.length = NaN; obj.unshift = Array.prototype.unshift; obj.unshift(-1); obj["0"] === -1. Actual: ' + (obj["0"])); } -//CHECK#7 obj.length = Number.NEGATIVE_INFINITY; var unshift = obj.unshift(-7); if (unshift !== 1) { throw new Test262Error('#7: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.unshift = Array.prototype.unshift; obj.unshift(-7) === 1. Actual: ' + (unshift)); } -//CHECK#8 if (obj.length !== 1) { throw new Test262Error('#8: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.unshift = Array.prototype.unshift; obj.unshift(-7); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#9 if (obj["0"] !== -7) { throw new Test262Error('#9: var obj = {}; obj.length = Number.NEGATIVE_INFINITY; obj.unshift = Array.prototype.unshift; obj.unshift(-7); obj["0"] === -7. Actual: ' + (obj["0"])); } -//CHECK#10 obj.length = 0.5; var unshift = obj.unshift(-10); if (unshift !== 1) { throw new Test262Error('#10: var obj = {}; obj.length = 0.5; obj.unshift = Array.prototype.unshift; obj.unshift(-10) === 1. Actual: ' + (unshift)); } -//CHECK#11 if (obj.length !== 1) { throw new Test262Error('#11: var obj = {}; obj.length = 0.5; obj.unshift = Array.prototype.unshift; obj.unshift(-10); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#12 if (obj["0"] !== -10) { throw new Test262Error('#12: var obj = {}; obj.length = 0.5; obj.unshift = Array.prototype.unshift; obj.unshift(-10); obj["0"] === -10. Actual: ' + (obj["0"])); } -//CHECK#13 obj.length = 1.5; var unshift = obj.unshift(-13); if (unshift !== 2) { throw new Test262Error('#13: var obj = {}; obj.length = 1.5; obj.unshift = Array.prototype.unshift; obj.unshift(-13) === 2. Actual: ' + (unshift)); } -//CHECK#14 if (obj.length !== 2) { throw new Test262Error('#14: var obj = {}; obj.length = 1.5; obj.unshift = Array.prototype.unshift; obj.unshift(-13); obj.length === 2. Actual: ' + (obj.length)); } -//CHECK#15 if (obj["0"] !== -13) { throw new Test262Error('#15: var obj = {}; obj.length = 1.5; obj.unshift = Array.prototype.unshift; obj.unshift(-13); obj["0"] === -13. Actual: ' + (obj["0"])); } -//CHECK#16 obj.length = new Number(0); var unshift = obj.unshift(-16); if (unshift !== 1) { throw new Test262Error('#16: var obj = {}; obj.length = new Number(0); obj.unshift = Array.prototype.unshift; obj.unshift(-16) === 1. Actual: ' + (unshift)); } -//CHECK#17 if (obj.length !== 1) { throw new Test262Error('#17: var obj = {}; obj.length = new Number(0); obj.unshift = Array.prototype.unshift; obj.unshift(-16); obj.length === 1. Actual: ' + (obj.length)); } -//CHECK#18 if (obj["0"] !== -16) { throw new Test262Error('#18: var obj = {}; obj.length = new Number(0); obj.unshift = Array.prototype.unshift; obj.unshift(-16); obj["0"] === -16. Actual: ' + (obj["0"])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T3.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T3.js index ec30e2f716df..8979724e9b88 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T3.js +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A2_T3.js @@ -14,131 +14,107 @@ description: > var obj = {}; obj.unshift = Array.prototype.unshift; -//CHECK#1 obj.length = { - valueOf: function() { + valueOf() { return 3 } }; var unshift = obj.unshift(); -if (unshift !== 3) { - throw new Test262Error('#1: obj.length = {valueOf: function() {return 3}} obj.unshift() === 3. Actual: ' + (unshift)); -} +assert.sameValue(unshift, 3, 'The value of unshift is expected to be 3'); -//CHECK#2 obj.length = { - valueOf: function() { + valueOf() { return 3 }, - toString: function() { + toString() { return 1 } }; var unshift = obj.unshift(); -if (unshift !== 3) { - throw new Test262Error('#0: obj.length = {valueOf: function() {return 3}, toString: function() {return 1}} obj.unshift() === 3. Actual: ' + (unshift)); -} +assert.sameValue(unshift, 3, 'The value of unshift is expected to be 3'); -//CHECK#3 obj.length = { - valueOf: function() { + valueOf() { return 3 }, - toString: function() { + toString() { return {} } }; var unshift = obj.unshift(); -if (unshift !== 3) { - throw new Test262Error('#1: obj.length = {valueOf: function() {return 3}, toString: function() {return {}}} obj.unshift() === 3. Actual: ' + (unshift)); -} +assert.sameValue(unshift, 3, 'The value of unshift is expected to be 3'); -//CHECK#4 try { obj.length = { - valueOf: function() { + valueOf() { return 3 }, - toString: function() { + toString() { throw "error" } }; var unshift = obj.unshift(); - if (unshift !== 3) { - throw new Test262Error('#4.1: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.unshift() === ",". Actual: ' + (unshift)); - } + assert.sameValue(unshift, 3, 'The value of unshift is expected to be 3'); } catch (e) { - if (e === "error") { - throw new Test262Error('#4.2: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.unshift() not throw "error"'); - } else { - throw new Test262Error('#4.3: obj.length = {valueOf: function() {return 3}, toString: function() {throw "error"}}; obj.unshift() not throw Error. Actual: ' + (e)); - } + assert.notSameValue(e, "error", 'The value of e is not "error"'); } -//CHECK#5 obj.length = { - toString: function() { + toString() { return 1 } }; var unshift = obj.unshift(); -if (unshift !== 1) { - throw new Test262Error('#5: obj.length = {toString: function() {return 1}} obj.unshift() === 1. Actual: ' + (unshift)); -} +assert.sameValue(unshift, 1, 'The value of unshift is expected to be 1'); -//CHECK#6 obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return 1 } } var unshift = obj.unshift(); -if (unshift !== 1) { - throw new Test262Error('#6: obj.length = {valueOf: function() {return {}}, toString: function() {return 1}} obj.unshift() === 1. Actual: ' + (unshift)); -} +assert.sameValue(unshift, 1, 'The value of unshift is expected to be 1'); -//CHECK#7 try { obj.length = { - valueOf: function() { + valueOf() { throw "error" }, - toString: function() { + toString() { return 1 } }; var unshift = obj.unshift(); - throw new Test262Error('#7.1: obj.length = {valueOf: function() {throw "error"}, toString: function() {return 1}}; obj.unshift() throw "error". Actual: ' + (unshift)); + throw new Test262Error('#7.1: obj.length = {valueOf() {throw "error"}, toString() {return 1}}; obj.unshift() throw "error". Actual: ' + (unshift)); } catch (e) { - if (e !== "error") { - throw new Test262Error('#7.2: obj.length = {valueOf: function() {throw "error"}, toString: function() {return 1}}; obj.unshift() throw "error". Actual: ' + (e)); - } + assert.sameValue(e, "error", 'The value of e is expected to be "error"'); } -//CHECK#8 try { obj.length = { - valueOf: function() { + valueOf() { return {} }, - toString: function() { + toString() { return {} } }; var unshift = obj.unshift(); - throw new Test262Error('#8.1: obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.unshift() throw TypeError. Actual: ' + (unshift)); + throw new Test262Error('#8.1: obj.length = {valueOf() {return {}}, toString() {return {}}} obj.unshift() throw TypeError. Actual: ' + (unshift)); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#8.2: obj.length = {valueOf: function() {return {}}, toString: function() {return {}}} obj.unshift() throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A3_T2.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A3_T2.js index b38ab80704f8..1634da4c16fc 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A3_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A3_T2.js @@ -12,33 +12,27 @@ obj.unshift = Array.prototype.unshift; obj[0] = ""; obj.length = -4294967295; -//CHECK#1 var unshift = obj.unshift("x", "y", "z"); if (unshift !== 3) { throw new Test262Error('#1: var obj = {}; obj.unshift = Array.prototype.unshift; obj[0] = ""; obj.length = -4294967295; obj.unshift("x", "y", "z") === 3. Actual: ' + (unshift)); } -//CHECK#2 if (obj.length !== 3) { throw new Test262Error('#2: var obj = {}; obj.unshift = Array.prototype.unshift; obj[0] = ""; obj.length = -4294967295; obj.unshift("x", "y", "z"); obj.length === 3. Actual: ' + (obj.length)); } -//CHECK#3 if (obj[0] !== "x") { throw new Test262Error('#3: var obj = {}; obj.unshift = Array.prototype.unshift; obj[0] = ""; obj.length = -4294967295; obj.unshift("x", "y", "z"); obj[0] === "x". Actual: ' + (obj[0])); } -//CHECK#4 if (obj[1] !== "y") { throw new Test262Error('#4: var obj = {}; obj.unshift = Array.prototype.unshift; obj[0] = ""; obj.length = -4294967295; obj.unshift("x", "y", "z"); obj[1] === "y". Actual: ' + (obj[1])); } -//CHECK#5 if (obj[2] !== "z") { throw new Test262Error('#5: var obj = {}; obj.unshift = Array.prototype.unshift; obj[0] = ""; obj.length = -4294967295; obj.unshift("x", "y", "z"); obj[2] === "z". Actual: ' + (obj[2])); } -//CHECK#6 if (obj[3] !== undefined) { throw new Test262Error('#6: var obj = {}; obj.unshift = Array.prototype.unshift; obj[0] = ""; obj.length = -4294967295; obj.unshift("x", "y", "z"); obj[3] === undefined. Actual: ' + (obj[3])); } diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A4_T1.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A4_T1.js index e090235854ce..fb0cdeb78e6c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A4_T1.js +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A4_T1.js @@ -13,25 +13,21 @@ Array.prototype[0] = -1; var x = [1]; x.length = 1; -//CHECK#1 var unshift = x.unshift(0); if (unshift !== 2) { throw new Test262Error('#1: Array.prototype[0] = -1; x = [1]; x.length = 1; x.unshift(0) === 2. Actual: ' + (unshift)); } -//CHECK#2 if (x[0] !== 0) { throw new Test262Error('#2: Array.prototype[0] = -1; x = [1]; x.length = 1; x.unshift(0); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== 1) { throw new Test262Error('#3: Array.prototype[0] = -1; x = [1]; x.length = 1; x.unshift(0); x[1] === 1. Actual: ' + (x[1])); } delete x[0]; -//CHECK#4 if (x[0] !== -1) { throw new Test262Error('#4: Array.prototype[0] = -1; x = [1]; x.length = 1; x.unshift(0); delete x[0]; x[0] === -1. Actual: ' + (x[0])); } @@ -43,35 +39,29 @@ x = { 0: 1 }; -//CHECK#5 var unshift = x.unshift(0); if (unshift !== 2) { throw new Test262Error('#5: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {0:0}; x.unshift(0) === 2. Actual: ' + (unshift)); } -//CHECK#6 if (x[0] !== 0) { throw new Test262Error('#6: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {0:0}; x.unshift(0); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#7 if (x[1] !== 1) { throw new Test262Error('#7: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {0:0}; x.unshift(0); x[1] === 1. Actual: ' + (x[1])); } delete x[0]; -//CHECK#8 if (x[0] !== -1) { throw new Test262Error('#8: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {0:0}; x.unshift(0); delete x[0]; x[0] === -1. Actual: ' + (x[0])); } -//CHECK#9 if (x.length !== 2) { throw new Test262Error('#9: Object.prototype[0] = -1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {0:0}; x.unshift(0); x.length === 1. Actual: ' + (x.length)); } -//CHECK#10 delete x.length; if (x.length !== 1) { throw new Test262Error('#10: Object.prototype[1] = -1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {0:0}; x.unshift(0); delete x; x.length === 1. Actual: ' + (x.length)); diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A4_T2.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A4_T2.js index 2e945bb156c6..bc63e8cf668c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A4_T2.js +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A4_T2.js @@ -13,25 +13,21 @@ Array.prototype[0] = 1; var x = []; x.length = 1; -//CHECK#1 var unshift = x.unshift(0); if (unshift !== 2) { throw new Test262Error('#1: Array.prototype[0] = 1; x = []; x.length = 1; x.unshift(0) === 2. Actual: ' + (unshift)); } -//CHECK#2 if (x[0] !== 0) { throw new Test262Error('#2: Array.prototype[0] = 1; x = []; x.length = 1; x.unshift(0); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#3 if (x[1] !== 1) { throw new Test262Error('#3: Array.prototype[0] = 1; x = []; x.length = 1; x.unshift(0); x[1] === 1. Actual: ' + (x[1])); } delete x[0]; -//CHECK#4 if (x[0] !== 1) { throw new Test262Error('#4: Array.prototype[0] = 1; x = [1]; x.length = 1; x.unshift(0); delete x[0]; x[0] === 1. Actual: ' + (x[0])); } @@ -41,35 +37,29 @@ Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {}; -//CHECK#5 var unshift = x.unshift(0); if (unshift !== 2) { throw new Test262Error('#5: Object.prototype[0] = 1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {}; x.unshift(0) === 2. Actual: ' + (unshift)); } -//CHECK#6 if (x[0] !== 0) { throw new Test262Error('#6: Object.prototype[0] = 1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {}; x.unshift(0); x[0] === 0. Actual: ' + (x[0])); } -//CHECK#7 if (x[1] !== 1) { throw new Test262Error('#7: Object.prototype[0] = 1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {}; x.unshift(0); x[1] === 1. Actual: ' + (x[1])); } delete x[0]; -//CHECK#8 if (x[0] !== 1) { throw new Test262Error('#8: Object.prototype[0] = 1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {}; x.unshift(0); delete x[0]; x[0] === 1. Actual: ' + (x[0])); } -//CHECK#9 if (x.length !== 2) { throw new Test262Error('#9: Object.prototype[0] = 1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {}; x.unshift(0); x.length === 1. Actual: ' + (x.length)); } -//CHECK#10 delete x.length; if (x.length !== 1) { throw new Test262Error('#10: Object.prototype[1] = 1; Object.prototype.length = 1; Object.prototype.unshift = Array.prototype.unshift; x = {}; x.unshift(0); delete x; x.length === 1. Actual: ' + (x.length)); diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A5.7.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A5.7.js deleted file mode 100644 index 278ad6ff253d..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/unshift/S15.4.4.13_A5.7.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: The unshift property of Array can't be used as constructor -esid: sec-array.prototype.unshift -description: > - If property does not implement the internal [[Construct]] method, - throw a TypeError exception ----*/ - -//CHECK#1 - -try { - new Array.prototype.unshift(); - throw new Test262Error('#1.1: new Array.prototype.unshift() throw TypeError. Actual: ' + (new Array.prototype.unshift())); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new Array.prototype.unshift() throw TypeError. Actual: ' + (e)); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-array-is-frozen.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-array-is-frozen.js new file mode 100644 index 000000000000..912e021aaafb --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-array-is-frozen.js @@ -0,0 +1,50 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.unshift +description: > + A TypeError is thrown when "length" is [[Set]] on a frozen array. +info: | + Array.prototype.unshift ( ...items ) + + [...] + 4. If argCount > 0, then + [...] + d. Let j be +0𝔽. + e. For each element E of items, do + i. Perform ? Set(O, ! ToString(j), E, true). + ii. Set j to j + 1𝔽. + 5. Perform ? Set(O, "length", 𝔽(len + argCount), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +var arrayPrototypeSet0Calls = 0; + +Object.defineProperty(Array.prototype, "0", { + set(_val) { + Object.freeze(array); + arrayPrototypeSet0Calls++; + }, +}); + +assert.throws(TypeError, function() { + array.unshift(1); +}); + +assert(!array.hasOwnProperty(0)); +assert.sameValue(array.length, 0); +assert.sameValue(arrayPrototypeSet0Calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-array-length-is-non-writable.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-array-length-is-non-writable.js new file mode 100644 index 000000000000..9ce38b5d9364 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-array-length-is-non-writable.js @@ -0,0 +1,50 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.unshift +description: > + A TypeError is thrown when "length" is [[Set]] on an array with non-writable "length". +info: | + Array.prototype.unshift ( ...items ) + + [...] + 4. If argCount > 0, then + [...] + d. Let j be +0𝔽. + e. For each element E of items, do + i. Perform ? Set(O, ! ToString(j), E, true). + ii. Set j to j + 1𝔽. + 5. Perform ? Set(O, "length", 𝔽(len + argCount), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +var arrayPrototypeSet0Calls = 0; + +Object.defineProperty(Array.prototype, "0", { + set(_val) { + Object.defineProperty(array, "length", { writable: false }); + arrayPrototypeSet0Calls++; + }, +}); + +assert.throws(TypeError, function() { + array.unshift(1); +}); + +assert(!array.hasOwnProperty(0)); +assert.sameValue(array.length, 0); +assert.sameValue(arrayPrototypeSet0Calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-zero-array-is-frozen.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-zero-array-is-frozen.js new file mode 100644 index 000000000000..0896cb8a25b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-zero-array-is-frozen.js @@ -0,0 +1,38 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.unshift +description: > + A TypeError is thrown when "length" is [[Set]] on an empty frozen array. +info: | + Array.prototype.unshift ( ...items ) + + [...] + 2. Let len be ? LengthOfArrayLike(O). + [...] + 5. Perform ? Set(O, "length", 𝔽(len + argCount), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +Object.freeze(array); + +assert.throws(TypeError, function() { + array.unshift(); +}); + +assert(!array.hasOwnProperty(0)); +assert.sameValue(array.length, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-zero-array-length-is-non-writable.js b/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-zero-array-length-is-non-writable.js new file mode 100644 index 000000000000..c6fa486c0390 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/unshift/set-length-zero-array-length-is-non-writable.js @@ -0,0 +1,38 @@ +// Copyright (C) 2022 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.unshift +description: > + A TypeError is thrown when "length" is [[Set]] on an empty array with non-writable "length". +info: | + Array.prototype.unshift ( ...items ) + + [...] + 2. Let len be ? LengthOfArrayLike(O). + [...] + 5. Perform ? Set(O, "length", 𝔽(len + argCount), true). + + OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ) + + [...] + 2. If IsDataDescriptor(ownDesc) is true, then + a. If ownDesc.[[Writable]] is false, return false. + + Set ( O, P, V, Throw ) + + [...] + 1. Let success be ? O.[[Set]](P, V, O). + 2. If success is false and Throw is true, throw a TypeError exception. +---*/ + +var array = []; +Object.defineProperty(array, "length", { writable: false }); + +assert.throws(TypeError, function() { + array.unshift(); +}); + +assert(!array.hasOwnProperty(0)); +assert.sameValue(array.length, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T1.js b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T1.js index b805099a620b..c55a7cc8669c 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T1.js @@ -10,25 +10,19 @@ description: > Used values 1, new String("1"), new Object(1) and called without argument ---*/ +assert.sameValue(typeof Boolean(), "boolean", 'The value of `typeof Boolean()` is expected to be "boolean"'); +assert.sameValue(typeof Boolean(1), "boolean", 'The value of `typeof Boolean(1)` is expected to be "boolean"'); -//CHECK#1 -if (typeof Boolean() !== "boolean") { - throw new Test262Error('#1: typeof Boolean() should be "boolean", actual is "' + typeof Boolean() + '"'); -} +assert.sameValue( + typeof Boolean(new String("1")), + "boolean", + 'The value of `typeof Boolean(new String("1"))` is expected to be "boolean"' +); -//CHECK#2 -if (typeof Boolean(1) !== "boolean") { - throw new Test262Error('#2: typeof Boolean(1) should be "boolean", actual is "' + typeof Boolean(1) + '"'); -} - -//CHECK#3 -if (typeof Boolean(new String("1")) !== "boolean") { - throw new Test262Error('#3: typeof Boolean(new String("1")) should be "boolean", actual is "' + typeof Boolean(new String("1")) + '"'); -} - -//CHECK#4 -if (typeof Boolean(new Object(1)) !== "boolean") { - throw new Test262Error('#4: typeof Boolean(new Object(1)) should be "boolean", actual is "' + typeof Boolean(new Object(1)) + '"'); -} +assert.sameValue( + typeof Boolean(new Object(1)), + "boolean", + 'The value of `typeof Boolean(new Object(1))` is expected to be "boolean"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T2.js b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T2.js index b72381aeaff0..83fd28fca6d5 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T2.js @@ -8,37 +8,19 @@ info: | esid: sec-terms-and-definitions-boolean-value description: Used various number values as argument ---*/ +assert.sameValue(typeof Boolean(0), "boolean", 'The value of `typeof Boolean(0)` is expected to be "boolean"'); +assert.sameValue(Boolean(0), false, 'Boolean(0) must return false'); +assert.sameValue(typeof Boolean(-1), "boolean", 'The value of `typeof Boolean(-1)` is expected to be "boolean"'); +assert.sameValue(Boolean(-1), true, 'Boolean(-1) must return true'); -//CHECK#1 -if (typeof Boolean(0) !== "boolean") { - throw new Test262Error('#1.1: typeof Boolean(0) should be "boolean", actual is "' + typeof Boolean(0) + '"'); -} -if (Boolean(0) !== false) { - throw new Test262Error('#1.2: Boolean(0) should be false, actual is ' + Boolean(0)); -} +assert.sameValue( + typeof Boolean(-Infinity), + "boolean", + 'The value of `typeof Boolean(-Infinity)` is expected to be "boolean"' +); -//CHECK#2 -if (typeof Boolean(-1) !== "boolean") { - throw new Test262Error('#2.1: typeof Boolean(-1) should be "boolean", actual is "' + typeof Boolean(-1) + '"'); -} -if (Boolean(-1) !== true) { - throw new Test262Error('#2.2: Boolean(-1) should be true, actual is ' + Boolean(-1)); -} - -//CHECK#3 -if (typeof Boolean(-Infinity) !== "boolean") { - throw new Test262Error('#3.1: typeof Boolean(-Infinity) should be "boolean", actual is "' + typeof Boolean(-Infinity) + '"'); -} -if (Boolean(-Infinity) !== true) { - throw new Test262Error('#3.2: Boolean(-Infinity) should be true, actual is ' + Boolean(-Infinity)); -} - -//CHECK#4 -if (typeof Boolean(NaN) !== "boolean") { - throw new Test262Error('#4.1: typeof Boolean(NaN) should be "boolean", actual is "' + typeof Boolean(NaN) + '"'); -} -if (Boolean(NaN) !== false) { - throw new Test262Error('#4.2: Boolean(NaN) should be false, actual is ' + Boolean(NaN)); -} +assert.sameValue(Boolean(-Infinity), true, 'Boolean(-Infinity) must return true'); +assert.sameValue(typeof Boolean(NaN), "boolean", 'The value of `typeof Boolean(NaN)` is expected to be "boolean"'); +assert.sameValue(Boolean(NaN), false, 'Boolean(NaN) must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T3.js b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T3.js index a26e03f56f75..08be621238c8 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T3.js @@ -1,6 +1,5 @@ // Copyright 2009 the Sputnik authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. - /*--- info: | Returns a boolean value (not a Boolean object) computed by @@ -9,44 +8,27 @@ esid: sec-terms-and-definitions-boolean-value description: Used various string values as argument ---*/ -//CHECK#1 -if (typeof Boolean("0") !== "boolean") { - throw new Test262Error('#1.1: typeof Boolean("0") should be "boolean", actual is "' + typeof Boolean("0") + '"'); -} -if (Boolean("0") !== true) { - throw new Test262Error('#1.2: Boolean("0") should be true'); -} +assert.sameValue(typeof Boolean("0"), "boolean", 'The value of `typeof Boolean("0")` is expected to be "boolean"'); +assert.sameValue(Boolean("0"), true, 'Boolean("0") must return true'); +assert.sameValue(typeof Boolean("-1"), "boolean", 'The value of `typeof Boolean("-1")` is expected to be "boolean"'); +assert.sameValue(Boolean("-1"), true, 'Boolean("-1") must return true'); +assert.sameValue(typeof Boolean("1"), "boolean", 'The value of `typeof Boolean("1")` is expected to be "boolean"'); +assert.sameValue(Boolean("1"), true, 'Boolean("1") must return true'); -//CHECK#2 -if (typeof Boolean("-1") !== "boolean") { - throw new Test262Error('#2.1: typeof Boolean("-1") should be "boolean", actual is "' + typeof Boolean("-1") + '"'); -} -if (Boolean("-1") !== true) { - throw new Test262Error('#2.2: Boolean("-1") should be true'); -} +assert.sameValue( + typeof Boolean("false"), + "boolean", + 'The value of `typeof Boolean("false")` is expected to be "boolean"' +); -//CHECK#3 -if (typeof Boolean("1") !== "boolean") { - throw new Test262Error('#3.1: typeof Boolean("1") should be "boolean", actual is "' + typeof Boolean("1") + '"'); -} -if (Boolean("1") !== true) { - throw new Test262Error('#3.2: Boolean("1") should be true'); -} +assert.sameValue(Boolean("false"), true, 'Boolean("false") must return true'); -//CHECK#4 -if (typeof Boolean("false") !== "boolean") { - throw new Test262Error('#4.1: typeof Boolean("false") should be "boolean", actual is "' + typeof Boolean("false") + '"'); -} -if (Boolean("false") !== true) { - throw new Test262Error('#4.2: Boolean("false") should be true'); -} +assert.sameValue( + typeof Boolean("true"), + "boolean", + 'The value of `typeof Boolean("true")` is expected to be "boolean"' +); -//CHECK#5 -if (typeof Boolean("true") !== "boolean") { - throw new Test262Error('#5.1: typeof Boolean("true") should be "boolean", actual is "' + typeof Boolean("true") + '"'); -} -if (Boolean("true") !== true) { - throw new Test262Error('#5.2: Boolean("true") should be true'); -} +assert.sameValue(Boolean("true"), true, 'Boolean("true") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T4.js b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T4.js index 6931f30cddd0..d52fb031da08 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T4.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T4.js @@ -9,45 +9,33 @@ esid: sec-terms-and-definitions-boolean-value description: Used various undefined values and null as argument ---*/ -//CHECK#1 -if (typeof Boolean(undefined) !== "boolean") { - throw new Test262Error('#1.1: typeof Boolean(undefined) should be "boolean", actual is "' + typeof Boolean(undefined) + '"'); -} -if (Boolean(undefined) !== false) { - throw new Test262Error('#1.2: Boolean(undefined) should be false'); -} +assert.sameValue( + typeof Boolean(undefined), + "boolean", + 'The value of `typeof Boolean(undefined)` is expected to be "boolean"' +); -//CHECK#2 -if (typeof Boolean(void 0) !== "boolean") { - throw new Test262Error('#2.1: typeof Boolean(void 0) should be "boolean", actual is "' + typeof Boolean(void 0) + '"'); -} -if (Boolean(void 0) !== false) { - throw new Test262Error('#2.2: Boolean(void 0) should be false'); -} +assert.sameValue(Boolean(undefined), false, 'Boolean(undefined) must return false'); -//CHECK#3 -if (typeof Boolean(function() {}()) !== "boolean") { - throw new Test262Error('#3.1: typeof Boolean(function(){}()) should be "boolean", actual is "' + typeof Boolean(function() {}()) + '"'); -} -if (Boolean(function() {}()) !== false) { - throw new Test262Error('#3.2: Boolean(function(){}()) should be false'); -} +assert.sameValue( + typeof Boolean(void 0), + "boolean", + 'The value of `typeof Boolean(void 0)` is expected to be "boolean"' +); -//CHECK#4 -if (typeof Boolean(null) !== "boolean") { - throw new Test262Error('#4.1: typeof Boolean(null) should be "boolean", actual is "' + typeof Boolean(null) + '"'); -} -if (Boolean(null) !== false) { - throw new Test262Error('#4.2: Boolean(null) should be false'); -} +assert.sameValue(Boolean(void 0), false, 'Boolean(void 0) must return false'); -//CHECK#5 -if (typeof Boolean(x) !== "boolean") { - throw new Test262Error('#5.1: var x; typeof Boolean(x) should be "boolean", actual is "' + typeof Boolean(x) + '"'); -} -if (Boolean(x) !== false) { - throw new Test262Error('#5.2: var x; Boolean(x) should be false'); -} +assert.sameValue( + typeof Boolean(function() {}()), + "boolean", + 'The value of `typeof Boolean(function() {}())` is expected to be "boolean"' +); + +assert.sameValue(Boolean(function() {}()), false, 'Boolean(function() {}()) must return false'); +assert.sameValue(typeof Boolean(null), "boolean", 'The value of `typeof Boolean(null)` is expected to be "boolean"'); +assert.sameValue(Boolean(null), false, 'Boolean(null) must return false'); +assert.sameValue(typeof Boolean(x), "boolean", 'The value of `typeof Boolean(x)` is expected to be "boolean"'); +assert.sameValue(Boolean(x), false, 'Boolean() must return false'); var x; reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T5.js b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T5.js index f2b3198ded26..0bb2c7f4970d 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T5.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A1_T5.js @@ -11,44 +11,33 @@ description: Used various assigning values to any variable as argument var x; -//CHECK#1 -if (typeof Boolean(x = 0) !== "boolean") { - throw new Test262Error('#1.1: typeof Boolean(x=0) should be "boolean", actual is "' + typeof Boolean(x = 0) + '"'); -} -if (Boolean(x = 0) !== false) { - throw new Test262Error('#1.2: Boolean(x=0) should be false'); -} +assert.sameValue(typeof Boolean(x = 0), "boolean", 'The value of `typeof Boolean(x = 0)` is expected to be "boolean"'); +assert.sameValue(Boolean(x = 0), false, 'Boolean(x = 0) must return false'); +assert.sameValue(typeof Boolean(x = 1), "boolean", 'The value of `typeof Boolean(x = 1)` is expected to be "boolean"'); +assert.sameValue(Boolean(x = 1), true, 'Boolean(x = 1) must return true'); -//CHECK#2 -if (typeof Boolean(x = 1) !== "boolean") { - throw new Test262Error('#2.1: typeof Boolean(x=1) should be "boolean", actual is "' + typeof Boolean(x = 1) + '"'); -} -if (Boolean(x = 1) !== true) { - throw new Test262Error('#2.2: Boolean(x=1) should be true'); -} +assert.sameValue( + typeof Boolean(x = false), + "boolean", + 'The value of `typeof Boolean(x = false)` is expected to be "boolean"' +); -//CHECK#3 -if (typeof Boolean(x = false) !== "boolean") { - throw new Test262Error('#3.1: typeof Boolean(x=false) should be "boolean", actual is "' + typeof Boolean(x = false) + '"'); -} -if (Boolean(x = false) !== false) { - throw new Test262Error('#3.2: Boolean(x=false) should be false'); -} +assert.sameValue(Boolean(x = false), false, 'Boolean(x = false) must return false'); -//CHECK#4 -if (typeof Boolean(x = true) !== "boolean") { - throw new Test262Error('#4.1: typeof Boolean(x=true) should be "boolean", actual is "' + typeof Boolean(x = true) + '"'); -} -if (Boolean(x = true) !== true) { - throw new Test262Error('#4.2: Boolean(x=true) should be true'); -} +assert.sameValue( + typeof Boolean(x = true), + "boolean", + 'The value of `typeof Boolean(x = true)` is expected to be "boolean"' +); -//CHECK#5 -if (typeof Boolean(x = null) !== "boolean") { - throw new Test262Error('#5.1: typeof Boolean(x=null) should be "boolean", actual is "' + typeof Boolean(x = null) + '"'); -} -if (Boolean(x = null) !== false) { - throw new Test262Error('#5.2: Boolean(x=null) should be false'); -} +assert.sameValue(Boolean(x = true), true, 'Boolean(x = true) must return true'); + +assert.sameValue( + typeof Boolean(x = null), + "boolean", + 'The value of `typeof Boolean(x = null)` is expected to be "boolean"' +); + +assert.sameValue(Boolean(x = null), false, 'Boolean(x = null) must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A2.js b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A2.js index 0e845b86e3da..b5e504ce55bf 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A2.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.1.1_A2.js @@ -6,15 +6,7 @@ info: Boolean() returns false esid: sec-terms-and-definitions-boolean-value description: Call Boolean() and check result ---*/ - -//CHECK#1 -if (typeof Boolean() !== "boolean") { - throw new Test262Error('#1: typeof Boolean() should be "boolean", actual is "' + typeof Boolean() + '"'); -} - -//CHECK#2 -if (Boolean() !== false) { - throw new Test262Error('#2: Boolean() should be false'); -} +assert.sameValue(typeof Boolean(), "boolean", 'The value of `typeof Boolean()` is expected to be "boolean"'); +assert.sameValue(Boolean(), false, 'Boolean() must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A1.js b/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A1.js index 332943ed9938..d2de13687600 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A1.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A1.js @@ -9,48 +9,21 @@ esid: sec-boolean-constructor description: Checking type of the newly created object and it value ---*/ -//CHECK#1 -if (typeof new Boolean() !== "object") { - throw new Test262Error("#1: typeof new Boolean() === 'object'"); -} +assert.sameValue(typeof new Boolean(), "object", 'The value of `typeof new Boolean()` is expected to be "object"'); +assert.notSameValue(new Boolean(), undefined, 'new Boolean() is expected to not equal ``undefined``'); -//CHECK#2 -if (new Boolean() === undefined) { - throw new Test262Error("#2: new Boolean() should not be undefined"); -} - -//CHECK#3 var x3 = new Boolean(); -if (typeof x3 !== "object") { - throw new Test262Error("#3: typeof new Boolean() !== 'object'"); -} +assert.sameValue(typeof x3, "object", 'The value of `typeof x3` is expected to be "object"'); -//CHECK#4 var x4 = new Boolean(); -if (x4 === undefined) { - throw new Test262Error("#4: new Boolean() should not be undefined"); -} +assert.notSameValue(x4, undefined, 'The value of x4 is expected to not equal ``undefined``'); +assert.sameValue(typeof new Boolean(1), "object", 'The value of `typeof new Boolean(1)` is expected to be "object"'); +assert.notSameValue(new Boolean(1), undefined, 'new Boolean(1) is expected to not equal ``undefined``'); -//CHECK#5 -if (typeof new Boolean(1) !== "object") { - throw new Test262Error("#5: typeof new Boolean(10) === 'object'"); -} - -//CHECK#6 -if (new Boolean(1) === undefined) { - throw new Test262Error("#6: new Boolean(1) should not be undefined"); -} - -//CHECK#7 var x7 = new Boolean(1); -if (typeof x7 !== "object") { - throw new Test262Error("#7: typeof new Boolean(1) !== 'object'"); -} +assert.sameValue(typeof x7, "object", 'The value of `typeof x7` is expected to be "object"'); -//CHECK#8 var x8 = new Boolean(1); -if (x8 === undefined) { - throw new Test262Error("#8: new Boolean(1) should not be undefined"); -} +assert.notSameValue(x8, undefined, 'The value of x8 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A2.js b/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A2.js index b9351c4f216b..5a31cc11bb56 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A2.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A2.js @@ -12,20 +12,22 @@ description: Checking prototype property of the newly created object // CHECK#1 var x1 = new Boolean(1); -if (typeof x1.constructor.prototype !== "object") { - throw new Test262Error('#1: typeof x1.constructor.prototype === "object"'); -} -//CHECK#2 +assert.sameValue( + typeof x1.constructor.prototype, + "object", + 'The value of `typeof x1.constructor.prototype` is expected to be "object"' +); + var x2 = new Boolean(2); -if (!Boolean.prototype.isPrototypeOf(x2)) { - throw new Test262Error('#2: Boolean.prototype.isPrototypeOf(x2)'); -} +assert(Boolean.prototype.isPrototypeOf(x2), 'Boolean.prototype.isPrototypeOf(x2) must return true'); -//CHECK#3 var x3 = new Boolean(3); -if (Boolean.prototype !== x3.constructor.prototype) { - throw new Test262Error('#3: Boolean.prototype === x3.constructor.prototype'); -} + +assert.sameValue( + Boolean.prototype, + x3.constructor.prototype, + 'The value of Boolean.prototype is expected to equal the value of x3.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A3.js b/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A3.js index f9a94f0754c0..5776bd7a5a3e 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A3.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A3.js @@ -11,26 +11,15 @@ description: Checking value of the newly created object // CHECK#1 var x1 = new Boolean(1); -if (x1.valueOf() !== true) { - throw new Test262Error('#1: var x1 = new Boolean(1); x1.valueOf() === true'); -} +assert.sameValue(x1.valueOf(), true, 'x1.valueOf() must return true'); -//CHECK#2 var x2 = new Boolean(); -if (x2.valueOf() !== false) { - throw new Test262Error('#2: var x2 = new Boolean(); x2.valueOf() === false'); -} +assert.sameValue(x2.valueOf(), false, 'x2.valueOf() must return false'); -//CHECK#3 var x2 = new Boolean(0); -if (x2.valueOf() !== false) { - throw new Test262Error('#3: var x2 = new Boolean(0); x2.valueOf() === false'); -} +assert.sameValue(x2.valueOf(), false, 'x2.valueOf() must return false'); -//CHECK#4 var x2 = new Boolean(new Object()); -if (x2.valueOf() !== true) { - throw new Test262Error('#4: var x2 = new Boolean(new Object()); x2.valueOf() === true'); -} +assert.sameValue(x2.valueOf(), true, 'x2.valueOf() must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A4.js b/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A4.js index fea733f8cfa7..c2695184cb3a 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A4.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.2.1_A4.js @@ -13,9 +13,6 @@ delete Boolean.prototype.toString; var obj = new Boolean(); -//CHECK#1 -if (obj.toString() !== "[object Boolean]") { - throw new Test262Error('#1: The [[Class]] property of the newly constructed object is set to "Boolean"'); -} +assert.sameValue(obj.toString(), "[object Boolean]", 'obj.toString() must return "[object Boolean]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.3_A1.js b/js/src/tests/test262/built-ins/Boolean/S15.6.3_A1.js index 235aa5e7fed6..2ea4b61e28ae 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.3_A1.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.3_A1.js @@ -6,9 +6,6 @@ info: The Boolean constructor has the property "prototype" esid: sec-boolean.prototype description: Checking existence of the property "prototype" ---*/ - -if (!Boolean.hasOwnProperty("prototype")) { - throw new Test262Error('#1: The Boolean constructor has the property "prototype"'); -} +assert(Boolean.hasOwnProperty("prototype"), 'Boolean.hasOwnProperty("prototype") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.3_A2.js b/js/src/tests/test262/built-ins/Boolean/S15.6.3_A2.js index c3c299feb979..a9017ef6dd7a 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.3_A2.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.3_A2.js @@ -8,10 +8,9 @@ info: | esid: sec-boolean.prototype description: Checking prototype of the Boolean constructor ---*/ - -//CHECK#1 -if (!(Function.prototype.isPrototypeOf(Boolean))) { - throw new Test262Error('#1: the value of the internal [[Prototype]] property of the Boolean constructor is the Function prototype object.'); -} +assert( + Function.prototype.isPrototypeOf(Boolean), + 'Function.prototype.isPrototypeOf(Boolean) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S15.6.3_A3.js b/js/src/tests/test262/built-ins/Boolean/S15.6.3_A3.js index e094f579aab5..8b84f5f7b108 100644 --- a/js/src/tests/test262/built-ins/Boolean/S15.6.3_A3.js +++ b/js/src/tests/test262/built-ins/Boolean/S15.6.3_A3.js @@ -6,15 +6,7 @@ info: Boolean constructor has length property whose value is 1 esid: sec-boolean.prototype description: Checking Boolean.length property ---*/ - -//CHECK#1 -if (!Boolean.hasOwnProperty("length")) { - throw new Test262Error('#1: Boolean constructor has length property'); -} - -//CHECK#2 -if (Boolean.length !== 1) { - throw new Test262Error('#2: Boolean constructor length property value is 1'); -} +assert(Boolean.hasOwnProperty("length"), 'Boolean.hasOwnProperty("length") must return true'); +assert.sameValue(Boolean.length, 1, 'The value of Boolean.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S9.2_A1_T1.js b/js/src/tests/test262/built-ins/Boolean/S9.2_A1_T1.js index 8516fbbba066..ef74e43f64b6 100644 --- a/js/src/tests/test262/built-ins/Boolean/S9.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/S9.2_A1_T1.js @@ -9,24 +9,9 @@ description: > transformation ---*/ -// CHECK#1 -if (Boolean(undefined) !== false) { - throw new Test262Error('#1: Boolean(undefined) === false. Actual: ' + (Boolean(undefined))); -} - -// CHECK#2 -if (Boolean(void 0) !== false) { - throw new Test262Error('#2: Boolean(undefined) === false. Actual: ' + (Boolean(undefined))); -} - -// CHECK#3 -if (Boolean(eval("var x")) !== false) { - throw new Test262Error('#3: Boolean(eval("var x")) === false. Actual: ' + (Boolean(eval("var x")))); -} - -// CHECK#4 -if (Boolean() !== false) { - throw new Test262Error('#4: Boolean() === false. Actual: ' + (Boolean())); -} +assert.sameValue(Boolean(undefined), false, 'Boolean(undefined) must return false'); +assert.sameValue(Boolean(void 0), false, 'Boolean(void 0) must return false'); +assert.sameValue(Boolean(eval("var x")), false, 'Boolean(eval("var x")) must return false'); +assert.sameValue(Boolean(), false, 'Boolean() must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S9.2_A2_T1.js b/js/src/tests/test262/built-ins/Boolean/S9.2_A2_T1.js index d2d29d45c107..f35a62eb8f0b 100644 --- a/js/src/tests/test262/built-ins/Boolean/S9.2_A2_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/S9.2_A2_T1.js @@ -6,10 +6,6 @@ info: Result of boolean conversion from null value is false esid: sec-toboolean description: null convert to Boolean by explicit transformation ---*/ - -// CHECK#1 -if (Boolean(null) !== false) { - throw new Test262Error('#1: Boolean(null) === false. Actual: ' + (Boolean(null))); -} +assert.sameValue(Boolean(null), false, 'Boolean(null) must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S9.2_A3_T1.js b/js/src/tests/test262/built-ins/Boolean/S9.2_A3_T1.js index 13e305dd3086..478031caa41e 100644 --- a/js/src/tests/test262/built-ins/Boolean/S9.2_A3_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/S9.2_A3_T1.js @@ -6,15 +6,7 @@ info: Result of boolean conversion from boolean value is no conversion esid: sec-toboolean description: true and false convert to Boolean by explicit transformation ---*/ - -// CHECK#1 -if (Boolean(true) !== true) { - throw new Test262Error('#1: Boolean(true) === true. Actual: ' + (Boolean(true))); -} - -// CHECK#2 -if (Boolean(false) !== false) { - throw new Test262Error('#2: Boolean(false) === false. Actual: ' + (Boolean(false))); -} +assert.sameValue(Boolean(true), true, 'Boolean(true) must return true'); +assert.sameValue(Boolean(false), false, 'Boolean(false) must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S9.2_A4_T1.js b/js/src/tests/test262/built-ins/Boolean/S9.2_A4_T1.js index d40c68cd8a05..1c178f1fa0ae 100644 --- a/js/src/tests/test262/built-ins/Boolean/S9.2_A4_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/S9.2_A4_T1.js @@ -8,20 +8,8 @@ info: | esid: sec-toboolean description: +0, -0 and NaN convert to Boolean by explicit transformation ---*/ - -// CHECK#1 -if (Boolean(+0) !== false) { - throw new Test262Error('#1: Boolean(+0) === false. Actual: ' + (Boolean(+0))); -} - -// CHECK#2 -if (Boolean(-0) !== false) { - throw new Test262Error('#2: Boolean(-0) === false. Actual: ' + (Boolean(-0))); -} - -// CHECK#3 -if (Boolean(Number.NaN) !== false) { - throw new Test262Error('#3: Boolean(Number.NaN) === false. Actual: ' + (Boolean(Number.NaN))); -} +assert.sameValue(Boolean(+0), false, 'Boolean(+0) must return false'); +assert.sameValue(Boolean(-0), false, 'Boolean(-0) must return false'); +assert.sameValue(Boolean(Number.NaN), false, 'Boolean(Number.NaN) must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S9.2_A4_T3.js b/js/src/tests/test262/built-ins/Boolean/S9.2_A4_T3.js index 1f1f2e1b67ae..b357ab9052d8 100644 --- a/js/src/tests/test262/built-ins/Boolean/S9.2_A4_T3.js +++ b/js/src/tests/test262/built-ins/Boolean/S9.2_A4_T3.js @@ -11,45 +11,13 @@ description: > Number.MAX_VALUE, Number.MIN_VALUE and some numbers convert to Boolean by explicit transformation ---*/ - -// CHECK#1 -if (Boolean(Number.POSITIVE_INFINITY) !== true) { - throw new Test262Error('#1: Boolean(+Infinity) === true. Actual: ' + (Boolean(+Infinity))); -} - -// CHECK#2; -if (Boolean(Number.NEGATIVE_INFINITY) !== true) { - throw new Test262Error('#2: Boolean(-Infinity) === true. Actual: ' + (Boolean(-Infinity))); -} - -// CHECK#3 -if (Boolean(Number.MAX_VALUE) !== true) { - throw new Test262Error('#3: Boolean(Number.MAX_VALUE) === true. Actual: ' + (Boolean(Number.MAX_VALUE))); -} - -// CHECK#4 -if (Boolean(Number.MIN_VALUE) !== true) { - throw new Test262Error('#4: Boolean(Number.MIN_VALUE) === true. Actual: ' + (Boolean(Number.MIN_VALUE))); -} - -// CHECK#5 -if (Boolean(13) !== true) { - throw new Test262Error('#5: Boolean(13) === true. Actual: ' + (Boolean(13))); -} - -// CHECK#6 -if (Boolean(-13) !== true) { - throw new Test262Error('#6: Boolean(-13) === true. Actual: ' + (Boolean(-13))); -} - -// CHECK#7 -if (Boolean(1.3) !== true) { - throw new Test262Error('#7: Boolean(1.3) === true. Actual: ' + (Boolean(1.3))); -} - -// CHECK#8 -if (Boolean(-1.3) !== true) { - throw new Test262Error('#8: Boolean(-1.3) === true. Actual: ' + (Boolean(-1.3))); -} +assert.sameValue(Boolean(Number.POSITIVE_INFINITY), true, 'Boolean(Number.POSITIVE_INFINITY) must return true'); +assert.sameValue(Boolean(Number.NEGATIVE_INFINITY), true, 'Boolean(Number.NEGATIVE_INFINITY) must return true'); +assert.sameValue(Boolean(Number.MAX_VALUE), true, 'Boolean(Number.MAX_VALUE) must return true'); +assert.sameValue(Boolean(Number.MIN_VALUE), true, 'Boolean(Number.MIN_VALUE) must return true'); +assert.sameValue(Boolean(13), true, 'Boolean(13) must return true'); +assert.sameValue(Boolean(-13), true, 'Boolean(-13) must return true'); +assert.sameValue(Boolean(1.3), true, 'Boolean(1.3) must return true'); +assert.sameValue(Boolean(-1.3), true, 'Boolean(-1.3) must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S9.2_A5_T1.js b/js/src/tests/test262/built-ins/Boolean/S9.2_A5_T1.js index e0de21cac25b..78111566c99a 100644 --- a/js/src/tests/test262/built-ins/Boolean/S9.2_A5_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/S9.2_A5_T1.js @@ -8,10 +8,6 @@ info: | esid: sec-toboolean description: "\"\" is converted to Boolean by explicit transformation" ---*/ - -// CHECK#1 -if (Boolean("") !== false) { - throw new Test262Error('#1: Boolean("") === false. Actual: ' + (Boolean(""))); -} +assert.sameValue(Boolean(""), false, 'Boolean("") must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S9.2_A5_T3.js b/js/src/tests/test262/built-ins/Boolean/S9.2_A5_T3.js index 58fcfc970b53..3122ff8eeda5 100644 --- a/js/src/tests/test262/built-ins/Boolean/S9.2_A5_T3.js +++ b/js/src/tests/test262/built-ins/Boolean/S9.2_A5_T3.js @@ -8,15 +8,7 @@ info: | esid: sec-toboolean description: Any nonempty string convert to Boolean by explicit transformation ---*/ - -// CHECK#1 -if (Boolean(" ") !== true) { - throw new Test262Error('#1: Boolean(" ") === true. Actual: ' + (Boolean(" "))); -} - -// CHECK#2 -if (Boolean("Nonempty String") !== true) { - throw new Test262Error('#2: Boolean("Nonempty String") === true. Actual: ' + (Boolean("Nonempty String"))); -} +assert.sameValue(Boolean(" "), true, 'Boolean(" ") must return true'); +assert.sameValue(Boolean("Nonempty String"), true, 'Boolean("Nonempty String") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/S9.2_A6_T1.js b/js/src/tests/test262/built-ins/Boolean/S9.2_A6_T1.js index 2ddc2df1815e..bfacbb758a70 100644 --- a/js/src/tests/test262/built-ins/Boolean/S9.2_A6_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/S9.2_A6_T1.js @@ -7,99 +7,35 @@ esid: sec-toboolean description: Different objects convert to Boolean by explicit transformation ---*/ -// CHECK#1 -if (Boolean(new Object()) !== true) { - throw new Test262Error('#1: Boolean(new Object()) === true. Actual: ' + (Boolean(new Object()))); -} +assert.sameValue(Boolean(new Object()), true, 'Boolean(new Object()) must return true'); +assert.sameValue(Boolean(new String("")), true, 'Boolean(new String("")) must return true'); +assert.sameValue(Boolean(new String()), true, 'Boolean(new String()) must return true'); +assert.sameValue(Boolean(new Boolean(true)), true, 'Boolean(new Boolean(true)) must return true'); +assert.sameValue(Boolean(new Boolean(false)), true, 'Boolean(new Boolean(false)) must return true'); +assert.sameValue(Boolean(new Boolean()), true, 'Boolean(new Boolean()) must return true'); +assert.sameValue(Boolean(new Array()), true, 'Boolean(new Array()) must return true'); +assert.sameValue(Boolean(new Number()), true, 'Boolean(new Number()) must return true'); +assert.sameValue(Boolean(new Number(-0)), true, 'Boolean(new Number(-0)) must return true'); +assert.sameValue(Boolean(new Number(0)), true, 'Boolean(new Number(0)) must return true'); +assert.sameValue(Boolean(new Number()), true, 'Boolean(new Number()) must return true'); +assert.sameValue(Boolean(new Number(Number.NaN)), true, 'Boolean(new Number(Number.NaN)) must return true'); +assert.sameValue(Boolean(new Number(-1)), true, 'Boolean(new Number(-1)) must return true'); +assert.sameValue(Boolean(new Number(1)), true, 'Boolean(new Number(1)) must return true'); -// CHECK#2 -if (Boolean(new String("")) !== true) { - throw new Test262Error('#2: Boolean(new String("")) === true. Actual: ' + (Boolean(new String("")))); -} +assert.sameValue( + Boolean(new Number(Number.POSITIVE_INFINITY)), + true, + 'Boolean(new Number(Number.POSITIVE_INFINITY)) must return true' +); -// CHECK#3 -if (Boolean(new String()) !== true) { - throw new Test262Error('#3: Boolean(new String()) === true. Actual: ' + (Boolean(new String()))); -} +assert.sameValue( + Boolean(new Number(Number.NEGATIVE_INFINITY)), + true, + 'Boolean(new Number(Number.NEGATIVE_INFINITY)) must return true' +); -// CHECK#4 -if (Boolean(new Boolean(true)) !== true) { - throw new Test262Error('#4: Boolean(new Boolean(true)) === true. Actual: ' + (Boolean(new Boolean(true)))); -} - -// CHECK#5 -if (Boolean(new Boolean(false)) !== true) { - throw new Test262Error('#5: Boolean(new Boolean(false)) === true. Actual: ' + (Boolean(new Boolean(false)))); -} - -// CHECK#6 -if (Boolean(new Boolean()) !== true) { - throw new Test262Error('#6: Boolean(new Boolean()) === true. Actual: ' + (Boolean(new Boolean()))); -} - -// CHECK#7 -if (Boolean(new Array()) !== true) { - throw new Test262Error('#7: Boolean(new Array()) === true. Actual: ' + (Boolean(new Array()))); -} - -// CHECK#8 -if (Boolean(new Number()) !== true) { - throw new Test262Error('#8: Boolean(new Number()) === true. Actual: ' + (Boolean(new Number()))); -} - -// CHECK#9 -if (Boolean(new Number(-0)) !== true) { - throw new Test262Error('#9: Boolean(new Number(-0)) === true. Actual: ' + (Boolean(new Number(-0)))); -} - -// CHECK#10 -if (Boolean(new Number(0)) !== true) { - throw new Test262Error('#10: Boolean(new Number(0)) === true. Actual: ' + (Boolean(new Number(0)))); -} - -// CHECK#11 -if (Boolean(new Number()) !== true) { - throw new Test262Error('#11: Boolean(new Number()) === true. Actual: ' + (Boolean(new Number()))); -} - -// CHECK#12 -if (Boolean(new Number(Number.NaN)) !== true) { - throw new Test262Error('#12: Boolean(new Number(Number.NaN)) === true. Actual: ' + (Boolean(new Number(Number.NaN)))); -} - -// CHECK#13 -if (Boolean(new Number(-1)) !== true) { - throw new Test262Error('#13: Boolean(new Number(-1)) === true. Actual: ' + (Boolean(new Number(-1)))); -} - -// CHECK#14 -if (Boolean(new Number(1)) !== true) { - throw new Test262Error('#14: Boolean(new Number(1)) === true. Actual: ' + (Boolean(new Number(1)))); -} - -// CHECK#15 -if (Boolean(new Number(Number.POSITIVE_INFINITY)) !== true) { - throw new Test262Error('#15: Boolean(new Number(Number.POSITIVE_INFINITY)) === true. Actual: ' + (Boolean(new Number(Number.POSITIVE_INFINITY)))); -} - -// CHECK#16 -if (Boolean(new Number(Number.NEGATIVE_INFINITY)) !== true) { - throw new Test262Error('#16: Boolean(new Number(Number.NEGATIVE_INFINITY)) === true. Actual: ' + (Boolean(new Number(Number.NEGATIVE_INFINITY)))); -} - -// CHECK#17 -if (Boolean(new Function()) !== true) { - throw new Test262Error('#17: Boolean(new Function()) === true. Actual: ' + (Boolean(new Function()))); -} - -// CHECK#18 -if (Boolean(new Date()) !== true) { - throw new Test262Error('#18: Boolean(new Date()) === true. Actual: ' + (Boolean(new Date()))); -} - -// CHECK#19 -if (Boolean(new Date(0)) !== true) { - throw new Test262Error('#19: Boolean(new Date(0)) === true. Actual: ' + (Boolean(new Date(0)))); -} +assert.sameValue(Boolean(new Function()), true, 'Boolean(new Function()) must return true'); +assert.sameValue(Boolean(new Date()), true, 'Boolean(new Date()) must return true'); +assert.sameValue(Boolean(new Date(0)), true, 'Boolean(new Date(0)) must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A1.js b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A1.js index 08eedb4a3db8..506250ab6f09 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A1.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A1.js @@ -9,20 +9,20 @@ esid: sec-boolean.prototype description: Checking Boolean.prototype property ---*/ -//CHECK#1 -if (typeof Boolean.prototype !== "object") { - throw new Test262Error('#1: typeof Boolean.prototype === "object"'); -} +assert.sameValue( + typeof Boolean.prototype, + "object", + 'The value of `typeof Boolean.prototype` is expected to be "object"' +); -//CHECK#2 -if (Boolean.prototype != false) { - throw new Test262Error('#2: Boolean.prototype == false'); -} +assert(Boolean.prototype == false, 'The value of Boolean.prototype is expected to be false'); delete Boolean.prototype.toString; -if (Boolean.prototype.toString() !== "[object Boolean]") { - throw new Test262Error('#3: The [[Class]] property of the Boolean prototype object is set to "Boolean"'); -} +assert.sameValue( + Boolean.prototype.toString(), + "[object Boolean]", + 'Boolean.prototype.toString() must return "[object Boolean]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A2.js b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A2.js index 7daf06c44780..712c4846ebd0 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A2.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A2.js @@ -11,8 +11,6 @@ includes: [propertyHelper.js] // CHECK#1 var x = Boolean.prototype; verifyNotWritable(Boolean, "prototype", null, 1); -if (Boolean.prototype !== x) { - throw new Test262Error('#1: Boolean.prototype has the attribute ReadOnly'); -} +assert.sameValue(Boolean.prototype, x, 'The value of Boolean.prototype is expected to equal the value of x'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A3.js b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A3-strict.js similarity index 64% rename from js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A3.js rename to js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A3-strict.js index d7e76bdee229..9f4025f1602e 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A3.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A3-strict.js @@ -1,3 +1,4 @@ +'use strict'; // Copyright 2009 the Sputnik authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. @@ -6,18 +7,14 @@ info: Boolean.prototype has the attribute DontDelete esid: sec-boolean.prototype description: Checking if deleting the Boolean.prototype property fails includes: [propertyHelper.js] +flags: [onlyStrict] ---*/ // CHECK#1 verifyNotConfigurable(Boolean, "prototype"); -try { - if (delete Boolean.prototype !== false) { - throw new Test262Error('#1: Boolean.prototype has the attribute DontDelete'); - } -} catch (e) { - if (e instanceof Test262Error) throw e; - assert(e instanceof TypeError); -} +assert.throws(TypeError, () => { + delete Boolean.prototype; +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A4.js b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A4.js index 10c91208bdf6..fb25477820fe 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A4.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.3.1_A4.js @@ -7,15 +7,13 @@ esid: sec-boolean.prototype description: Checking if enumerating the Boolean.prototype property fails ---*/ -//CHECK#1 for (x in Boolean) { - if (x === "prototype") { - throw new Test262Error('#1: Boolean.prototype has the attribute DontEnum'); - } + assert.notSameValue(x, "prototype", 'The value of x is not "prototype"'); } -if (Boolean.propertyIsEnumerable('prototype')) { - throw new Test262Error('#2: Boolean.prototype has the attribute DontEnum'); -} +assert( + !Boolean.propertyIsEnumerable('prototype'), + 'The value of !Boolean.propertyIsEnumerable(\'prototype\') is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.4_A1.js b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.4_A1.js deleted file mode 100644 index 549704b5c396..000000000000 --- a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.4_A1.js +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: | - The Boolean prototype object is itself a Boolean object - (its [[Class]] is "Boolean") whose value is false -esid: sec-properties-of-the-boolean-prototype-object -description: Checking type and value of Boolean.prototype ----*/ - -//CHECK#1 -if (typeof Boolean.prototype !== "object") { - throw new Test262Error('#1: typeof Boolean.prototype === "object"'); -} - -//CHECK#2 -if (Boolean.prototype != false) { - throw new Test262Error('#2: Boolean.prototype == false'); -} - -delete Boolean.prototype.toString; - -if (Boolean.prototype.toString() !== "[object Boolean]") { - throw new Test262Error('#3: The [[Class]] property of the Boolean prototype object is set to "Boolean"'); -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.4_A2.js b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.4_A2.js index edb578a89488..f5ce2c97cf1a 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.4_A2.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/S15.6.4_A2.js @@ -9,9 +9,9 @@ esid: sec-properties-of-the-boolean-prototype-object description: Checking Object.prototype.isPrototypeOf(Boolean.prototype) ---*/ -//CHECK#1 -if (!Object.prototype.isPrototypeOf(Boolean.prototype)) { - throw new Test262Error('#1: Object prototype object is the prototype of Boolean prototype object'); -} +assert( + Object.prototype.isPrototypeOf(Boolean.prototype), + 'Object.prototype.isPrototypeOf(Boolean.prototype) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/constructor/S15.6.4.1_A1.js b/js/src/tests/test262/built-ins/Boolean/prototype/constructor/S15.6.4.1_A1.js index e544a193e11e..cf579e869078 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/constructor/S15.6.4.1_A1.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/constructor/S15.6.4.1_A1.js @@ -8,10 +8,10 @@ info: | esid: sec-boolean-constructor description: Compare Boolean.prototype.constructor with Boolean ---*/ - -//CHECK#1 -if (Boolean.prototype.constructor !== Boolean) { - throw new Test262Error('#1: Boolean.prototype.constructor === Boolean'); -} +assert.sameValue( + Boolean.prototype.constructor, + Boolean, + 'The value of Boolean.prototype.constructor is expected to equal the value of Boolean' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T1.js b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T1.js index a99c350e5730..ddbefc221323 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T1.js @@ -10,40 +10,17 @@ info: | es5id: 15.6.4.2_A1_T1 description: no arguments ---*/ +assert.sameValue(Boolean.prototype.toString(), "false", 'Boolean.prototype.toString() must return "false"'); +assert.sameValue((new Boolean()).toString(), "false", '(new Boolean()).toString() must return "false"'); +assert.sameValue((new Boolean(false)).toString(), "false", '(new Boolean(false)).toString() must return "false"'); +assert.sameValue((new Boolean(true)).toString(), "true", '(new Boolean(true)).toString() must return "true"'); +assert.sameValue((new Boolean(1)).toString(), "true", '(new Boolean(1)).toString() must return "true"'); +assert.sameValue((new Boolean(0)).toString(), "false", '(new Boolean(0)).toString() must return "false"'); -//CHECK#1 -if (Boolean.prototype.toString() !== "false") { - throw new Test262Error('#1: Boolean.prototype.toString() === "false"'); -} - -//CHECK#2 -if ((new Boolean()).toString() !== "false") { - throw new Test262Error('#2: (new Boolean()).toString() === "false"'); -} - -//CHECK#3 -if ((new Boolean(false)).toString() !== "false") { - throw new Test262Error('#3: (new Boolean(false)).toString() === "false"'); -} - -//CHECK#4 -if ((new Boolean(true)).toString() !== "true") { - throw new Test262Error('#4: (new Boolean(true)).toString() === "true"'); -} - -//CHECK#5 -if ((new Boolean(1)).toString() !== "true") { - throw new Test262Error('#5: (new Boolean(1)).toString() === "true"'); -} - -//CHECK#6 -if ((new Boolean(0)).toString() !== "false") { - throw new Test262Error('#6: (new Boolean(0)).toString() === "false"'); -} - -//CHECK#7 -if ((new Boolean(new Object())).toString() !== "true") { - throw new Test262Error('#7: (new Boolean(new Object())).toString() === "true"'); -} +assert.sameValue( + (new Boolean(new Object())).toString(), + "true", + '(new Boolean(new Object())).toString() must return "true"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T2.js b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T2.js index 262866839b8c..8f1cc3d22324 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T2.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T2.js @@ -10,40 +10,28 @@ info: | es5id: 15.6.4.2_A1_T2 description: with some argument ---*/ +assert.sameValue(Boolean.prototype.toString(true), "false", 'Boolean.prototype.toString(true) must return "false"'); +assert.sameValue((new Boolean()).toString(true), "false", '(new Boolean()).toString(true) must return "false"'); -//CHECK#1 -if (Boolean.prototype.toString(true) !== "false") { - throw new Test262Error('#1: Boolean.prototype.toString(true) === "false"'); -} +assert.sameValue( + (new Boolean(false)).toString(true), + "false", + '(new Boolean(false)).toString(true) must return "false"' +); -//CHECK#2 -if ((new Boolean()).toString(true) !== "false") { - throw new Test262Error('#2: (new Boolean()).toString(true) === "false"'); -} +assert.sameValue( + (new Boolean(true)).toString(false), + "true", + '(new Boolean(true)).toString(false) must return "true"' +); -//CHECK#3 -if ((new Boolean(false)).toString(true) !== "false") { - throw new Test262Error('#3: (new Boolean(false)).toString(true) === "false"'); -} +assert.sameValue((new Boolean(1)).toString(false), "true", '(new Boolean(1)).toString(false) must return "true"'); +assert.sameValue((new Boolean(0)).toString(true), "false", '(new Boolean(0)).toString(true) must return "false"'); -//CHECK#4 -if ((new Boolean(true)).toString(false) !== "true") { - throw new Test262Error('#4: (new Boolean(true)).toString(false) === "true"'); -} - -//CHECK#5 -if ((new Boolean(1)).toString(false) !== "true") { - throw new Test262Error('#5: (new Boolean(1)).toString(false) === "true"'); -} - -//CHECK#6 -if ((new Boolean(0)).toString(true) !== "false") { - throw new Test262Error('#6: (new Boolean(0)).toString(true) === "false"'); -} - -//CHECK#7 -if ((new Boolean(new Object())).toString(false) !== "true") { - throw new Test262Error('#7: (new Boolean(new Object())).toString(false) === "true"'); -} +assert.sameValue( + (new Boolean(new Object())).toString(false), + "true", + '(new Boolean(new Object())).toString(false) must return "true"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T1.js b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T1.js index 171ebbba1226..f1a849b32554 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T1.js @@ -11,30 +11,16 @@ es5id: 15.6.4.2_A2_T1 description: transferring to the String objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = new String(); s1.toString = Boolean.prototype.toString; var v1 = s1.toString(); - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} +}); -//CHECK#2 -try { +assert.throws(TypeError, () => { var s2 = new String(); s2.myToString = Boolean.prototype.toString; var v2 = s2.myToString(); - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T2.js b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T2.js index 159cb7ec126d..e4837f700f18 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T2.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T2.js @@ -11,30 +11,16 @@ es5id: 15.6.4.2_A2_T2 description: transferring to the Number objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = new Number(); s1.toString = Boolean.prototype.toString; - var v1 = s1.toString(); - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.toString(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = new Number(); s2.myToString = Boolean.prototype.toString; - var v2 = s2.myToString(); - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myToString(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T3.js b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T3.js index a8c9f56128f6..f6a6519a1b83 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T3.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T3.js @@ -11,30 +11,16 @@ es5id: 15.6.4.2_A2_T3 description: transferring to the Date objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = new Date(); s1.toString = Boolean.prototype.toString; - var v1 = s1.toString(); - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.toString(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = new Date(); s2.myToString = Boolean.prototype.toString; - var v2 = s2.myToString(); - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myToString(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T4.js b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T4.js index d5f7f7f2cffd..7b7bbfad108c 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T4.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T4.js @@ -11,30 +11,17 @@ es5id: 15.6.4.2_A2_T4 description: transferring to the Object objects ---*/ -//CHECK#1 -try { + +assert.throws(TypeError, () => { var s1 = new Object(); s1.toString = Boolean.prototype.toString; - var v1 = s1.toString(); - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.toString(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = new Object(); s2.myToString = Boolean.prototype.toString; - var v2 = s2.myToString(); - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myToString(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T5.js b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T5.js index bf69a5c91d0c..a3fa1b565f5b 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T5.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/toString/S15.6.4.2_A2_T5.js @@ -11,34 +11,20 @@ es5id: 15.6.4.2_A2_T5 description: transferring to the other objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = { x: 1 }; s1.toString = Boolean.prototype.toString; - var v1 = s1.toString(); - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.toString(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = { x: 1 }; s2.myToString = Boolean.prototype.toString; - var v2 = s2.myToString(); - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.toString on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myToString(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T1.js b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T1.js index 404951432873..e0edbaf6412f 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T1.js @@ -6,35 +6,16 @@ info: Boolean.prototype.valueOf() returns this boolean value esid: sec-boolean.prototype.valueof description: no arguments ---*/ +assert.sameValue(Boolean.prototype.valueOf(), false, 'Boolean.prototype.valueOf() must return false'); +assert.sameValue((new Boolean()).valueOf(), false, '(new Boolean()).valueOf() must return false'); +assert.sameValue((new Boolean(0)).valueOf(), false, '(new Boolean(0)).valueOf() must return false'); +assert.sameValue((new Boolean(-1)).valueOf(), true, '(new Boolean(-1)).valueOf() must return true'); +assert.sameValue((new Boolean(1)).valueOf(), true, '(new Boolean(1)).valueOf() must return true'); -//CHECK#1 -if (Boolean.prototype.valueOf() !== false) { - throw new Test262Error('#1: Boolean.prototype.valueOf() === false'); -} - -//CHECK#2 -if ((new Boolean()).valueOf() !== false) { - throw new Test262Error('#2: (new Boolean()).valueOf() === false'); -} - -//CHECK#3 -if ((new Boolean(0)).valueOf() !== false) { - throw new Test262Error('#3: (new Boolean(0)).valueOf() === false'); -} - -//CHECK#4 -if ((new Boolean(-1)).valueOf() !== true) { - throw new Test262Error('#4: (new Boolean(-1)).valueOf() === true'); -} - -//CHECK#5 -if ((new Boolean(1)).valueOf() !== true) { - throw new Test262Error('#5: (new Boolean(1)).valueOf() === true'); -} - -//CHECK#6 -if ((new Boolean(new Object())).valueOf() !== true) { - throw new Test262Error('#6: (new Boolean(new Object())).valueOf() === true'); -} +assert.sameValue( + (new Boolean(new Object())).valueOf(), + true, + '(new Boolean(new Object())).valueOf() must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T2.js b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T2.js index 1a52f80ffc67..28d0045fb94b 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T2.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T2.js @@ -6,35 +6,16 @@ info: Boolean.prototype.valueOf() returns this boolean value esid: sec-boolean.prototype.valueof description: calling with argument ---*/ +assert.sameValue(Boolean.prototype.valueOf(true), false, 'Boolean.prototype.valueOf(true) must return false'); +assert.sameValue((new Boolean()).valueOf(true), false, '(new Boolean()).valueOf(true) must return false'); +assert.sameValue((new Boolean(0)).valueOf(true), false, '(new Boolean(0)).valueOf(true) must return false'); +assert.sameValue((new Boolean(-1)).valueOf(false), true, '(new Boolean(-1)).valueOf(false) must return true'); +assert.sameValue((new Boolean(1)).valueOf(false), true, '(new Boolean(1)).valueOf(false) must return true'); -//CHECK#1 -if (Boolean.prototype.valueOf(true) !== false) { - throw new Test262Error('#1: Boolean.prototype.valueOf(true) === false'); -} - -//CHECK#2 -if ((new Boolean()).valueOf(true) !== false) { - throw new Test262Error('#2: (new Boolean()).valueOf(true) === false'); -} - -//CHECK#3 -if ((new Boolean(0)).valueOf(true) !== false) { - throw new Test262Error('#3: (new Boolean(0)).valueOf(true) === false'); -} - -//CHECK#4 -if ((new Boolean(-1)).valueOf(false) !== true) { - throw new Test262Error('#4: (new Boolean(-1)).valueOf(false) === true'); -} - -//CHECK#5 -if ((new Boolean(1)).valueOf(false) !== true) { - throw new Test262Error('#5: (new Boolean(1)).valueOf(false) === true'); -} - -//CHECK#6 -if ((new Boolean(new Object())).valueOf(false) !== true) { - throw new Test262Error('#6: (new Boolean(new Object())).valueOf(false) === true'); -} +assert.sameValue( + (new Boolean(new Object())).valueOf(false), + true, + '(new Boolean(new Object())).valueOf(false) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T1.js b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T1.js index 6246169e0718..00e3caf52678 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T1.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T1.js @@ -10,30 +10,16 @@ esid: sec-boolean.prototype.valueof description: transferring to the String objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = new String(); s1.valueOf = Boolean.prototype.valueOf; - var v1 = s1.valueOf(); - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.valueOf(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = new String(); - s2.myValueOf = Boolean.prototype.valueOf; - var v2 = s2.myValueOf(); - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myvalueOf = Boolean.prototype.valueOf; + s2.myvalueOf(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T2.js b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T2.js index 54e02525602b..129656b8889c 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T2.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T2.js @@ -10,30 +10,16 @@ esid: sec-boolean.prototype.valueof description: transferring to the Number objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = new Number(); s1.valueOf = Boolean.prototype.valueOf; - var v1 = s1.valueOf(); - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.valueOf(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = new Number(); - s2.myValueOf = Boolean.prototype.valueOf; - var v2 = s2.myValueOf(); - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myvalueOf = Boolean.prototype.valueOf; + s2.myvalueOf(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T3.js b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T3.js index 7ae2bf3d62da..7782764edcdc 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T3.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T3.js @@ -10,30 +10,16 @@ esid: sec-boolean.prototype.valueof description: transferring to the Date objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = new Date(); s1.valueOf = Boolean.prototype.valueOf; - var v1 = s1.valueOf(); - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.valueOf(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = new Date(); - s2.myValueOf = Boolean.prototype.valueOf; - var v2 = s2.myValueOf(); - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myvalueOf = Boolean.prototype.valueOf; + s2.myvalueOf(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T4.js b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T4.js index 58564f56b9f7..90d3c95ab745 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T4.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T4.js @@ -10,30 +10,16 @@ esid: sec-boolean.prototype.valueof description: transferring to the Object objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = new Object(); s1.valueOf = Boolean.prototype.valueOf; - var v1 = s1.valueOf(); - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.valueOf(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = new Object(); - s2.myValueOf = Boolean.prototype.valueOf; - var v2 = s2.myValueOf(); - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myvalueOf = Boolean.prototype.valueOf; + s2.myvalueOf(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T5.js b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T5.js index ca7eb54d50da..6d51c076056b 100644 --- a/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T5.js +++ b/js/src/tests/test262/built-ins/Boolean/prototype/valueOf/S15.6.4.3_A2_T5.js @@ -10,34 +10,20 @@ esid: sec-boolean.prototype.valueof description: transferring to the other objects ---*/ -//CHECK#1 -try { +assert.throws(TypeError, () => { var s1 = { x: 1 }; s1.valueOf = Boolean.prototype.valueOf; - var v1 = s1.valueOf(); - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s1.valueOf(); +}); -//CHECK#1 -try { +assert.throws(TypeError, () => { var s2 = { x: 1 }; - s2.myValueOf = Boolean.prototype.valueOf; - var v2 = s2.myValueOf(); - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError'); -} -catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Boolean.prototype.valueOf on not a Boolean object should throw TypeError, not ' + e); - } -} + s2.myvalueOf = Boolean.prototype.valueOf; + s2.myvalueOf(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-invalid-by-length.js b/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-invalid-by-length.js new file mode 100644 index 000000000000..7626720d2a5d --- /dev/null +++ b/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-invalid-by-length.js @@ -0,0 +1,43 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-dataview-buffer-byteoffset-bytelength +description: > + The sum of the view's offset and byte length cannot exceed the underlying + buffer's byte length if it is modified during retrieval of the NewTarget's + prototype. +features: [resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +var buffer = new ArrayBuffer(3, {maxByteLength: 3}); +var expectedError; + +var newTarget = function() {}.bind(null); +Object.defineProperty(newTarget, 'prototype', { + get: function() { + try { + buffer.resize(2); + expectedError = RangeError; + } catch (error) { + expectedError = null; + } + } +}); +var error = null; + +try { + Reflect.construct(DataView, [buffer, 1, 2], newTarget); +} catch (caught) { + error = caught.constructor; +} + +assert.sameValue(error, expectedError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-invalid-by-offset.js b/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-invalid-by-offset.js new file mode 100644 index 000000000000..63cb6a2ef1b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-invalid-by-offset.js @@ -0,0 +1,42 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-dataview-buffer-byteoffset-bytelength +description: > + The view's offset cannot exceed the underlying buffer's byte length if it is + modified during retrieval of the NewTarget's prototype. +features: [resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +var buffer = new ArrayBuffer(3, {maxByteLength: 3}); +var expectedError; + +var newTarget = function() {}.bind(null); +Object.defineProperty(newTarget, 'prototype', { + get: function() { + try { + buffer.resize(1); + expectedError = RangeError; + } catch (error) { + expectedError = null; + } + } +}); +var error = null; + +try { + Reflect.construct(DataView, [buffer, 2], newTarget); +} catch (caught) { + error = caught.constructor; +} + +assert.sameValue(error, expectedError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-valid-by-length.js b/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-valid-by-length.js new file mode 100644 index 000000000000..3aacc841b4e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-valid-by-length.js @@ -0,0 +1,35 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-dataview-buffer-byteoffset-bytelength +description: > + The sum of the view's offset and byte length may equal the underlying + buffer's byte length if it is modified during retrieval of the NewTarget's + prototype. +features: [resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +var buffer = new ArrayBuffer(3, {maxByteLength: 3}); + +var newTarget = function() {}.bind(null); +Object.defineProperty(newTarget, 'prototype', { + get: function() { + try { + buffer.resize(2); + } catch (error) {} + } +}); + +var result = Reflect.construct(DataView, [buffer, 1, 1], newTarget); + +assert.sameValue(result.constructor, DataView); +assert.sameValue(result.byteLength, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-valid-by-offset.js b/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-valid-by-offset.js new file mode 100644 index 000000000000..ba6b7e9eaa9d --- /dev/null +++ b/js/src/tests/test262/built-ins/DataView/custom-proto-access-resizes-buffer-valid-by-offset.js @@ -0,0 +1,38 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-dataview-buffer-byteoffset-bytelength +description: > + The view's offset may equal the underlying buffer's byte length if it is + modified during retrieval of the NewTarget's prototype. +features: [resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +var buffer = new ArrayBuffer(3, {maxByteLength: 3}); +var expectedByteLength; + +var newTarget = function() {}.bind(null); +Object.defineProperty(newTarget, 'prototype', { + get: function() { + try { + buffer.resize(2); + expectedByteLength = 0; + } catch (error) { + expectedByteLength = 1; + } + } +}); + +var result = Reflect.construct(DataView, [buffer, 2], newTarget); + +assert.sameValue(result.constructor, DataView); +assert.sameValue(result.byteLength, expectedByteLength); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/DataView/prototype/Symbol.toStringTag.js b/js/src/tests/test262/built-ins/DataView/prototype/Symbol.toStringTag.js index 30a7eb7c5b43..a6787061c550 100644 --- a/js/src/tests/test262/built-ins/DataView/prototype/Symbol.toStringTag.js +++ b/js/src/tests/test262/built-ins/DataView/prototype/Symbol.toStringTag.js @@ -14,7 +14,11 @@ includes: [propertyHelper.js] features: [Symbol.toStringTag] ---*/ -assert.sameValue(DataView.prototype[Symbol.toStringTag], 'DataView'); +assert.sameValue( + DataView.prototype[Symbol.toStringTag], + 'DataView', + 'The value of DataView.prototype[Symbol.toStringTag] is expected to be "DataView"' +); verifyNotEnumerable(DataView.prototype, Symbol.toStringTag); verifyNotWritable(DataView.prototype, Symbol.toStringTag); diff --git a/js/src/tests/test262/built-ins/DataView/prototype/byteLength/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/DataView/prototype/byteLength/resizable-array-buffer-auto.js index 310c213bdb8d..6ff801c6efc8 100644 --- a/js/src/tests/test262/built-ins/DataView/prototype/byteLength/resizable-array-buffer-auto.js +++ b/js/src/tests/test262/built-ins/DataView/prototype/byteLength/resizable-array-buffer-auto.js @@ -37,6 +37,13 @@ assert.sameValue(dataView.byteLength, expected, "following shrink (within bounds try { ab.resize(1); + expected = 0; +} catch (_) {} + +assert.sameValue(dataView.byteLength, expected, "following shrink (on boundary)"); + +try { + ab.resize(0); expected = TypeError; } catch (_) { expected = Test262Error; diff --git a/js/src/tests/test262/built-ins/DataView/prototype/byteOffset/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/DataView/prototype/byteOffset/resizable-array-buffer-auto.js index 8d61fea36b9b..49d07780bfed 100644 --- a/js/src/tests/test262/built-ins/DataView/prototype/byteOffset/resizable-array-buffer-auto.js +++ b/js/src/tests/test262/built-ins/DataView/prototype/byteOffset/resizable-array-buffer-auto.js @@ -32,9 +32,15 @@ try { assert.sameValue(dataView.byteOffset, 1, "following shrink (within bounds)"); -var expectedError; try { ab.resize(1); +} catch (_) {} + +assert.sameValue(dataView.byteOffset, 1, "following shrink (on boundary)"); + +var expectedError; +try { + ab.resize(0); expectedError = TypeError; } catch (_) { expectedError = Test262Error; diff --git a/js/src/tests/test262/built-ins/Date/S15.9.2.1_A1.js b/js/src/tests/test262/built-ins/Date/S15.9.2.1_A1.js index 5757ae8fb4b9..12f408a72314 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.2.1_A1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.2.1_A1.js @@ -9,75 +9,65 @@ info: | es5id: 15.9.2.1_A1 description: Checking type of returned value ---*/ +assert.sameValue(typeof Date(), "string", 'The value of `typeof Date()` is expected to be "string"'); +assert.sameValue(typeof Date(1), "string", 'The value of `typeof Date(1)` is expected to be "string"'); +assert.sameValue(typeof Date(1970, 1), "string", 'The value of `typeof Date(1970, 1)` is expected to be "string"'); -//CHECK#1 -if (typeof Date() !== "string") { - throw new Test262Error('#1: typeof Date() should be "string", actual is ' + (typeof Date())); -} +assert.sameValue( + typeof Date(1970, 1, 1), + "string", + 'The value of `typeof Date(1970, 1, 1)` is expected to be "string"' +); -//CHECK#2 -if (typeof Date(1) !== "string") { - throw new Test262Error('#2: typeof Date(1) should be "string", actual is ' + (typeof Date(1))); -} +assert.sameValue( + typeof Date(1970, 1, 1, 1), + "string", + 'The value of `typeof Date(1970, 1, 1, 1)` is expected to be "string"' +); -//CHECK#3 -if (typeof Date(1970, 1) !== "string") { - throw new Test262Error('#3: typeof Date(1970, 1) should be "string", actual is ' + (typeof Date(1970, 1))); -} +assert.sameValue( + typeof Date(1970, 1, 1, 1), + "string", + 'The value of `typeof Date(1970, 1, 1, 1)` is expected to be "string"' +); -//CHECK#4 -if (typeof Date(1970, 1, 1) !== "string") { - throw new Test262Error('#4: typeof Date(1970, 1, 1) should be "string", actual is ' + (typeof Date(1970, 1, 1))); -} +assert.sameValue( + typeof Date(1970, 1, 1, 1, 0), + "string", + 'The value of `typeof Date(1970, 1, 1, 1, 0)` is expected to be "string"' +); -//CHECK#5 -if (typeof Date(1970, 1, 1, 1) !== "string") { - throw new Test262Error('#5: typeof Date(1970, 1, 1, 1) should be "string", actual is ' + (typeof Date(1970, 1, 1, 1))); -} +assert.sameValue( + typeof Date(1970, 1, 1, 1, 0, 0), + "string", + 'The value of `typeof Date(1970, 1, 1, 1, 0, 0)` is expected to be "string"' +); -//CHECK#6 -if (typeof Date(1970, 1, 1, 1) !== "string") { - throw new Test262Error('#7: typeof Date(1970, 1, 1, 1) should be "string", actual is ' + (typeof Date(1970, 1, 1, 1))); -} +assert.sameValue( + typeof Date(1970, 1, 1, 1, 0, 0, 0), + "string", + 'The value of `typeof Date(1970, 1, 1, 1, 0, 0, 0)` is expected to be "string"' +); -//CHECK#8 -if (typeof Date(1970, 1, 1, 1, 0) !== "string") { - throw new Test262Error('#8: typeof Date(1970, 1, 1, 1, 0) should be "string", actual is ' + (typeof Date(1970, 1, 1, 1, 0))); -} +assert.sameValue( + typeof Date(Number.NaN), + "string", + 'The value of `typeof Date(Number.NaN)` is expected to be "string"' +); -//CHECK#9 -if (typeof Date(1970, 1, 1, 1, 0, 0) !== "string") { - throw new Test262Error('#9: typeof Date(1970, 1, 1, 1, 0, 0) should be "string", actual is ' + (typeof Date(1970, 1, 1, 1, 0, 0))); -} +assert.sameValue( + typeof Date(Number.POSITIVE_INFINITY), + "string", + 'The value of `typeof Date(Number.POSITIVE_INFINITY)` is expected to be "string"' +); -//CHECK#10 -if (typeof Date(1970, 1, 1, 1, 0, 0, 0) !== "string") { - throw new Test262Error('#10: typeof Date(1970, 1, 1, 1, 0, 0, 0) should be "string", actual is ' + (typeof Date(1970, 1, 1, 1, 0, 0, 0))); -} +assert.sameValue( + typeof Date(Number.NEGATIVE_INFINITY), + "string", + 'The value of `typeof Date(Number.NEGATIVE_INFINITY)` is expected to be "string"' +); -//CHECK#11 -if (typeof Date(Number.NaN) !== "string") { - throw new Test262Error('#11: typeof Date(Number.NaN) should be "string", actual is ' + (typeof Date(Number.NaN))); -} - -//CHECK#12 -if (typeof Date(Number.POSITIVE_INFINITY) !== "string") { - throw new Test262Error('#12: typeof Date(Number.POSITIVE_INFINITY) should be "string", actual is ' + (typeof Date(Number.POSITIVE_INFINITY))); -} - -//CHECK#13 -if (typeof Date(Number.NEGATIVE_INFINITY) !== "string") { - throw new Test262Error('#13: typeof Date(Number.NEGATIVE_INFINITY) should be "string", actual is ' + (typeof Date(Number.NEGATIVE_INFINITY))); -} - -//CHECK#14 -if (typeof Date(undefined) !== "string") { - throw new Test262Error('#14: typeof Date(undefined) should be "string", actual is ' + (typeof Date(undefined))); -} - -//CHECK#15 -if (typeof Date(null) !== "string") { - throw new Test262Error('#15: typeof Date(null) should be "string", actual is ' + (typeof Date(null))); -} +assert.sameValue(typeof Date(undefined), "string", 'The value of `typeof Date(undefined)` is expected to be "string"'); +assert.sameValue(typeof Date(null), "string", 'The value of `typeof Date(null)` is expected to be "string"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.2.1_A2.js b/js/src/tests/test262/built-ins/Date/S15.9.2.1_A2.js index a730d12e3e67..81b6bfc777a0 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.2.1_A2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.2.1_A2.js @@ -21,74 +21,74 @@ function isEqual(d1, d2) { } } -//CHECK#1 -if (!isEqual(Date(), (new Date()).toString())) { - throw new Test262Error('#1: Date() is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(), (new Date()).toString()), + 'isEqual(Date(), (new Date()).toString()) must return true' +); -//CHECK#2 -if (!isEqual(Date(1), (new Date()).toString())) { - throw new Test262Error('#2: Date(1) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(1), (new Date()).toString()), + 'isEqual(Date(1), (new Date()).toString()) must return true' +); -//CHECK#3 -if (!isEqual(Date(1970, 1), (new Date()).toString())) { - throw new Test262Error('#3: Date(1970, 1) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(1970, 1), (new Date()).toString()), + 'isEqual(Date(1970, 1), (new Date()).toString()) must return true' +); -//CHECK#4 -if (!isEqual(Date(1970, 1, 1), (new Date()).toString())) { - throw new Test262Error('#4: Date(1970, 1, 1) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(1970, 1, 1), (new Date()).toString()), + 'isEqual(Date(1970, 1, 1), (new Date()).toString()) must return true' +); -//CHECK#5 -if (!isEqual(Date(1970, 1, 1, 1), (new Date()).toString())) { - throw new Test262Error('#5: Date(1970, 1, 1, 1) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(1970, 1, 1, 1), (new Date()).toString()), + 'isEqual(Date(1970, 1, 1, 1), (new Date()).toString()) must return true' +); -//CHECK#6 -if (!isEqual(Date(1970, 1, 1, 1), (new Date()).toString())) { - throw new Test262Error('#7: Date(1970, 1, 1, 1) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(1970, 1, 1, 1), (new Date()).toString()), + 'isEqual(Date(1970, 1, 1, 1), (new Date()).toString()) must return true' +); -//CHECK#8 -if (!isEqual(Date(1970, 1, 1, 1, 0), (new Date()).toString())) { - throw new Test262Error('#8: Date(1970, 1, 1, 1, 0) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(1970, 1, 1, 1, 0), (new Date()).toString()), + 'isEqual(Date(1970, 1, 1, 1, 0), (new Date()).toString()) must return true' +); -//CHECK#9 -if (!isEqual(Date(1970, 1, 1, 1, 0, 0), (new Date()).toString())) { - throw new Test262Error('#9: Date(1970, 1, 1, 1, 0, 0) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(1970, 1, 1, 1, 0, 0), (new Date()).toString()), + 'isEqual(Date(1970, 1, 1, 1, 0, 0), (new Date()).toString()) must return true' +); -//CHECK#10 -if (!isEqual(Date(1970, 1, 1, 1, 0, 0, 0), (new Date()).toString())) { - throw new Test262Error('#10: Date(1970, 1, 1, 1, 0, 0, 0) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(1970, 1, 1, 1, 0, 0, 0), (new Date()).toString()), + 'isEqual(Date(1970, 1, 1, 1, 0, 0, 0), (new Date()).toString()) must return true' +); -//CHECK#11 -if (!isEqual(Date(Number.NaN), (new Date()).toString())) { - throw new Test262Error('#11: Date(Number.NaN) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(Number.NaN), (new Date()).toString()), + 'isEqual(Date(Number.NaN), (new Date()).toString()) must return true' +); -//CHECK#12 -if (!isEqual(Date(Number.POSITIVE_INFINITY), (new Date()).toString())) { - throw new Test262Error('#12: Date(Number.POSITIVE_INFINITY) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(Number.POSITIVE_INFINITY), (new Date()).toString()), + 'isEqual(Date(Number.POSITIVE_INFINITY), (new Date()).toString()) must return true' +); -//CHECK#13 -if (!isEqual(Date(Number.NEGATIVE_INFINITY), (new Date()).toString())) { - throw new Test262Error('#13: Date(Number.NEGATIVE_INFINITY) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(Number.NEGATIVE_INFINITY), (new Date()).toString()), + 'isEqual(Date(Number.NEGATIVE_INFINITY), (new Date()).toString()) must return true' +); -//CHECK#14 -if (!isEqual(Date(undefined), (new Date()).toString())) { - throw new Test262Error('#14: Date(undefined) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(undefined), (new Date()).toString()), + 'isEqual(Date(undefined), (new Date()).toString()) must return true' +); -//CHECK#15 -if (!isEqual(Date(null), (new Date()).toString())) { - throw new Test262Error('#15: Date(null) is equal to (new Date()).toString()'); -} +assert( + isEqual(Date(null), (new Date()).toString()), + 'isEqual(Date(null), (new Date()).toString()) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T1.js index 93dfb829670f..8f64633007c6 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T1.js @@ -9,220 +9,172 @@ esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 2 arguments, (year, month) ---*/ -if (typeof new Date(1899, 11) !== "object") { - throw new Test262Error("#1.1: typeof new Date(1899, 11) should be 'object'"); -} +assert.sameValue( + typeof new Date(1899, 11), + "object", + 'The value of `typeof new Date(1899, 11)` is expected to be "object"' +); -if (new Date(1899, 11) === undefined) { - throw new Test262Error("#1.2: new Date(1899, 11) should not be undefined"); -} +assert.notSameValue(new Date(1899, 11), undefined, 'new Date(1899, 11) is expected to not equal ``undefined``'); var x13 = new Date(1899, 11); -if (typeof x13 !== "object") { - throw new Test262Error("#1.3: typeof new Date(1899, 11) should be 'object'"); -} +assert.sameValue(typeof x13, "object", 'The value of `typeof x13` is expected to be "object"'); var x14 = new Date(1899, 11); -if (x14 === undefined) { - throw new Test262Error("#1.4: new Date(1899, 11) should not be undefined"); -} +assert.notSameValue(x14, undefined, 'The value of x14 is expected to not equal ``undefined``'); -if (typeof new Date(1899, 12) !== "object") { - throw new Test262Error("#2.1: typeof new Date(1899, 12) should be 'object'"); -} +assert.sameValue( + typeof new Date(1899, 12), + "object", + 'The value of `typeof new Date(1899, 12)` is expected to be "object"' +); -if (new Date(1899, 12) === undefined) { - throw new Test262Error("#2.2: new Date(1899, 12) should not be undefined"); -} +assert.notSameValue(new Date(1899, 12), undefined, 'new Date(1899, 12) is expected to not equal ``undefined``'); var x23 = new Date(1899, 12); -if (typeof x23 !== "object") { - throw new Test262Error("#2.3: typeof new Date(1899, 12) should be 'object'"); -} +assert.sameValue(typeof x23, "object", 'The value of `typeof x23` is expected to be "object"'); var x24 = new Date(1899, 12); -if (x24 === undefined) { - throw new Test262Error("#2.4: new Date(1899, 12) should not be undefined"); -} +assert.notSameValue(x24, undefined, 'The value of x24 is expected to not equal ``undefined``'); -if (typeof new Date(1900, 0) !== "object") { - throw new Test262Error("#3.1: typeof new Date(1900, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1900, 0), + "object", + 'The value of `typeof new Date(1900, 0)` is expected to be "object"' +); -if (new Date(1900, 0) === undefined) { - throw new Test262Error("#3.2: new Date(1900, 0) should not be undefined"); -} +assert.notSameValue(new Date(1900, 0), undefined, 'new Date(1900, 0) is expected to not equal ``undefined``'); var x33 = new Date(1900, 0); -if (typeof x33 !== "object") { - throw new Test262Error("#3.3: typeof new Date(1900, 0) should be 'object'"); -} +assert.sameValue(typeof x33, "object", 'The value of `typeof x33` is expected to be "object"'); var x34 = new Date(1900, 0); -if (x34 === undefined) { - throw new Test262Error("#3.4: new Date(1900, 0) should not be undefined"); -} +assert.notSameValue(x34, undefined, 'The value of x34 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 11) !== "object") { - throw new Test262Error("#4.1: typeof new Date(1969, 11) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 11), + "object", + 'The value of `typeof new Date(1969, 11)` is expected to be "object"' +); -if (new Date(1969, 11) === undefined) { - throw new Test262Error("#4.2: new Date(1969, 11) should not be undefined"); -} +assert.notSameValue(new Date(1969, 11), undefined, 'new Date(1969, 11) is expected to not equal ``undefined``'); var x43 = new Date(1969, 11); -if (typeof x43 !== "object") { - throw new Test262Error("#4.3: typeof new Date(1969, 11) should be 'object'"); -} +assert.sameValue(typeof x43, "object", 'The value of `typeof x43` is expected to be "object"'); var x44 = new Date(1969, 11); -if (x44 === undefined) { - throw new Test262Error("#4.4: new Date(1969, 11) should not be undefined"); -} +assert.notSameValue(x44, undefined, 'The value of x44 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 12) !== "object") { - throw new Test262Error("#5.1: typeof new Date(1969, 12) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 12), + "object", + 'The value of `typeof new Date(1969, 12)` is expected to be "object"' +); -if (new Date(1969, 12) === undefined) { - throw new Test262Error("#5.2: new Date(1969, 12) should not be undefined"); -} +assert.notSameValue(new Date(1969, 12), undefined, 'new Date(1969, 12) is expected to not equal ``undefined``'); var x53 = new Date(1969, 12); -if (typeof x53 !== "object") { - throw new Test262Error("#5.3: typeof new Date(1969, 12) should be 'object'"); -} +assert.sameValue(typeof x53, "object", 'The value of `typeof x53` is expected to be "object"'); var x54 = new Date(1969, 12); -if (x54 === undefined) { - throw new Test262Error("#5.4: new Date(1969, 12) should not be undefined"); -} +assert.notSameValue(x54, undefined, 'The value of x54 is expected to not equal ``undefined``'); -if (typeof new Date(1970, 0) !== "object") { - throw new Test262Error("#6.1: typeof new Date(1970, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1970, 0), + "object", + 'The value of `typeof new Date(1970, 0)` is expected to be "object"' +); -if (new Date(1970, 0) === undefined) { - throw new Test262Error("#6.2: new Date(1970, 0) should not be undefined"); -} +assert.notSameValue(new Date(1970, 0), undefined, 'new Date(1970, 0) is expected to not equal ``undefined``'); var x63 = new Date(1970, 0); -if (typeof x63 !== "object") { - throw new Test262Error("#6.3: typeof new Date(1970, 0) should be 'object'"); -} +assert.sameValue(typeof x63, "object", 'The value of `typeof x63` is expected to be "object"'); var x64 = new Date(1970, 0); -if (x64 === undefined) { - throw new Test262Error("#6.4: new Date(1970, 0) should not be undefined"); -} +assert.notSameValue(x64, undefined, 'The value of x64 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 11) !== "object") { - throw new Test262Error("#7.1: typeof new Date(1999, 11) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 11), + "object", + 'The value of `typeof new Date(1999, 11)` is expected to be "object"' +); -if (new Date(1999, 11) === undefined) { - throw new Test262Error("#7.2: new Date(1999, 11) should not be undefined"); -} +assert.notSameValue(new Date(1999, 11), undefined, 'new Date(1999, 11) is expected to not equal ``undefined``'); var x73 = new Date(1999, 11); -if (typeof x73 !== "object") { - throw new Test262Error("#7.3: typeof new Date(1999, 11) should be 'object'"); -} +assert.sameValue(typeof x73, "object", 'The value of `typeof x73` is expected to be "object"'); var x74 = new Date(1999, 11); -if (x74 === undefined) { - throw new Test262Error("#7.4: new Date(1999, 11) should not be undefined"); -} +assert.notSameValue(x74, undefined, 'The value of x74 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 12) !== "object") { - throw new Test262Error("#8.1: typeof new Date(1999, 12) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 12), + "object", + 'The value of `typeof new Date(1999, 12)` is expected to be "object"' +); -if (new Date(1999, 12) === undefined) { - throw new Test262Error("#8.2: new Date(1999, 12) should not be undefined"); -} +assert.notSameValue(new Date(1999, 12), undefined, 'new Date(1999, 12) is expected to not equal ``undefined``'); var x83 = new Date(1999, 12); -if (typeof x83 !== "object") { - throw new Test262Error("#8.3: typeof new Date(1999, 12) should be 'object'"); -} +assert.sameValue(typeof x83, "object", 'The value of `typeof x83` is expected to be "object"'); var x84 = new Date(1999, 12); -if (x84 === undefined) { - throw new Test262Error("#8.4: new Date(1999, 12) should not be undefined"); -} +assert.notSameValue(x84, undefined, 'The value of x84 is expected to not equal ``undefined``'); -if (typeof new Date(2000, 0) !== "object") { - throw new Test262Error("#9.1: typeof new Date(2000, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2000, 0), + "object", + 'The value of `typeof new Date(2000, 0)` is expected to be "object"' +); -if (new Date(2000, 0) === undefined) { - throw new Test262Error("#9.2: new Date(2000, 0) should not be undefined"); -} +assert.notSameValue(new Date(2000, 0), undefined, 'new Date(2000, 0) is expected to not equal ``undefined``'); var x93 = new Date(2000, 0); -if (typeof x93 !== "object") { - throw new Test262Error("#9.3: typeof new Date(2000, 0) should be 'object'"); -} +assert.sameValue(typeof x93, "object", 'The value of `typeof x93` is expected to be "object"'); var x94 = new Date(2000, 0); -if (x94 === undefined) { - throw new Test262Error("#9.4: new Date(2000, 0) should not be undefined"); -} +assert.notSameValue(x94, undefined, 'The value of x94 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 11) !== "object") { - throw new Test262Error("#10.1: typeof new Date(2099, 11) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 11), + "object", + 'The value of `typeof new Date(2099, 11)` is expected to be "object"' +); -if (new Date(2099, 11) === undefined) { - throw new Test262Error("#10.2: new Date(2099, 11) should not be undefined"); -} +assert.notSameValue(new Date(2099, 11), undefined, 'new Date(2099, 11) is expected to not equal ``undefined``'); var x103 = new Date(2099, 11); -if (typeof x103 !== "object") { - throw new Test262Error("#10.3: typeof new Date(2099, 11) should be 'object'"); -} +assert.sameValue(typeof x103, "object", 'The value of `typeof x103` is expected to be "object"'); var x104 = new Date(2099, 11); -if (x104 === undefined) { - throw new Test262Error("#10.4: new Date(2099, 11) should not be undefined"); -} +assert.notSameValue(x104, undefined, 'The value of x104 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 12) !== "object") { - throw new Test262Error("#11.1: typeof new Date(2099, 12) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 12), + "object", + 'The value of `typeof new Date(2099, 12)` is expected to be "object"' +); -if (new Date(2099, 12) === undefined) { - throw new Test262Error("#11.2: new Date(2099, 12) should not be undefined"); -} +assert.notSameValue(new Date(2099, 12), undefined, 'new Date(2099, 12) is expected to not equal ``undefined``'); var x113 = new Date(2099, 12); -if (typeof x113 !== "object") { - throw new Test262Error("#11.3: typeof new Date(2099, 12) should be 'object'"); -} +assert.sameValue(typeof x113, "object", 'The value of `typeof x113` is expected to be "object"'); var x114 = new Date(2099, 12); -if (x114 === undefined) { - throw new Test262Error("#11.4: new Date(2099, 12) should not be undefined"); -} +assert.notSameValue(x114, undefined, 'The value of x114 is expected to not equal ``undefined``'); -if (typeof new Date(2100, 0) !== "object") { - throw new Test262Error("#12.1: typeof new Date(2100, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2100, 0), + "object", + 'The value of `typeof new Date(2100, 0)` is expected to be "object"' +); -if (new Date(2100, 0) === undefined) { - throw new Test262Error("#12.2: new Date(2100, 0) should not be undefined"); -} +assert.notSameValue(new Date(2100, 0), undefined, 'new Date(2100, 0) is expected to not equal ``undefined``'); var x123 = new Date(2100, 0); -if (typeof x123 !== "object") { - throw new Test262Error("#12.3: typeof new Date(2100, 0) should be 'object'"); -} +assert.sameValue(typeof x123, "object", 'The value of `typeof x123` is expected to be "object"'); var x124 = new Date(2100, 0); -if (x124 === undefined) { - throw new Test262Error("#12.4: new Date(2100, 0) should not be undefined"); -} +assert.notSameValue(x124, undefined, 'The value of x124 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T2.js index 0752d0e4aa6f..e2c91e81b377 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T2.js @@ -9,220 +9,172 @@ esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 3 arguments, (year, month, date) ---*/ -if (typeof new Date(1899, 11, 31) !== "object") { - throw new Test262Error("#1.1: typeof new Date(1899, 11, 31) should be 'object'"); -} +assert.sameValue( + typeof new Date(1899, 11, 31), + "object", + 'The value of `typeof new Date(1899, 11, 31)` is expected to be "object"' +); -if (new Date(1899, 11, 31) === undefined) { - throw new Test262Error("#1.2: new Date(1899, 11, 31) should not be undefined"); -} +assert.notSameValue(new Date(1899, 11, 31), undefined, 'new Date(1899, 11, 31) is expected to not equal ``undefined``'); var x13 = new Date(1899, 11, 31); -if (typeof x13 !== "object") { - throw new Test262Error("#1.3: typeof new Date(1899, 11, 31) should be 'object'"); -} +assert.sameValue(typeof x13, "object", 'The value of `typeof x13` is expected to be "object"'); var x14 = new Date(1899, 11, 31); -if (x14 === undefined) { - throw new Test262Error("#1.4: new Date(1899, 11, 31) should not be undefined"); -} +assert.notSameValue(x14, undefined, 'The value of x14 is expected to not equal ``undefined``'); -if (typeof new Date(1899, 12, 1) !== "object") { - throw new Test262Error("#2.1: typeof new Date(1899, 12, 1) should be 'object'"); -} +assert.sameValue( + typeof new Date(1899, 12, 1), + "object", + 'The value of `typeof new Date(1899, 12, 1)` is expected to be "object"' +); -if (new Date(1899, 12, 1) === undefined) { - throw new Test262Error("#2.2: new Date(1899, 12, 1) should not be undefined"); -} +assert.notSameValue(new Date(1899, 12, 1), undefined, 'new Date(1899, 12, 1) is expected to not equal ``undefined``'); var x23 = new Date(1899, 12, 1); -if (typeof x23 !== "object") { - throw new Test262Error("#2.3: typeof new Date(1899, 12, 1) should be 'object'"); -} +assert.sameValue(typeof x23, "object", 'The value of `typeof x23` is expected to be "object"'); var x24 = new Date(1899, 12, 1); -if (x24 === undefined) { - throw new Test262Error("#2.4: new Date(1899, 12, 1) should not be undefined"); -} +assert.notSameValue(x24, undefined, 'The value of x24 is expected to not equal ``undefined``'); -if (typeof new Date(1900, 0, 1) !== "object") { - throw new Test262Error("#3.1: typeof new Date(1900, 0, 1) should be 'object'"); -} +assert.sameValue( + typeof new Date(1900, 0, 1), + "object", + 'The value of `typeof new Date(1900, 0, 1)` is expected to be "object"' +); -if (new Date(1900, 0, 1) === undefined) { - throw new Test262Error("#3.2: new Date(1900, 0, 1) should not be undefined"); -} +assert.notSameValue(new Date(1900, 0, 1), undefined, 'new Date(1900, 0, 1) is expected to not equal ``undefined``'); var x33 = new Date(1900, 0, 1); -if (typeof x33 !== "object") { - throw new Test262Error("#3.3: typeof new Date(1900, 0, 1) should be 'object'"); -} +assert.sameValue(typeof x33, "object", 'The value of `typeof x33` is expected to be "object"'); var x34 = new Date(1900, 0, 1); -if (x34 === undefined) { - throw new Test262Error("#3.4: new Date(1900, 0, 1) should not be undefined"); -} +assert.notSameValue(x34, undefined, 'The value of x34 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 11, 31) !== "object") { - throw new Test262Error("#4.1: typeof new Date(1969, 11, 31) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 11, 31), + "object", + 'The value of `typeof new Date(1969, 11, 31)` is expected to be "object"' +); -if (new Date(1969, 11, 31) === undefined) { - throw new Test262Error("#4.2: new Date(1969, 11, 31) should not be undefined"); -} +assert.notSameValue(new Date(1969, 11, 31), undefined, 'new Date(1969, 11, 31) is expected to not equal ``undefined``'); var x43 = new Date(1969, 11, 31); -if (typeof x43 !== "object") { - throw new Test262Error("#4.3: typeof new Date(1969, 11, 31) should be 'object'"); -} +assert.sameValue(typeof x43, "object", 'The value of `typeof x43` is expected to be "object"'); var x44 = new Date(1969, 11, 31); -if (x44 === undefined) { - throw new Test262Error("#4.4: new Date(1969, 11, 31) should not be undefined"); -} +assert.notSameValue(x44, undefined, 'The value of x44 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 12, 1) !== "object") { - throw new Test262Error("#5.1: typeof new Date(1969, 12, 1) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 12, 1), + "object", + 'The value of `typeof new Date(1969, 12, 1)` is expected to be "object"' +); -if (new Date(1969, 12, 1) === undefined) { - throw new Test262Error("#5.2: new Date(1969, 12, 1) should not be undefined"); -} +assert.notSameValue(new Date(1969, 12, 1), undefined, 'new Date(1969, 12, 1) is expected to not equal ``undefined``'); var x53 = new Date(1969, 12, 1); -if (typeof x53 !== "object") { - throw new Test262Error("#5.3: typeof new Date(1969, 12, 1) should be 'object'"); -} +assert.sameValue(typeof x53, "object", 'The value of `typeof x53` is expected to be "object"'); var x54 = new Date(1969, 12, 1); -if (x54 === undefined) { - throw new Test262Error("#5.4: new Date(1969, 12, 1) should not be undefined"); -} +assert.notSameValue(x54, undefined, 'The value of x54 is expected to not equal ``undefined``'); -if (typeof new Date(1970, 0, 1) !== "object") { - throw new Test262Error("#6.1: typeof new Date(1970, 0, 1) should be 'object'"); -} +assert.sameValue( + typeof new Date(1970, 0, 1), + "object", + 'The value of `typeof new Date(1970, 0, 1)` is expected to be "object"' +); -if (new Date(1970, 0, 1) === undefined) { - throw new Test262Error("#6.2: new Date(1970, 0, 1) should not be undefined"); -} +assert.notSameValue(new Date(1970, 0, 1), undefined, 'new Date(1970, 0, 1) is expected to not equal ``undefined``'); var x63 = new Date(1970, 0, 1); -if (typeof x63 !== "object") { - throw new Test262Error("#6.3: typeof new Date(1970, 0, 1) should be 'object'"); -} +assert.sameValue(typeof x63, "object", 'The value of `typeof x63` is expected to be "object"'); var x64 = new Date(1970, 0, 1); -if (x64 === undefined) { - throw new Test262Error("#6.4: new Date(1970, 0, 1) should not be undefined"); -} +assert.notSameValue(x64, undefined, 'The value of x64 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 11, 31) !== "object") { - throw new Test262Error("#7.1: typeof new Date(1999, 11, 31) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 11, 31), + "object", + 'The value of `typeof new Date(1999, 11, 31)` is expected to be "object"' +); -if (new Date(1999, 11, 31) === undefined) { - throw new Test262Error("#7.2: new Date(1999, 11, 31) should not be undefined"); -} +assert.notSameValue(new Date(1999, 11, 31), undefined, 'new Date(1999, 11, 31) is expected to not equal ``undefined``'); var x73 = new Date(1999, 11, 31); -if (typeof x73 !== "object") { - throw new Test262Error("#7.3: typeof new Date(1999, 11, 31) should be 'object'"); -} +assert.sameValue(typeof x73, "object", 'The value of `typeof x73` is expected to be "object"'); var x74 = new Date(1999, 11, 31); -if (x74 === undefined) { - throw new Test262Error("#7.4: new Date(1999, 11, 31) should not be undefined"); -} +assert.notSameValue(x74, undefined, 'The value of x74 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 12, 1) !== "object") { - throw new Test262Error("#8.1: typeof new Date(1999, 12, 1) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 12, 1), + "object", + 'The value of `typeof new Date(1999, 12, 1)` is expected to be "object"' +); -if (new Date(1999, 12, 1) === undefined) { - throw new Test262Error("#8.2: new Date(1999, 12, 1) should not be undefined"); -} +assert.notSameValue(new Date(1999, 12, 1), undefined, 'new Date(1999, 12, 1) is expected to not equal ``undefined``'); var x83 = new Date(1999, 12, 1); -if (typeof x83 !== "object") { - throw new Test262Error("#8.3: typeof new Date(1999, 12, 1) should be 'object'"); -} +assert.sameValue(typeof x83, "object", 'The value of `typeof x83` is expected to be "object"'); var x84 = new Date(1999, 12, 1); -if (x84 === undefined) { - throw new Test262Error("#8.4: new Date(1999, 12, 1) should not be undefined"); -} +assert.notSameValue(x84, undefined, 'The value of x84 is expected to not equal ``undefined``'); -if (typeof new Date(2000, 0, 1) !== "object") { - throw new Test262Error("#9.1: typeof new Date(2000, 0, 1) should be 'object'"); -} +assert.sameValue( + typeof new Date(2000, 0, 1), + "object", + 'The value of `typeof new Date(2000, 0, 1)` is expected to be "object"' +); -if (new Date(2000, 0, 1) === undefined) { - throw new Test262Error("#9.2: new Date(2000, 0, 1) should not be undefined"); -} +assert.notSameValue(new Date(2000, 0, 1), undefined, 'new Date(2000, 0, 1) is expected to not equal ``undefined``'); var x93 = new Date(2000, 0, 1); -if (typeof x93 !== "object") { - throw new Test262Error("#9.3: typeof new Date(2000, 0, 1) should be 'object'"); -} +assert.sameValue(typeof x93, "object", 'The value of `typeof x93` is expected to be "object"'); var x94 = new Date(2000, 0, 1); -if (x94 === undefined) { - throw new Test262Error("#9.4: new Date(2000, 0, 1) should not be undefined"); -} +assert.notSameValue(x94, undefined, 'The value of x94 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 11, 31) !== "object") { - throw new Test262Error("#10.1: typeof new Date(2099, 11, 31) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 11, 31), + "object", + 'The value of `typeof new Date(2099, 11, 31)` is expected to be "object"' +); -if (new Date(2099, 11, 31) === undefined) { - throw new Test262Error("#10.2: new Date(2099, 11, 31) should not be undefined"); -} +assert.notSameValue(new Date(2099, 11, 31), undefined, 'new Date(2099, 11, 31) is expected to not equal ``undefined``'); var x103 = new Date(2099, 11, 31); -if (typeof x103 !== "object") { - throw new Test262Error("#10.3: typeof new Date(2099, 11, 31) should be 'object'"); -} +assert.sameValue(typeof x103, "object", 'The value of `typeof x103` is expected to be "object"'); var x104 = new Date(2099, 11, 31); -if (x104 === undefined) { - throw new Test262Error("#10.4: new Date(2099, 11, 31) should not be undefined"); -} +assert.notSameValue(x104, undefined, 'The value of x104 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 12, 1) !== "object") { - throw new Test262Error("#11.1: typeof new Date(2099, 12, 1) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 12, 1), + "object", + 'The value of `typeof new Date(2099, 12, 1)` is expected to be "object"' +); -if (new Date(2099, 12, 1) === undefined) { - throw new Test262Error("#11.2: new Date(2099, 12, 1) should not be undefined"); -} +assert.notSameValue(new Date(2099, 12, 1), undefined, 'new Date(2099, 12, 1) is expected to not equal ``undefined``'); var x113 = new Date(2099, 12, 1); -if (typeof x113 !== "object") { - throw new Test262Error("#11.3: typeof new Date(2099, 12, 1) should be 'object'"); -} +assert.sameValue(typeof x113, "object", 'The value of `typeof x113` is expected to be "object"'); var x114 = new Date(2099, 12, 1); -if (x114 === undefined) { - throw new Test262Error("#11.4: new Date(2099, 12, 1) should not be undefined"); -} +assert.notSameValue(x114, undefined, 'The value of x114 is expected to not equal ``undefined``'); -if (typeof new Date(2100, 0, 1) !== "object") { - throw new Test262Error("#12.1: typeof new Date(2100, 0, 1) should be 'object'"); -} +assert.sameValue( + typeof new Date(2100, 0, 1), + "object", + 'The value of `typeof new Date(2100, 0, 1)` is expected to be "object"' +); -if (new Date(2100, 0, 1) === undefined) { - throw new Test262Error("#12.2: new Date(2100, 0, 1) should not be undefined"); -} +assert.notSameValue(new Date(2100, 0, 1), undefined, 'new Date(2100, 0, 1) is expected to not equal ``undefined``'); var x123 = new Date(2100, 0, 1); -if (typeof x123 !== "object") { - throw new Test262Error("#12.3: typeof new Date(2100, 0, 1) should be 'object'"); -} +assert.sameValue(typeof x123, "object", 'The value of `typeof x123` is expected to be "object"'); var x124 = new Date(2100, 0, 1); -if (x124 === undefined) { - throw new Test262Error("#12.4: new Date(2100, 0, 1) should not be undefined"); -} +assert.notSameValue(x124, undefined, 'The value of x124 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T3.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T3.js index 10039468b120..9494ea056ae7 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T3.js @@ -8,221 +8,204 @@ info: | esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 4 arguments, (year, month, date, hours) ---*/ +assert.sameValue( + typeof new Date(1899, 11, 31, 23), + "object", + 'The value of `typeof new Date(1899, 11, 31, 23)` is expected to be "object"' +); -if (typeof new Date(1899, 11, 31, 23) !== "object") { - throw new Test262Error("#1.1: typeof new Date(1899, 11, 31, 23) should be 'object'"); -} - -if (new Date(1899, 11, 31, 23) === undefined) { - throw new Test262Error("#1.2: new Date(1899, 11, 31, 23) should not be undefined"); -} +assert.notSameValue( + new Date(1899, 11, 31, 23), + undefined, + 'new Date(1899, 11, 31, 23) is expected to not equal ``undefined``' +); var x13 = new Date(1899, 11, 31, 23); -if (typeof x13 !== "object") { - throw new Test262Error("#1.3: typeof new Date(1899, 11, 31, 23) should be 'object'"); -} +assert.sameValue(typeof x13, "object", 'The value of `typeof x13` is expected to be "object"'); var x14 = new Date(1899, 11, 31, 23); -if (x14 === undefined) { - throw new Test262Error("#1.4: new Date(1899, 11, 31, 23) should not be undefined"); -} +assert.notSameValue(x14, undefined, 'The value of x14 is expected to not equal ``undefined``'); -if (typeof new Date(1899, 12, 1, 0) !== "object") { - throw new Test262Error("#2.1: typeof new Date(1899, 12, 1, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1899, 12, 1, 0), + "object", + 'The value of `typeof new Date(1899, 12, 1, 0)` is expected to be "object"' +); -if (new Date(1899, 12, 1, 0) === undefined) { - throw new Test262Error("#2.2: new Date(1899, 12, 1, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1899, 12, 1, 0), + undefined, + 'new Date(1899, 12, 1, 0) is expected to not equal ``undefined``' +); var x23 = new Date(1899, 12, 1, 0); -if (typeof x23 !== "object") { - throw new Test262Error("#2.3: typeof new Date(1899, 12, 1, 0) should be 'object'"); -} +assert.sameValue(typeof x23, "object", 'The value of `typeof x23` is expected to be "object"'); var x24 = new Date(1899, 12, 1, 0); -if (x24 === undefined) { - throw new Test262Error("#2.4: new Date(1899, 12, 1, 0) should not be undefined"); -} +assert.notSameValue(x24, undefined, 'The value of x24 is expected to not equal ``undefined``'); -if (typeof new Date(1900, 0, 1, 0) !== "object") { - throw new Test262Error("#3.1: typeof new Date(1900, 0, 1, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1900, 0, 1, 0), + "object", + 'The value of `typeof new Date(1900, 0, 1, 0)` is expected to be "object"' +); -if (new Date(1900, 0, 1, 0) === undefined) { - throw new Test262Error("#3.2: new Date(1900, 0, 1, 0) should not be undefined"); -} +assert.notSameValue(new Date(1900, 0, 1, 0), undefined, 'new Date(1900, 0, 1, 0) is expected to not equal ``undefined``'); var x33 = new Date(1900, 0, 1, 0); -if (typeof x33 !== "object") { - throw new Test262Error("#3.3: typeof new Date(1900, 0, 1, 0) should be 'object'"); -} +assert.sameValue(typeof x33, "object", 'The value of `typeof x33` is expected to be "object"'); var x34 = new Date(1900, 0, 1, 0); -if (x34 === undefined) { - throw new Test262Error("#3.4: new Date(1900, 0, 1, 0) should not be undefined"); -} +assert.notSameValue(x34, undefined, 'The value of x34 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 11, 31, 23) !== "object") { - throw new Test262Error("#4.1: typeof new Date(1969, 11, 31, 23) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 11, 31, 23), + "object", + 'The value of `typeof new Date(1969, 11, 31, 23)` is expected to be "object"' +); -if (new Date(1969, 11, 31, 23) === undefined) { - throw new Test262Error("#4.2: new Date(1969, 11, 31, 23) should not be undefined"); -} +assert.notSameValue( + new Date(1969, 11, 31, 23), + undefined, + 'new Date(1969, 11, 31, 23) is expected to not equal ``undefined``' +); var x43 = new Date(1969, 11, 31, 23); -if (typeof x43 !== "object") { - throw new Test262Error("#4.3: typeof new Date(1969, 11, 31, 23) should be 'object'"); -} +assert.sameValue(typeof x43, "object", 'The value of `typeof x43` is expected to be "object"'); var x44 = new Date(1969, 11, 31, 23); -if (x44 === undefined) { - throw new Test262Error("#4.4: new Date(1969, 11, 31, 23) should not be undefined"); -} +assert.notSameValue(x44, undefined, 'The value of x44 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 12, 1, 0) !== "object") { - throw new Test262Error("#5.1: typeof new Date(1969, 12, 1, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 12, 1, 0), + "object", + 'The value of `typeof new Date(1969, 12, 1, 0)` is expected to be "object"' +); -if (new Date(1969, 12, 1, 0) === undefined) { - throw new Test262Error("#5.2: new Date(1969, 12, 1, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1969, 12, 1, 0), + undefined, + 'new Date(1969, 12, 1, 0) is expected to not equal ``undefined``' +); var x53 = new Date(1969, 12, 1, 0); -if (typeof x53 !== "object") { - throw new Test262Error("#5.3: typeof new Date(1969, 12, 1, 0) should be 'object'"); -} +assert.sameValue(typeof x53, "object", 'The value of `typeof x53` is expected to be "object"'); var x54 = new Date(1969, 12, 1, 0); -if (x54 === undefined) { - throw new Test262Error("#5.4: new Date(1969, 12, 1, 0) should not be undefined"); -} +assert.notSameValue(x54, undefined, 'The value of x54 is expected to not equal ``undefined``'); -if (typeof new Date(1970, 0, 1, 0) !== "object") { - throw new Test262Error("#6.1: typeof new Date(1970, 0, 1, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1970, 0, 1, 0), + "object", + 'The value of `typeof new Date(1970, 0, 1, 0)` is expected to be "object"' +); -if (new Date(1970, 0, 1, 0) === undefined) { - throw new Test262Error("#6.2: new Date(1970, 0, 1, 0) should not be undefined"); -} +assert.notSameValue(new Date(1970, 0, 1, 0), undefined, 'new Date(1970, 0, 1, 0) is expected to not equal ``undefined``'); var x63 = new Date(1970, 0, 1, 0); -if (typeof x63 !== "object") { - throw new Test262Error("#6.3: typeof new Date(1970, 0, 1, 0) should be 'object'"); -} +assert.sameValue(typeof x63, "object", 'The value of `typeof x63` is expected to be "object"'); var x64 = new Date(1970, 0, 1, 0); -if (x64 === undefined) { - throw new Test262Error("#6.4: new Date(1970, 0, 1, 0) should not be undefined"); -} +assert.notSameValue(x64, undefined, 'The value of x64 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 11, 31, 23) !== "object") { - throw new Test262Error("#7.1: typeof new Date(1999, 11, 31, 23) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 11, 31, 23), + "object", + 'The value of `typeof new Date(1999, 11, 31, 23)` is expected to be "object"' +); -if (new Date(1999, 11, 31, 23) === undefined) { - throw new Test262Error("#7.2: new Date(1999, 11, 31, 23) should not be undefined"); -} +assert.notSameValue( + new Date(1999, 11, 31, 23), + undefined, + 'new Date(1999, 11, 31, 23) is expected to not equal ``undefined``' +); var x73 = new Date(1999, 11, 31, 23); -if (typeof x73 !== "object") { - throw new Test262Error("#7.3: typeof new Date(1999, 11, 31, 23) should be 'object'"); -} +assert.sameValue(typeof x73, "object", 'The value of `typeof x73` is expected to be "object"'); var x74 = new Date(1999, 11, 31, 23); -if (x74 === undefined) { - throw new Test262Error("#7.4: new Date(1999, 11, 31, 23) should not be undefined"); -} +assert.notSameValue(x74, undefined, 'The value of x74 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 12, 1, 0) !== "object") { - throw new Test262Error("#8.1: typeof new Date(1999, 12, 1, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 12, 1, 0), + "object", + 'The value of `typeof new Date(1999, 12, 1, 0)` is expected to be "object"' +); -if (new Date(1999, 12, 1, 0) === undefined) { - throw new Test262Error("#8.2: new Date(1999, 12, 1, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1999, 12, 1, 0), + undefined, + 'new Date(1999, 12, 1, 0) is expected to not equal ``undefined``' +); var x83 = new Date(1999, 12, 1, 0); -if (typeof x83 !== "object") { - throw new Test262Error("#8.3: typeof new Date(1999, 12, 1, 0) should be 'object'"); -} +assert.sameValue(typeof x83, "object", 'The value of `typeof x83` is expected to be "object"'); var x84 = new Date(1999, 12, 1, 0); -if (x84 === undefined) { - throw new Test262Error("#8.4: new Date(1999, 12, 1, 0) should not be undefined"); -} +assert.notSameValue(x84, undefined, 'The value of x84 is expected to not equal ``undefined``'); -if (typeof new Date(2000, 0, 1, 0) !== "object") { - throw new Test262Error("#9.1: typeof new Date(2000, 0, 1, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2000, 0, 1, 0), + "object", + 'The value of `typeof new Date(2000, 0, 1, 0)` is expected to be "object"' +); -if (new Date(2000, 0, 1, 0) === undefined) { - throw new Test262Error("#9.2: new Date(2000, 0, 1, 0) should not be undefined"); -} +assert.notSameValue(new Date(2000, 0, 1, 0), undefined, 'new Date(2000, 0, 1, 0) is expected to not equal ``undefined``'); var x93 = new Date(2000, 0, 1, 0); -if (typeof x93 !== "object") { - throw new Test262Error("#9.3: typeof new Date(2000, 0, 1, 0) should be 'object'"); -} +assert.sameValue(typeof x93, "object", 'The value of `typeof x93` is expected to be "object"'); var x94 = new Date(2000, 0, 1, 0); -if (x94 === undefined) { - throw new Test262Error("#9.4: new Date(2000, 0, 1, 0) should not be undefined"); -} +assert.notSameValue(x94, undefined, 'The value of x94 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 11, 31, 23) !== "object") { - throw new Test262Error("#10.1: typeof new Date(2099, 11, 31, 23) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 11, 31, 23), + "object", + 'The value of `typeof new Date(2099, 11, 31, 23)` is expected to be "object"' +); -if (new Date(2099, 11, 31, 23) === undefined) { - throw new Test262Error("#10.2: new Date(2099, 11, 31, 23) should not be undefined"); -} +assert.notSameValue( + new Date(2099, 11, 31, 23), + undefined, + 'new Date(2099, 11, 31, 23) is expected to not equal ``undefined``' +); var x103 = new Date(2099, 11, 31, 23); -if (typeof x103 !== "object") { - throw new Test262Error("#10.3: typeof new Date(2099, 11, 31, 23) should be 'object'"); -} +assert.sameValue(typeof x103, "object", 'The value of `typeof x103` is expected to be "object"'); var x104 = new Date(2099, 11, 31, 23); -if (x104 === undefined) { - throw new Test262Error("#10.4: new Date(2099, 11, 31, 23) should not be undefined"); -} +assert.notSameValue(x104, undefined, 'The value of x104 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 12, 1, 0) !== "object") { - throw new Test262Error("#11.1: typeof new Date(2099, 12, 1, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 12, 1, 0), + "object", + 'The value of `typeof new Date(2099, 12, 1, 0)` is expected to be "object"' +); -if (new Date(2099, 12, 1, 0) === undefined) { - throw new Test262Error("#11.2: new Date(2099, 12, 1, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2099, 12, 1, 0), + undefined, + 'new Date(2099, 12, 1, 0) is expected to not equal ``undefined``' +); var x113 = new Date(2099, 12, 1, 0); -if (typeof x113 !== "object") { - throw new Test262Error("#11.3: typeof new Date(2099, 12, 1, 0) should be 'object'"); -} +assert.sameValue(typeof x113, "object", 'The value of `typeof x113` is expected to be "object"'); var x114 = new Date(2099, 12, 1, 0); -if (x114 === undefined) { - throw new Test262Error("#11.4: new Date(2099, 12, 1, 0) should not be undefined"); -} +assert.notSameValue(x114, undefined, 'The value of x114 is expected to not equal ``undefined``'); -if (typeof new Date(2100, 0, 1, 0) !== "object") { - throw new Test262Error("#12.1: typeof new Date(2100, 0, 1, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2100, 0, 1, 0), + "object", + 'The value of `typeof new Date(2100, 0, 1, 0)` is expected to be "object"' +); -if (new Date(2100, 0, 1, 0) === undefined) { - throw new Test262Error("#12.2: new Date(2100, 0, 1, 0) should not be undefined"); -} +assert.notSameValue(new Date(2100, 0, 1, 0), undefined, 'new Date(2100, 0, 1, 0) is expected to not equal ``undefined``'); var x123 = new Date(2100, 0, 1, 0); -if (typeof x123 !== "object") { - throw new Test262Error("#12.3: typeof new Date(2100, 0, 1, 0) should be 'object'"); -} +assert.sameValue(typeof x123, "object", 'The value of `typeof x123` is expected to be "object"'); var x124 = new Date(2100, 0, 1, 0); -if (x124 === undefined) { - throw new Test262Error("#12.4: new Date(2100, 0, 1, 0) should not be undefined"); -} +assert.notSameValue(x124, undefined, 'The value of x124 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T4.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T4.js index e9e85b1f32fc..a0bc64f510af 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T4.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T4.js @@ -8,221 +8,220 @@ info: | esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 5 arguments, (year, month, date, hours, minutes) ---*/ +assert.sameValue( + typeof new Date(1899, 11, 31, 23, 59), + "object", + 'The value of `typeof new Date(1899, 11, 31, 23, 59)` is expected to be "object"' +); -if (typeof new Date(1899, 11, 31, 23, 59) !== "object") { - throw new Test262Error("#1.1: typeof new Date(1899, 11, 31, 23, 59) should be 'object'"); -} - -if (new Date(1899, 11, 31, 23, 59) === undefined) { - throw new Test262Error("#1.2: new Date(1899, 11, 31, 23, 59) should not be undefined"); -} +assert.notSameValue( + new Date(1899, 11, 31, 23, 59), + undefined, + 'new Date(1899, 11, 31, 23, 59) is expected to not equal ``undefined``' +); var x13 = new Date(1899, 11, 31, 23, 59); -if (typeof x13 !== "object") { - throw new Test262Error("#1.3: typeof new Date(1899, 11, 31, 23, 59) should be 'object'"); -} +assert.sameValue(typeof x13, "object", 'The value of `typeof x13` is expected to be "object"'); var x14 = new Date(1899, 11, 31, 23, 59); -if (x14 === undefined) { - throw new Test262Error("#1.4: new Date(1899, 11, 31, 23, 59) should not be undefined"); -} +assert.notSameValue(x14, undefined, 'The value of x14 is expected to not equal ``undefined``'); -if (typeof new Date(1899, 12, 1, 0, 0) !== "object") { - throw new Test262Error("#2.1: typeof new Date(1899, 12, 1, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1899, 12, 1, 0, 0), + "object", + 'The value of `typeof new Date(1899, 12, 1, 0, 0)` is expected to be "object"' +); -if (new Date(1899, 12, 1, 0, 0) === undefined) { - throw new Test262Error("#2.2: new Date(1899, 12, 1, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1899, 12, 1, 0, 0), + undefined, + 'new Date(1899, 12, 1, 0, 0) is expected to not equal ``undefined``' +); var x23 = new Date(1899, 12, 1, 0, 0); -if (typeof x23 !== "object") { - throw new Test262Error("#2.3: typeof new Date(1899, 12, 1, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x23, "object", 'The value of `typeof x23` is expected to be "object"'); var x24 = new Date(1899, 12, 1, 0, 0); -if (x24 === undefined) { - throw new Test262Error("#2.4: new Date(1899, 12, 1, 0, 0) should not be undefined"); -} +assert.notSameValue(x24, undefined, 'The value of x24 is expected to not equal ``undefined``'); -if (typeof new Date(1900, 0, 1, 0, 0) !== "object") { - throw new Test262Error("#3.1: typeof new Date(1900, 0, 1, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1900, 0, 1, 0, 0), + "object", + 'The value of `typeof new Date(1900, 0, 1, 0, 0)` is expected to be "object"' +); -if (new Date(1900, 0, 1, 0, 0) === undefined) { - throw new Test262Error("#3.2: new Date(1900, 0, 1, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1900, 0, 1, 0, 0), + undefined, + 'new Date(1900, 0, 1, 0, 0) is expected to not equal ``undefined``' +); var x33 = new Date(1900, 0, 1, 0, 0); -if (typeof x33 !== "object") { - throw new Test262Error("#3.3: typeof new Date(1900, 0, 1, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x33, "object", 'The value of `typeof x33` is expected to be "object"'); var x34 = new Date(1900, 0, 1, 0, 0); -if (x34 === undefined) { - throw new Test262Error("#3.4: new Date(1900, 0, 1, 0, 0) should not be undefined"); -} +assert.notSameValue(x34, undefined, 'The value of x34 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 11, 31, 23, 59) !== "object") { - throw new Test262Error("#4.1: typeof new Date(1969, 11, 31, 23, 59) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 11, 31, 23, 59), + "object", + 'The value of `typeof new Date(1969, 11, 31, 23, 59)` is expected to be "object"' +); -if (new Date(1969, 11, 31, 23, 59) === undefined) { - throw new Test262Error("#4.2: new Date(1969, 11, 31, 23, 59) should not be undefined"); -} +assert.notSameValue( + new Date(1969, 11, 31, 23, 59), + undefined, + 'new Date(1969, 11, 31, 23, 59) is expected to not equal ``undefined``' +); var x43 = new Date(1969, 11, 31, 23, 59); -if (typeof x43 !== "object") { - throw new Test262Error("#4.3: typeof new Date(1969, 11, 31, 23, 59) should be 'object'"); -} +assert.sameValue(typeof x43, "object", 'The value of `typeof x43` is expected to be "object"'); var x44 = new Date(1969, 11, 31, 23, 59); -if (x44 === undefined) { - throw new Test262Error("#4.4: new Date(1969, 11, 31, 23, 59) should not be undefined"); -} +assert.notSameValue(x44, undefined, 'The value of x44 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 12, 1, 0, 0) !== "object") { - throw new Test262Error("#5.1: typeof new Date(1969, 12, 1, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 12, 1, 0, 0), + "object", + 'The value of `typeof new Date(1969, 12, 1, 0, 0)` is expected to be "object"' +); -if (new Date(1969, 12, 1, 0, 0) === undefined) { - throw new Test262Error("#5.2: new Date(1969, 12, 1, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1969, 12, 1, 0, 0), + undefined, + 'new Date(1969, 12, 1, 0, 0) is expected to not equal ``undefined``' +); var x53 = new Date(1969, 12, 1, 0, 0); -if (typeof x53 !== "object") { - throw new Test262Error("#5.3: typeof new Date(1969, 12, 1, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x53, "object", 'The value of `typeof x53` is expected to be "object"'); var x54 = new Date(1969, 12, 1, 0, 0); -if (x54 === undefined) { - throw new Test262Error("#5.4: new Date(1969, 12, 1, 0, 0) should not be undefined"); -} +assert.notSameValue(x54, undefined, 'The value of x54 is expected to not equal ``undefined``'); -if (typeof new Date(1970, 0, 1, 0, 0) !== "object") { - throw new Test262Error("#6.1: typeof new Date(1970, 0, 1, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1970, 0, 1, 0, 0), + "object", + 'The value of `typeof new Date(1970, 0, 1, 0, 0)` is expected to be "object"' +); -if (new Date(1970, 0, 1, 0, 0) === undefined) { - throw new Test262Error("#6.2: new Date(1970, 0, 1, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1970, 0, 1, 0, 0), + undefined, + 'new Date(1970, 0, 1, 0, 0) is expected to not equal ``undefined``' +); var x63 = new Date(1970, 0, 1, 0, 0); -if (typeof x63 !== "object") { - throw new Test262Error("#6.3: typeof new Date(1970, 0, 1, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x63, "object", 'The value of `typeof x63` is expected to be "object"'); var x64 = new Date(1970, 0, 1, 0, 0); -if (x64 === undefined) { - throw new Test262Error("#6.4: new Date(1970, 0, 1, 0, 0) should not be undefined"); -} +assert.notSameValue(x64, undefined, 'The value of x64 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 11, 31, 23, 59) !== "object") { - throw new Test262Error("#7.1: typeof new Date(1999, 11, 31, 23, 59) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 11, 31, 23, 59), + "object", + 'The value of `typeof new Date(1999, 11, 31, 23, 59)` is expected to be "object"' +); -if (new Date(1999, 11, 31, 23, 59) === undefined) { - throw new Test262Error("#7.2: new Date(1999, 11, 31, 23, 59) should not be undefined"); -} +assert.notSameValue( + new Date(1999, 11, 31, 23, 59), + undefined, + 'new Date(1999, 11, 31, 23, 59) is expected to not equal ``undefined``' +); var x73 = new Date(1999, 11, 31, 23, 59); -if (typeof x73 !== "object") { - throw new Test262Error("#7.3: typeof new Date(1999, 11, 31, 23, 59) should be 'object'"); -} +assert.sameValue(typeof x73, "object", 'The value of `typeof x73` is expected to be "object"'); var x74 = new Date(1999, 11, 31, 23, 59); -if (x74 === undefined) { - throw new Test262Error("#7.4: new Date(1999, 11, 31, 23, 59) should not be undefined"); -} +assert.notSameValue(x74, undefined, 'The value of x74 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 12, 1, 0, 0) !== "object") { - throw new Test262Error("#8.1: typeof new Date(1999, 12, 1, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 12, 1, 0, 0), + "object", + 'The value of `typeof new Date(1999, 12, 1, 0, 0)` is expected to be "object"' +); -if (new Date(1999, 12, 1, 0, 0) === undefined) { - throw new Test262Error("#8.2: new Date(1999, 12, 1, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1999, 12, 1, 0, 0), + undefined, + 'new Date(1999, 12, 1, 0, 0) is expected to not equal ``undefined``' +); var x83 = new Date(1999, 12, 1, 0, 0); -if (typeof x83 !== "object") { - throw new Test262Error("#8.3: typeof new Date(1999, 12, 1, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x83, "object", 'The value of `typeof x83` is expected to be "object"'); var x84 = new Date(1999, 12, 1, 0, 0); -if (x84 === undefined) { - throw new Test262Error("#8.4: new Date(1999, 12, 1, 0, 0) should not be undefined"); -} +assert.notSameValue(x84, undefined, 'The value of x84 is expected to not equal ``undefined``'); -if (typeof new Date(2000, 0, 1, 0, 0) !== "object") { - throw new Test262Error("#9.1: typeof new Date(2000, 0, 1, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2000, 0, 1, 0, 0), + "object", + 'The value of `typeof new Date(2000, 0, 1, 0, 0)` is expected to be "object"' +); -if (new Date(2000, 0, 1, 0, 0) === undefined) { - throw new Test262Error("#9.2: new Date(2000, 0, 1, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2000, 0, 1, 0, 0), + undefined, + 'new Date(2000, 0, 1, 0, 0) is expected to not equal ``undefined``' +); var x93 = new Date(2000, 0, 1, 0, 0); -if (typeof x93 !== "object") { - throw new Test262Error("#9.3: typeof new Date(2000, 0, 1, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x93, "object", 'The value of `typeof x93` is expected to be "object"'); var x94 = new Date(2000, 0, 1, 0, 0); -if (x94 === undefined) { - throw new Test262Error("#9.4: new Date(2000, 0, 1, 0, 0) should not be undefined"); -} +assert.notSameValue(x94, undefined, 'The value of x94 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 11, 31, 23, 59) !== "object") { - throw new Test262Error("#10.1: typeof new Date(2099, 11, 31, 23, 59) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 11, 31, 23, 59), + "object", + 'The value of `typeof new Date(2099, 11, 31, 23, 59)` is expected to be "object"' +); -if (new Date(2099, 11, 31, 23, 59) === undefined) { - throw new Test262Error("#10.2: new Date(2099, 11, 31, 23, 59) should not be undefined"); -} +assert.notSameValue( + new Date(2099, 11, 31, 23, 59), + undefined, + 'new Date(2099, 11, 31, 23, 59) is expected to not equal ``undefined``' +); var x103 = new Date(2099, 11, 31, 23, 59); -if (typeof x103 !== "object") { - throw new Test262Error("#10.3: typeof new Date(2099, 11, 31, 23, 59) should be 'object'"); -} +assert.sameValue(typeof x103, "object", 'The value of `typeof x103` is expected to be "object"'); var x104 = new Date(2099, 11, 31, 23, 59); -if (x104 === undefined) { - throw new Test262Error("#10.4: new Date(2099, 11, 31, 23, 59) should not be undefined"); -} +assert.notSameValue(x104, undefined, 'The value of x104 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 12, 1, 0, 0) !== "object") { - throw new Test262Error("#11.1: typeof new Date(2099, 12, 1, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 12, 1, 0, 0), + "object", + 'The value of `typeof new Date(2099, 12, 1, 0, 0)` is expected to be "object"' +); -if (new Date(2099, 12, 1, 0, 0) === undefined) { - throw new Test262Error("#11.2: new Date(2099, 12, 1, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2099, 12, 1, 0, 0), + undefined, + 'new Date(2099, 12, 1, 0, 0) is expected to not equal ``undefined``' +); var x113 = new Date(2099, 12, 1, 0, 0); -if (typeof x113 !== "object") { - throw new Test262Error("#11.3: typeof new Date(2099, 12, 1, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x113, "object", 'The value of `typeof x113` is expected to be "object"'); var x114 = new Date(2099, 12, 1, 0, 0); -if (x114 === undefined) { - throw new Test262Error("#11.4: new Date(2099, 12, 1, 0, 0) should not be undefined"); -} +assert.notSameValue(x114, undefined, 'The value of x114 is expected to not equal ``undefined``'); -if (typeof new Date(2100, 0, 1, 0, 0) !== "object") { - throw new Test262Error("#12.1: typeof new Date(2100, 0, 1, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2100, 0, 1, 0, 0), + "object", + 'The value of `typeof new Date(2100, 0, 1, 0, 0)` is expected to be "object"' +); -if (new Date(2100, 0, 1, 0, 0) === undefined) { - throw new Test262Error("#12.2: new Date(2100, 0, 1, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2100, 0, 1, 0, 0), + undefined, + 'new Date(2100, 0, 1, 0, 0) is expected to not equal ``undefined``' +); var x123 = new Date(2100, 0, 1, 0, 0); -if (typeof x123 !== "object") { - throw new Test262Error("#12.3: typeof new Date(2100, 0, 1, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x123, "object", 'The value of `typeof x123` is expected to be "object"'); var x124 = new Date(2100, 0, 1, 0, 0); -if (x124 === undefined) { - throw new Test262Error("#12.4: new Date(2100, 0, 1, 0, 0) should not be undefined"); -} +assert.notSameValue(x124, undefined, 'The value of x124 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T5.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T5.js index 10d847c40233..440c5cea98ea 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T5.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T5.js @@ -8,221 +8,220 @@ info: | esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 6 arguments, (year, month, date, hours, minutes, seconds) ---*/ +assert.sameValue( + typeof new Date(1899, 11, 31, 23, 59, 59), + "object", + 'The value of `typeof new Date(1899, 11, 31, 23, 59, 59)` is expected to be "object"' +); -if (typeof new Date(1899, 11, 31, 23, 59, 59) !== "object") { - throw new Test262Error("#1.1: typeof new Date(1899, 11, 31, 23, 59, 59) should be 'object'"); -} - -if (new Date(1899, 11, 31, 23, 59, 59) === undefined) { - throw new Test262Error("#1.2: new Date(1899, 11, 31, 23, 59, 59) should not be undefined"); -} +assert.notSameValue( + new Date(1899, 11, 31, 23, 59, 59), + undefined, + 'new Date(1899, 11, 31, 23, 59, 59) is expected to not equal ``undefined``' +); var x13 = new Date(1899, 11, 31, 23, 59, 59); -if (typeof x13 !== "object") { - throw new Test262Error("#1.3: typeof new Date(1899, 11, 31, 23, 59, 59) should be 'object'"); -} +assert.sameValue(typeof x13, "object", 'The value of `typeof x13` is expected to be "object"'); var x14 = new Date(1899, 11, 31, 23, 59, 59); -if (x14 === undefined) { - throw new Test262Error("#1.4: new Date(1899, 11, 31, 23, 59, 59) should not be undefined"); -} +assert.notSameValue(x14, undefined, 'The value of x14 is expected to not equal ``undefined``'); -if (typeof new Date(1899, 12, 1, 0, 0, 0) !== "object") { - throw new Test262Error("#2.1: typeof new Date(1899, 12, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1899, 12, 1, 0, 0, 0), + "object", + 'The value of `typeof new Date(1899, 12, 1, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1899, 12, 1, 0, 0, 0) === undefined) { - throw new Test262Error("#2.2: new Date(1899, 12, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1899, 12, 1, 0, 0, 0), + undefined, + 'new Date(1899, 12, 1, 0, 0, 0) is expected to not equal ``undefined``' +); var x23 = new Date(1899, 12, 1, 0, 0, 0); -if (typeof x23 !== "object") { - throw new Test262Error("#2.3: typeof new Date(1899, 12, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x23, "object", 'The value of `typeof x23` is expected to be "object"'); var x24 = new Date(1899, 12, 1, 0, 0, 0); -if (x24 === undefined) { - throw new Test262Error("#2.4: new Date(1899, 12, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x24, undefined, 'The value of x24 is expected to not equal ``undefined``'); -if (typeof new Date(1900, 0, 1, 0, 0, 0) !== "object") { - throw new Test262Error("#3.1: typeof new Date(1900, 0, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1900, 0, 1, 0, 0, 0), + "object", + 'The value of `typeof new Date(1900, 0, 1, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1900, 0, 1, 0, 0, 0) === undefined) { - throw new Test262Error("#3.2: new Date(1900, 0, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1900, 0, 1, 0, 0, 0), + undefined, + 'new Date(1900, 0, 1, 0, 0, 0) is expected to not equal ``undefined``' +); var x33 = new Date(1900, 0, 1, 0, 0, 0); -if (typeof x33 !== "object") { - throw new Test262Error("#3.3: typeof new Date(1900, 0, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x33, "object", 'The value of `typeof x33` is expected to be "object"'); var x34 = new Date(1900, 0, 1, 0, 0, 0); -if (x34 === undefined) { - throw new Test262Error("#3.4: new Date(1900, 0, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x34, undefined, 'The value of x34 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 11, 31, 23, 59, 59) !== "object") { - throw new Test262Error("#4.1: typeof new Date(1969, 11, 31, 23, 59, 59) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 11, 31, 23, 59, 59), + "object", + 'The value of `typeof new Date(1969, 11, 31, 23, 59, 59)` is expected to be "object"' +); -if (new Date(1969, 11, 31, 23, 59, 59) === undefined) { - throw new Test262Error("#4.2: new Date(1969, 11, 31, 23, 59, 59) should not be undefined"); -} +assert.notSameValue( + new Date(1969, 11, 31, 23, 59, 59), + undefined, + 'new Date(1969, 11, 31, 23, 59, 59) is expected to not equal ``undefined``' +); var x43 = new Date(1969, 11, 31, 23, 59, 59); -if (typeof x43 !== "object") { - throw new Test262Error("#4.3: typeof new Date(1969, 11, 31, 23, 59, 59) should be 'object'"); -} +assert.sameValue(typeof x43, "object", 'The value of `typeof x43` is expected to be "object"'); var x44 = new Date(1969, 11, 31, 23, 59, 59); -if (x44 === undefined) { - throw new Test262Error("#4.4: new Date(1969, 11, 31, 23, 59, 59) should not be undefined"); -} +assert.notSameValue(x44, undefined, 'The value of x44 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 12, 1, 0, 0, 0) !== "object") { - throw new Test262Error("#5.1: typeof new Date(1969, 12, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 12, 1, 0, 0, 0), + "object", + 'The value of `typeof new Date(1969, 12, 1, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1969, 12, 1, 0, 0, 0) === undefined) { - throw new Test262Error("#5.2: new Date(1969, 12, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1969, 12, 1, 0, 0, 0), + undefined, + 'new Date(1969, 12, 1, 0, 0, 0) is expected to not equal ``undefined``' +); var x53 = new Date(1969, 12, 1, 0, 0, 0); -if (typeof x53 !== "object") { - throw new Test262Error("#5.3: typeof new Date(1969, 12, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x53, "object", 'The value of `typeof x53` is expected to be "object"'); var x54 = new Date(1969, 12, 1, 0, 0, 0); -if (x54 === undefined) { - throw new Test262Error("#5.4: new Date(1969, 12, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x54, undefined, 'The value of x54 is expected to not equal ``undefined``'); -if (typeof new Date(1970, 0, 1, 0, 0, 0) !== "object") { - throw new Test262Error("#6.1: typeof new Date(1970, 0, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1970, 0, 1, 0, 0, 0), + "object", + 'The value of `typeof new Date(1970, 0, 1, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1970, 0, 1, 0, 0, 0) === undefined) { - throw new Test262Error("#6.2: new Date(1970, 0, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1970, 0, 1, 0, 0, 0), + undefined, + 'new Date(1970, 0, 1, 0, 0, 0) is expected to not equal ``undefined``' +); var x63 = new Date(1970, 0, 1, 0, 0, 0); -if (typeof x63 !== "object") { - throw new Test262Error("#6.3: typeof new Date(1970, 0, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x63, "object", 'The value of `typeof x63` is expected to be "object"'); var x64 = new Date(1970, 0, 1, 0, 0, 0); -if (x64 === undefined) { - throw new Test262Error("#6.4: new Date(1970, 0, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x64, undefined, 'The value of x64 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 11, 31, 23, 59, 59) !== "object") { - throw new Test262Error("#7.1: typeof new Date(1999, 11, 31, 23, 59, 59) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 11, 31, 23, 59, 59), + "object", + 'The value of `typeof new Date(1999, 11, 31, 23, 59, 59)` is expected to be "object"' +); -if (new Date(1999, 11, 31, 23, 59, 59) === undefined) { - throw new Test262Error("#7.2: new Date(1999, 11, 31, 23, 59, 59) should not be undefined"); -} +assert.notSameValue( + new Date(1999, 11, 31, 23, 59, 59), + undefined, + 'new Date(1999, 11, 31, 23, 59, 59) is expected to not equal ``undefined``' +); var x73 = new Date(1999, 11, 31, 23, 59, 59); -if (typeof x73 !== "object") { - throw new Test262Error("#7.3: typeof new Date(1999, 11, 31, 23, 59, 59) should be 'object'"); -} +assert.sameValue(typeof x73, "object", 'The value of `typeof x73` is expected to be "object"'); var x74 = new Date(1999, 11, 31, 23, 59, 59); -if (x74 === undefined) { - throw new Test262Error("#7.4: new Date(1999, 11, 31, 23, 59, 59) should not be undefined"); -} +assert.notSameValue(x74, undefined, 'The value of x74 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 12, 1, 0, 0, 0) !== "object") { - throw new Test262Error("#8.1: typeof new Date(1999, 12, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 12, 1, 0, 0, 0), + "object", + 'The value of `typeof new Date(1999, 12, 1, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1999, 12, 1, 0, 0, 0) === undefined) { - throw new Test262Error("#8.2: new Date(1999, 12, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1999, 12, 1, 0, 0, 0), + undefined, + 'new Date(1999, 12, 1, 0, 0, 0) is expected to not equal ``undefined``' +); var x83 = new Date(1999, 12, 1, 0, 0, 0); -if (typeof x83 !== "object") { - throw new Test262Error("#8.3: typeof new Date(1999, 12, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x83, "object", 'The value of `typeof x83` is expected to be "object"'); var x84 = new Date(1999, 12, 1, 0, 0, 0); -if (x84 === undefined) { - throw new Test262Error("#8.4: new Date(1999, 12, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x84, undefined, 'The value of x84 is expected to not equal ``undefined``'); -if (typeof new Date(2000, 0, 1, 0, 0, 0) !== "object") { - throw new Test262Error("#9.1: typeof new Date(2000, 0, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2000, 0, 1, 0, 0, 0), + "object", + 'The value of `typeof new Date(2000, 0, 1, 0, 0, 0)` is expected to be "object"' +); -if (new Date(2000, 0, 1, 0, 0, 0) === undefined) { - throw new Test262Error("#9.2: new Date(2000, 0, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2000, 0, 1, 0, 0, 0), + undefined, + 'new Date(2000, 0, 1, 0, 0, 0) is expected to not equal ``undefined``' +); var x93 = new Date(2000, 0, 1, 0, 0, 0); -if (typeof x93 !== "object") { - throw new Test262Error("#9.3: typeof new Date(2000, 0, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x93, "object", 'The value of `typeof x93` is expected to be "object"'); var x94 = new Date(2000, 0, 1, 0, 0, 0); -if (x94 === undefined) { - throw new Test262Error("#9.4: new Date(2000, 0, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x94, undefined, 'The value of x94 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 11, 31, 23, 59, 59) !== "object") { - throw new Test262Error("#10.1: typeof new Date(2099, 11, 31, 23, 59, 59) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 11, 31, 23, 59, 59), + "object", + 'The value of `typeof new Date(2099, 11, 31, 23, 59, 59)` is expected to be "object"' +); -if (new Date(2099, 11, 31, 23, 59, 59) === undefined) { - throw new Test262Error("#10.2: new Date(2099, 11, 31, 23, 59, 59) should not be undefined"); -} +assert.notSameValue( + new Date(2099, 11, 31, 23, 59, 59), + undefined, + 'new Date(2099, 11, 31, 23, 59, 59) is expected to not equal ``undefined``' +); var x103 = new Date(2099, 11, 31, 23, 59, 59); -if (typeof x103 !== "object") { - throw new Test262Error("#10.3: typeof new Date(2099, 11, 31, 23, 59, 59) should be 'object'"); -} +assert.sameValue(typeof x103, "object", 'The value of `typeof x103` is expected to be "object"'); var x104 = new Date(2099, 11, 31, 23, 59, 59); -if (x104 === undefined) { - throw new Test262Error("#10.4: new Date(2099, 11, 31, 23, 59, 59) should not be undefined"); -} +assert.notSameValue(x104, undefined, 'The value of x104 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 12, 1, 0, 0, 0) !== "object") { - throw new Test262Error("#11.1: typeof new Date(2099, 12, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 12, 1, 0, 0, 0), + "object", + 'The value of `typeof new Date(2099, 12, 1, 0, 0, 0)` is expected to be "object"' +); -if (new Date(2099, 12, 1, 0, 0, 0) === undefined) { - throw new Test262Error("#11.2: new Date(2099, 12, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2099, 12, 1, 0, 0, 0), + undefined, + 'new Date(2099, 12, 1, 0, 0, 0) is expected to not equal ``undefined``' +); var x113 = new Date(2099, 12, 1, 0, 0, 0); -if (typeof x113 !== "object") { - throw new Test262Error("#11.3: typeof new Date(2099, 12, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x113, "object", 'The value of `typeof x113` is expected to be "object"'); var x114 = new Date(2099, 12, 1, 0, 0, 0); -if (x114 === undefined) { - throw new Test262Error("#11.4: new Date(2099, 12, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x114, undefined, 'The value of x114 is expected to not equal ``undefined``'); -if (typeof new Date(2100, 0, 1, 0, 0, 0) !== "object") { - throw new Test262Error("#12.1: typeof new Date(2100, 0, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2100, 0, 1, 0, 0, 0), + "object", + 'The value of `typeof new Date(2100, 0, 1, 0, 0, 0)` is expected to be "object"' +); -if (new Date(2100, 0, 1, 0, 0, 0) === undefined) { - throw new Test262Error("#12.2: new Date(2100, 0, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2100, 0, 1, 0, 0, 0), + undefined, + 'new Date(2100, 0, 1, 0, 0, 0) is expected to not equal ``undefined``' +); var x123 = new Date(2100, 0, 1, 0, 0, 0); -if (typeof x123 !== "object") { - throw new Test262Error("#12.3: typeof new Date(2100, 0, 1, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x123, "object", 'The value of `typeof x123` is expected to be "object"'); var x124 = new Date(2100, 0, 1, 0, 0, 0); -if (x124 === undefined) { - throw new Test262Error("#12.4: new Date(2100, 0, 1, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x124, undefined, 'The value of x124 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T6.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T6.js index f13df330142f..51b960e152fa 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T6.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A1_T6.js @@ -8,221 +8,220 @@ info: | esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 7 arguments, (year, month, date, hours, minutes, seconds, ms) ---*/ +assert.sameValue( + typeof new Date(1899, 11, 31, 23, 59, 59, 999), + "object", + 'The value of `typeof new Date(1899, 11, 31, 23, 59, 59, 999)` is expected to be "object"' +); -if (typeof new Date(1899, 11, 31, 23, 59, 59, 999) !== "object") { - throw new Test262Error("#1.1: typeof new Date(1899, 11, 31, 23, 59, 59, 999) should be 'object'"); -} - -if (new Date(1899, 11, 31, 23, 59, 59, 999) === undefined) { - throw new Test262Error("#1.2: new Date(1899, 11, 31, 23, 59, 59, 999) should not be undefined"); -} +assert.notSameValue( + new Date(1899, 11, 31, 23, 59, 59, 999), + undefined, + 'new Date(1899, 11, 31, 23, 59, 59, 999) is expected to not equal ``undefined``' +); var x13 = new Date(1899, 11, 31, 23, 59, 59, 999); -if (typeof x13 !== "object") { - throw new Test262Error("#1.3: typeof new Date(1899, 11, 31, 23, 59, 59, 999) should be 'object'"); -} +assert.sameValue(typeof x13, "object", 'The value of `typeof x13` is expected to be "object"'); var x14 = new Date(1899, 11, 31, 23, 59, 59, 999); -if (x14 === undefined) { - throw new Test262Error("#1.4: new Date(1899, 11, 31, 23, 59, 59, 999) should not be undefined"); -} +assert.notSameValue(x14, undefined, 'The value of x14 is expected to not equal ``undefined``'); -if (typeof new Date(1899, 12, 1, 0, 0, 0, 0) !== "object") { - throw new Test262Error("#2.1: typeof new Date(1899, 12, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1899, 12, 1, 0, 0, 0, 0), + "object", + 'The value of `typeof new Date(1899, 12, 1, 0, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1899, 12, 1, 0, 0, 0, 0) === undefined) { - throw new Test262Error("#2.2: new Date(1899, 12, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1899, 12, 1, 0, 0, 0, 0), + undefined, + 'new Date(1899, 12, 1, 0, 0, 0, 0) is expected to not equal ``undefined``' +); var x23 = new Date(1899, 12, 1, 0, 0, 0, 0); -if (typeof x23 !== "object") { - throw new Test262Error("#2.3: typeof new Date(1899, 12, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x23, "object", 'The value of `typeof x23` is expected to be "object"'); var x24 = new Date(1899, 12, 1, 0, 0, 0, 0); -if (x24 === undefined) { - throw new Test262Error("#2.4: new Date(1899, 12, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x24, undefined, 'The value of x24 is expected to not equal ``undefined``'); -if (typeof new Date(1900, 0, 1, 0, 0, 0, 0) !== "object") { - throw new Test262Error("#3.1: typeof new Date(1900, 0, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1900, 0, 1, 0, 0, 0, 0), + "object", + 'The value of `typeof new Date(1900, 0, 1, 0, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1900, 0, 1, 0, 0, 0, 0) === undefined) { - throw new Test262Error("#3.2: new Date(1900, 0, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1900, 0, 1, 0, 0, 0, 0), + undefined, + 'new Date(1900, 0, 1, 0, 0, 0, 0) is expected to not equal ``undefined``' +); var x33 = new Date(1900, 0, 1, 0, 0, 0, 0); -if (typeof x33 !== "object") { - throw new Test262Error("#3.3: typeof new Date(1900, 0, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x33, "object", 'The value of `typeof x33` is expected to be "object"'); var x34 = new Date(1900, 0, 1, 0, 0, 0, 0); -if (x34 === undefined) { - throw new Test262Error("#3.4: new Date(1900, 0, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x34, undefined, 'The value of x34 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 11, 31, 23, 59, 59, 999) !== "object") { - throw new Test262Error("#4.1: typeof new Date(1969, 11, 31, 23, 59, 59, 999) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 11, 31, 23, 59, 59, 999), + "object", + 'The value of `typeof new Date(1969, 11, 31, 23, 59, 59, 999)` is expected to be "object"' +); -if (new Date(1969, 11, 31, 23, 59, 59, 999) === undefined) { - throw new Test262Error("#4.2: new Date(1969, 11, 31, 23, 59, 59, 999) should not be undefined"); -} +assert.notSameValue( + new Date(1969, 11, 31, 23, 59, 59, 999), + undefined, + 'new Date(1969, 11, 31, 23, 59, 59, 999) is expected to not equal ``undefined``' +); var x43 = new Date(1969, 11, 31, 23, 59, 59, 999); -if (typeof x43 !== "object") { - throw new Test262Error("#4.3: typeof new Date(1969, 11, 31, 23, 59, 59, 999) should be 'object'"); -} +assert.sameValue(typeof x43, "object", 'The value of `typeof x43` is expected to be "object"'); var x44 = new Date(1969, 11, 31, 23, 59, 59, 999); -if (x44 === undefined) { - throw new Test262Error("#4.4: new Date(1969, 11, 31, 23, 59, 59, 999) should not be undefined"); -} +assert.notSameValue(x44, undefined, 'The value of x44 is expected to not equal ``undefined``'); -if (typeof new Date(1969, 12, 1, 0, 0, 0, 0) !== "object") { - throw new Test262Error("#5.1: typeof new Date(1969, 12, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1969, 12, 1, 0, 0, 0, 0), + "object", + 'The value of `typeof new Date(1969, 12, 1, 0, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1969, 12, 1, 0, 0, 0, 0) === undefined) { - throw new Test262Error("#5.2: new Date(1969, 12, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1969, 12, 1, 0, 0, 0, 0), + undefined, + 'new Date(1969, 12, 1, 0, 0, 0, 0) is expected to not equal ``undefined``' +); var x53 = new Date(1969, 12, 1, 0, 0, 0, 0); -if (typeof x53 !== "object") { - throw new Test262Error("#5.3: typeof new Date(1969, 12, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x53, "object", 'The value of `typeof x53` is expected to be "object"'); var x54 = new Date(1969, 12, 1, 0, 0, 0, 0); -if (x54 === undefined) { - throw new Test262Error("#5.4: new Date(1969, 12, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x54, undefined, 'The value of x54 is expected to not equal ``undefined``'); -if (typeof new Date(1970, 0, 1, 0, 0, 0, 0) !== "object") { - throw new Test262Error("#6.1: typeof new Date(1970, 0, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1970, 0, 1, 0, 0, 0, 0), + "object", + 'The value of `typeof new Date(1970, 0, 1, 0, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1970, 0, 1, 0, 0, 0, 0) === undefined) { - throw new Test262Error("#6.2: new Date(1970, 0, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1970, 0, 1, 0, 0, 0, 0), + undefined, + 'new Date(1970, 0, 1, 0, 0, 0, 0) is expected to not equal ``undefined``' +); var x63 = new Date(1970, 0, 1, 0, 0, 0, 0); -if (typeof x63 !== "object") { - throw new Test262Error("#6.3: typeof new Date(1970, 0, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x63, "object", 'The value of `typeof x63` is expected to be "object"'); var x64 = new Date(1970, 0, 1, 0, 0, 0, 0); -if (x64 === undefined) { - throw new Test262Error("#6.4: new Date(1970, 0, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x64, undefined, 'The value of x64 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 11, 31, 23, 59, 59, 999) !== "object") { - throw new Test262Error("#7.1: typeof new Date(1999, 11, 31, 23, 59, 59, 999) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 11, 31, 23, 59, 59, 999), + "object", + 'The value of `typeof new Date(1999, 11, 31, 23, 59, 59, 999)` is expected to be "object"' +); -if (new Date(1999, 11, 31, 23, 59, 59, 999) === undefined) { - throw new Test262Error("#7.2: new Date(1999, 11, 31, 23, 59, 59, 999) should not be undefined"); -} +assert.notSameValue( + new Date(1999, 11, 31, 23, 59, 59, 999), + undefined, + 'new Date(1999, 11, 31, 23, 59, 59, 999) is expected to not equal ``undefined``' +); var x73 = new Date(1999, 11, 31, 23, 59, 59, 999); -if (typeof x73 !== "object") { - throw new Test262Error("#7.3: typeof new Date(1999, 11, 31, 23, 59, 59, 999) should be 'object'"); -} +assert.sameValue(typeof x73, "object", 'The value of `typeof x73` is expected to be "object"'); var x74 = new Date(1999, 11, 31, 23, 59, 59, 999); -if (x74 === undefined) { - throw new Test262Error("#7.4: new Date(1999, 11, 31, 23, 59, 59, 999) should not be undefined"); -} +assert.notSameValue(x74, undefined, 'The value of x74 is expected to not equal ``undefined``'); -if (typeof new Date(1999, 12, 1, 0, 0, 0, 0) !== "object") { - throw new Test262Error("#8.1: typeof new Date(1999, 12, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(1999, 12, 1, 0, 0, 0, 0), + "object", + 'The value of `typeof new Date(1999, 12, 1, 0, 0, 0, 0)` is expected to be "object"' +); -if (new Date(1999, 12, 1, 0, 0, 0, 0) === undefined) { - throw new Test262Error("#8.2: new Date(1999, 12, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(1999, 12, 1, 0, 0, 0, 0), + undefined, + 'new Date(1999, 12, 1, 0, 0, 0, 0) is expected to not equal ``undefined``' +); var x83 = new Date(1999, 12, 1, 0, 0, 0, 0); -if (typeof x83 !== "object") { - throw new Test262Error("#8.3: typeof new Date(1999, 12, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x83, "object", 'The value of `typeof x83` is expected to be "object"'); var x84 = new Date(1999, 12, 1, 0, 0, 0, 0); -if (x84 === undefined) { - throw new Test262Error("#8.4: new Date(1999, 12, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x84, undefined, 'The value of x84 is expected to not equal ``undefined``'); -if (typeof new Date(2000, 0, 1, 0, 0, 0, 0) !== "object") { - throw new Test262Error("#9.1: typeof new Date(2000, 0, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2000, 0, 1, 0, 0, 0, 0), + "object", + 'The value of `typeof new Date(2000, 0, 1, 0, 0, 0, 0)` is expected to be "object"' +); -if (new Date(2000, 0, 1, 0, 0, 0, 0) === undefined) { - throw new Test262Error("#9.2: new Date(2000, 0, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2000, 0, 1, 0, 0, 0, 0), + undefined, + 'new Date(2000, 0, 1, 0, 0, 0, 0) is expected to not equal ``undefined``' +); var x93 = new Date(2000, 0, 1, 0, 0, 0, 0); -if (typeof x93 !== "object") { - throw new Test262Error("#9.3: typeof new Date(2000, 0, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x93, "object", 'The value of `typeof x93` is expected to be "object"'); var x94 = new Date(2000, 0, 1, 0, 0, 0, 0); -if (x94 === undefined) { - throw new Test262Error("#9.4: new Date(2000, 0, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x94, undefined, 'The value of x94 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 11, 31, 23, 59, 59, 999) !== "object") { - throw new Test262Error("#10.1: typeof new Date(2099, 11, 31, 23, 59, 59, 999) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 11, 31, 23, 59, 59, 999), + "object", + 'The value of `typeof new Date(2099, 11, 31, 23, 59, 59, 999)` is expected to be "object"' +); -if (new Date(2099, 11, 31, 23, 59, 59, 999) === undefined) { - throw new Test262Error("#10.2: new Date(2099, 11, 31, 23, 59, 59, 999) should not be undefined"); -} +assert.notSameValue( + new Date(2099, 11, 31, 23, 59, 59, 999), + undefined, + 'new Date(2099, 11, 31, 23, 59, 59, 999) is expected to not equal ``undefined``' +); var x103 = new Date(2099, 11, 31, 23, 59, 59, 999); -if (typeof x103 !== "object") { - throw new Test262Error("#10.3: typeof new Date(2099, 11, 31, 23, 59, 59, 999) should be 'object'"); -} +assert.sameValue(typeof x103, "object", 'The value of `typeof x103` is expected to be "object"'); var x104 = new Date(2099, 11, 31, 23, 59, 59, 999); -if (x104 === undefined) { - throw new Test262Error("#10.4: new Date(2099, 11, 31, 23, 59, 59, 999) should not be undefined"); -} +assert.notSameValue(x104, undefined, 'The value of x104 is expected to not equal ``undefined``'); -if (typeof new Date(2099, 12, 1, 0, 0, 0, 0) !== "object") { - throw new Test262Error("#11.1: typeof new Date(2099, 12, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2099, 12, 1, 0, 0, 0, 0), + "object", + 'The value of `typeof new Date(2099, 12, 1, 0, 0, 0, 0)` is expected to be "object"' +); -if (new Date(2099, 12, 1, 0, 0, 0, 0) === undefined) { - throw new Test262Error("#11.2: new Date(2099, 12, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2099, 12, 1, 0, 0, 0, 0), + undefined, + 'new Date(2099, 12, 1, 0, 0, 0, 0) is expected to not equal ``undefined``' +); var x113 = new Date(2099, 12, 1, 0, 0, 0, 0); -if (typeof x113 !== "object") { - throw new Test262Error("#11.3: typeof new Date(2099, 12, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x113, "object", 'The value of `typeof x113` is expected to be "object"'); var x114 = new Date(2099, 12, 1, 0, 0, 0, 0); -if (x114 === undefined) { - throw new Test262Error("#11.4: new Date(2099, 12, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x114, undefined, 'The value of x114 is expected to not equal ``undefined``'); -if (typeof new Date(2100, 0, 1, 0, 0, 0, 0) !== "object") { - throw new Test262Error("#12.1: typeof new Date(2100, 0, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue( + typeof new Date(2100, 0, 1, 0, 0, 0, 0), + "object", + 'The value of `typeof new Date(2100, 0, 1, 0, 0, 0, 0)` is expected to be "object"' +); -if (new Date(2100, 0, 1, 0, 0, 0, 0) === undefined) { - throw new Test262Error("#12.2: new Date(2100, 0, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue( + new Date(2100, 0, 1, 0, 0, 0, 0), + undefined, + 'new Date(2100, 0, 1, 0, 0, 0, 0) is expected to not equal ``undefined``' +); var x123 = new Date(2100, 0, 1, 0, 0, 0, 0); -if (typeof x123 !== "object") { - throw new Test262Error("#12.3: typeof new Date(2100, 0, 1, 0, 0, 0, 0) should be 'object'"); -} +assert.sameValue(typeof x123, "object", 'The value of `typeof x123` is expected to be "object"'); var x124 = new Date(2100, 0, 1, 0, 0, 0, 0); -if (x124 === undefined) { - throw new Test262Error("#12.4: new Date(2100, 0, 1, 0, 0, 0, 0) should not be undefined"); -} +assert.notSameValue(x124, undefined, 'The value of x124 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T1.js index 46cf90d13a2d..54e4ea72f22e 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T1.js @@ -11,183 +11,231 @@ description: 2 arguments, (year, month) ---*/ var x11 = new Date(1899, 11); -if (typeof x11.constructor.prototype !== "object") { - throw new Test262Error("#1.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x11.constructor.prototype, + "object", + 'The value of `typeof x11.constructor.prototype` is expected to be "object"' +); var x12 = new Date(1899, 11); -if (!Date.prototype.isPrototypeOf(x12)) { - throw new Test262Error('#1.2: Date.prototype.isPrototypeOf(x12)'); -} +assert(Date.prototype.isPrototypeOf(x12), 'Date.prototype.isPrototypeOf(x12) must return true'); var x13 = new Date(1899, 11); -if (Date.prototype !== x13.constructor.prototype) { - throw new Test262Error("#1.3: Date.prototype === x13.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x13.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x13.constructor.prototype' +); var x21 = new Date(1899, 12); -if (typeof x21.constructor.prototype !== "object") { - throw new Test262Error("#2.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x21.constructor.prototype, + "object", + 'The value of `typeof x21.constructor.prototype` is expected to be "object"' +); var x22 = new Date(1899, 12); -if (!Date.prototype.isPrototypeOf(x22)) { - throw new Test262Error('#2.2: Date.prototype.isPrototypeOf(x22)'); -} +assert(Date.prototype.isPrototypeOf(x22), 'Date.prototype.isPrototypeOf(x22) must return true'); var x23 = new Date(1899, 12); -if (Date.prototype !== x23.constructor.prototype) { - throw new Test262Error("#2.3: Date.prototype === x23.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x23.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x23.constructor.prototype' +); var x31 = new Date(1900, 0); -if (typeof x31.constructor.prototype !== "object") { - throw new Test262Error("#3.1: typeof x31.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x31.constructor.prototype, + "object", + 'The value of `typeof x31.constructor.prototype` is expected to be "object"' +); var x32 = new Date(1900, 0); -if (!Date.prototype.isPrototypeOf(x32)) { - throw new Test262Error('#3.2: Date.prototype.isPrototypeOf(x32)'); -} +assert(Date.prototype.isPrototypeOf(x32), 'Date.prototype.isPrototypeOf(x32) must return true'); var x33 = new Date(1900, 0); -if (Date.prototype !== x33.constructor.prototype) { - throw new Test262Error("#3.3: Date.prototype === x33.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x33.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x33.constructor.prototype' +); var x41 = new Date(1969, 11); -if (typeof x41.constructor.prototype !== "object") { - throw new Test262Error("#4.1: typeof x41.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x41.constructor.prototype, + "object", + 'The value of `typeof x41.constructor.prototype` is expected to be "object"' +); var x42 = new Date(1969, 11); -if (!Date.prototype.isPrototypeOf(x42)) { - throw new Test262Error('#4.2: Date.prototype.isPrototypeOf(x42)'); -} +assert(Date.prototype.isPrototypeOf(x42), 'Date.prototype.isPrototypeOf(x42) must return true'); var x43 = new Date(1969, 11); -if (Date.prototype !== x43.constructor.prototype) { - throw new Test262Error("#4.3: Date.prototype === x43.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x43.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x43.constructor.prototype' +); var x51 = new Date(1969, 12); -if (typeof x51.constructor.prototype !== "object") { - throw new Test262Error("#5.1: typeof x51.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x51.constructor.prototype, + "object", + 'The value of `typeof x51.constructor.prototype` is expected to be "object"' +); var x52 = new Date(1969, 12); -if (!Date.prototype.isPrototypeOf(x52)) { - throw new Test262Error('#5.2: Date.prototype.isPrototypeOf(x52)'); -} +assert(Date.prototype.isPrototypeOf(x52), 'Date.prototype.isPrototypeOf(x52) must return true'); var x53 = new Date(1969, 12); -if (Date.prototype !== x53.constructor.prototype) { - throw new Test262Error("#5.3: Date.prototype === x53.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x53.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x53.constructor.prototype' +); var x61 = new Date(1970, 0); -if (typeof x61.constructor.prototype !== "object") { - throw new Test262Error("#6.1: typeof x61.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x61.constructor.prototype, + "object", + 'The value of `typeof x61.constructor.prototype` is expected to be "object"' +); var x62 = new Date(1970, 0); -if (!Date.prototype.isPrototypeOf(x62)) { - throw new Test262Error('#6.2: Date.prototype.isPrototypeOf(x62)'); -} +assert(Date.prototype.isPrototypeOf(x62), 'Date.prototype.isPrototypeOf(x62) must return true'); var x63 = new Date(1970, 0); -if (Date.prototype !== x63.constructor.prototype) { - throw new Test262Error("#6.3: Date.prototype === x63.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x63.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x63.constructor.prototype' +); var x71 = new Date(1999, 11); -if (typeof x71.constructor.prototype !== "object") { - throw new Test262Error("#7.1: typeof x71.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x71.constructor.prototype, + "object", + 'The value of `typeof x71.constructor.prototype` is expected to be "object"' +); var x72 = new Date(1999, 11); -if (!Date.prototype.isPrototypeOf(x72)) { - throw new Test262Error('#7.2: Date.prototype.isPrototypeOf(x72)'); -} +assert(Date.prototype.isPrototypeOf(x72), 'Date.prototype.isPrototypeOf(x72) must return true'); var x73 = new Date(1999, 11); -if (Date.prototype !== x73.constructor.prototype) { - throw new Test262Error("#7.3: Date.prototype === x73.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x73.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x73.constructor.prototype' +); var x81 = new Date(1999, 12); -if (typeof x81.constructor.prototype !== "object") { - throw new Test262Error("#8.1: typeof x81.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x81.constructor.prototype, + "object", + 'The value of `typeof x81.constructor.prototype` is expected to be "object"' +); var x82 = new Date(1999, 12); -if (!Date.prototype.isPrototypeOf(x82)) { - throw new Test262Error('#8.2: Date.prototype.isPrototypeOf(x82)'); -} +assert(Date.prototype.isPrototypeOf(x82), 'Date.prototype.isPrototypeOf(x82) must return true'); var x83 = new Date(1999, 12); -if (Date.prototype !== x83.constructor.prototype) { - throw new Test262Error("#8.3: Date.prototype === x83.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x83.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x83.constructor.prototype' +); var x91 = new Date(2000, 0); -if (typeof x91.constructor.prototype !== "object") { - throw new Test262Error("#9.1: typeof x91.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x91.constructor.prototype, + "object", + 'The value of `typeof x91.constructor.prototype` is expected to be "object"' +); var x92 = new Date(2000, 0); -if (!Date.prototype.isPrototypeOf(x92)) { - throw new Test262Error('#9.2: Date.prototype.isPrototypeOf(x92)'); -} +assert(Date.prototype.isPrototypeOf(x92), 'Date.prototype.isPrototypeOf(x92) must return true'); var x93 = new Date(2000, 0); -if (Date.prototype !== x93.constructor.prototype) { - throw new Test262Error("#9.3: Date.prototype === x93.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x93.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x93.constructor.prototype' +); var x101 = new Date(2099, 11); -if (typeof x101.constructor.prototype !== "object") { - throw new Test262Error("#10.1: typeof x101.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x101.constructor.prototype, + "object", + 'The value of `typeof x101.constructor.prototype` is expected to be "object"' +); var x102 = new Date(2099, 11); -if (!Date.prototype.isPrototypeOf(x102)) { - throw new Test262Error('#10.2: Date.prototype.isPrototypeOf(x102)'); -} +assert(Date.prototype.isPrototypeOf(x102), 'Date.prototype.isPrototypeOf(x102) must return true'); var x103 = new Date(2099, 11); -if (Date.prototype !== x103.constructor.prototype) { - throw new Test262Error("#10.3: Date.prototype === x103.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x103.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x103.constructor.prototype' +); var x111 = new Date(2099, 12); -if (typeof x111.constructor.prototype !== "object") { - throw new Test262Error("#11.1: typeof x111.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x111.constructor.prototype, + "object", + 'The value of `typeof x111.constructor.prototype` is expected to be "object"' +); var x112 = new Date(2099, 12); -if (!Date.prototype.isPrototypeOf(x112)) { - throw new Test262Error('#11.2: Date.prototype.isPrototypeOf(x112)'); -} +assert(Date.prototype.isPrototypeOf(x112), 'Date.prototype.isPrototypeOf(x112) must return true'); var x113 = new Date(2099, 12); -if (Date.prototype !== x113.constructor.prototype) { - throw new Test262Error("#11.3: Date.prototype === x113.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x113.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x113.constructor.prototype' +); var x121 = new Date(2100, 0); -if (typeof x121.constructor.prototype !== "object") { - throw new Test262Error("#12.1: typeof x121.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x121.constructor.prototype, + "object", + 'The value of `typeof x121.constructor.prototype` is expected to be "object"' +); var x122 = new Date(2100, 0); -if (!Date.prototype.isPrototypeOf(x122)) { - throw new Test262Error('#12.2: Date.prototype.isPrototypeOf(x122)'); -} +assert(Date.prototype.isPrototypeOf(x122), 'Date.prototype.isPrototypeOf(x122) must return true'); var x123 = new Date(2100, 0); -if (Date.prototype !== x123.constructor.prototype) { - throw new Test262Error("#12.3: Date.prototype === x123.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x123.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x123.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T2.js index 523b749bff04..442fe547bca1 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T2.js @@ -11,183 +11,231 @@ description: 3 arguments, (year, month, date) ---*/ var x11 = new Date(1899, 11, 31); -if (typeof x11.constructor.prototype !== "object") { - throw new Test262Error("#1.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x11.constructor.prototype, + "object", + 'The value of `typeof x11.constructor.prototype` is expected to be "object"' +); var x12 = new Date(1899, 11, 31); -if (!Date.prototype.isPrototypeOf(x12)) { - throw new Test262Error('#1.2: Date.prototype.isPrototypeOf(x12)'); -} +assert(Date.prototype.isPrototypeOf(x12), 'Date.prototype.isPrototypeOf(x12) must return true'); var x13 = new Date(1899, 11, 31); -if (Date.prototype !== x13.constructor.prototype) { - throw new Test262Error("#1.3: Date.prototype === x13.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x13.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x13.constructor.prototype' +); var x21 = new Date(1899, 12, 1); -if (typeof x21.constructor.prototype !== "object") { - throw new Test262Error("#2.1: typeof x21.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x21.constructor.prototype, + "object", + 'The value of `typeof x21.constructor.prototype` is expected to be "object"' +); var x22 = new Date(1899, 12, 1); -if (!Date.prototype.isPrototypeOf(x22)) { - throw new Test262Error('#2.2: Date.prototype.isPrototypeOf(x22)'); -} +assert(Date.prototype.isPrototypeOf(x22), 'Date.prototype.isPrototypeOf(x22) must return true'); var x23 = new Date(1899, 12, 1); -if (Date.prototype !== x23.constructor.prototype) { - throw new Test262Error("#2.3: Date.prototype === x23.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x23.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x23.constructor.prototype' +); var x31 = new Date(1900, 0, 1); -if (typeof x31.constructor.prototype !== "object") { - throw new Test262Error("#3.1: typeof x31.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x31.constructor.prototype, + "object", + 'The value of `typeof x31.constructor.prototype` is expected to be "object"' +); var x32 = new Date(1900, 0, 1); -if (!Date.prototype.isPrototypeOf(x32)) { - throw new Test262Error('#3.2: Date.prototype.isPrototypeOf(x32)'); -} +assert(Date.prototype.isPrototypeOf(x32), 'Date.prototype.isPrototypeOf(x32) must return true'); var x33 = new Date(1900, 0, 1); -if (Date.prototype !== x33.constructor.prototype) { - throw new Test262Error("#3.3: Date.prototype === x33.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x33.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x33.constructor.prototype' +); var x41 = new Date(1969, 11, 31); -if (typeof x41.constructor.prototype !== "object") { - throw new Test262Error("#4.1: typeof x41.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x41.constructor.prototype, + "object", + 'The value of `typeof x41.constructor.prototype` is expected to be "object"' +); var x42 = new Date(1969, 11, 31); -if (!Date.prototype.isPrototypeOf(x42)) { - throw new Test262Error('#4.2: Date.prototype.isPrototypeOf(x42)'); -} +assert(Date.prototype.isPrototypeOf(x42), 'Date.prototype.isPrototypeOf(x42) must return true'); var x43 = new Date(1969, 11, 31); -if (Date.prototype !== x43.constructor.prototype) { - throw new Test262Error("#4.3: Date.prototype === x43.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x43.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x43.constructor.prototype' +); var x51 = new Date(1969, 12, 1); -if (typeof x51.constructor.prototype !== "object") { - throw new Test262Error("#5.1: typeof x51.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x51.constructor.prototype, + "object", + 'The value of `typeof x51.constructor.prototype` is expected to be "object"' +); var x52 = new Date(1969, 12, 1); -if (!Date.prototype.isPrototypeOf(x52)) { - throw new Test262Error('#5.2: Date.prototype.isPrototypeOf(x52)'); -} +assert(Date.prototype.isPrototypeOf(x52), 'Date.prototype.isPrototypeOf(x52) must return true'); var x53 = new Date(1969, 12, 1); -if (Date.prototype !== x53.constructor.prototype) { - throw new Test262Error("#5.3: Date.prototype === x53.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x53.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x53.constructor.prototype' +); var x61 = new Date(1970, 0, 1); -if (typeof x61.constructor.prototype !== "object") { - throw new Test262Error("#6.1: typeof x61.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x61.constructor.prototype, + "object", + 'The value of `typeof x61.constructor.prototype` is expected to be "object"' +); var x62 = new Date(1970, 0, 1); -if (!Date.prototype.isPrototypeOf(x62)) { - throw new Test262Error('#6.2: Date.prototype.isPrototypeOf(x62)'); -} +assert(Date.prototype.isPrototypeOf(x62), 'Date.prototype.isPrototypeOf(x62) must return true'); var x63 = new Date(1970, 0, 1); -if (Date.prototype !== x63.constructor.prototype) { - throw new Test262Error("#6.3: Date.prototype === x63.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x63.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x63.constructor.prototype' +); var x71 = new Date(1999, 11, 31); -if (typeof x71.constructor.prototype !== "object") { - throw new Test262Error("#7.1: typeof x71.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x71.constructor.prototype, + "object", + 'The value of `typeof x71.constructor.prototype` is expected to be "object"' +); var x72 = new Date(1999, 11, 31); -if (!Date.prototype.isPrototypeOf(x72)) { - throw new Test262Error('#7.2: Date.prototype.isPrototypeOf(x72)'); -} +assert(Date.prototype.isPrototypeOf(x72), 'Date.prototype.isPrototypeOf(x72) must return true'); var x73 = new Date(1999, 11, 31); -if (Date.prototype !== x73.constructor.prototype) { - throw new Test262Error("#7.3: Date.prototype === x73.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x73.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x73.constructor.prototype' +); var x81 = new Date(1999, 12, 1); -if (typeof x81.constructor.prototype !== "object") { - throw new Test262Error("#8.1: typeof x81.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x81.constructor.prototype, + "object", + 'The value of `typeof x81.constructor.prototype` is expected to be "object"' +); var x82 = new Date(1999, 12, 1); -if (!Date.prototype.isPrototypeOf(x82)) { - throw new Test262Error('#8.2: Date.prototype.isPrototypeOf(x82)'); -} +assert(Date.prototype.isPrototypeOf(x82), 'Date.prototype.isPrototypeOf(x82) must return true'); var x83 = new Date(1999, 12, 1); -if (Date.prototype !== x83.constructor.prototype) { - throw new Test262Error("#8.3: Date.prototype === x83.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x83.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x83.constructor.prototype' +); var x91 = new Date(2000, 0, 1); -if (typeof x91.constructor.prototype !== "object") { - throw new Test262Error("#9.1: typeof x91.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x91.constructor.prototype, + "object", + 'The value of `typeof x91.constructor.prototype` is expected to be "object"' +); var x92 = new Date(2000, 0, 1); -if (!Date.prototype.isPrototypeOf(x92)) { - throw new Test262Error('#9.2: Date.prototype.isPrototypeOf(x92)'); -} +assert(Date.prototype.isPrototypeOf(x92), 'Date.prototype.isPrototypeOf(x92) must return true'); var x93 = new Date(2000, 0, 1); -if (Date.prototype !== x93.constructor.prototype) { - throw new Test262Error("#9.3: Date.prototype === x93.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x93.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x93.constructor.prototype' +); var x101 = new Date(2099, 11, 31); -if (typeof x101.constructor.prototype !== "object") { - throw new Test262Error("#10.1: typeof x101.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x101.constructor.prototype, + "object", + 'The value of `typeof x101.constructor.prototype` is expected to be "object"' +); var x102 = new Date(2099, 11, 31); -if (!Date.prototype.isPrototypeOf(x102)) { - throw new Test262Error('#10.2: Date.prototype.isPrototypeOf(x102)'); -} +assert(Date.prototype.isPrototypeOf(x102), 'Date.prototype.isPrototypeOf(x102) must return true'); var x103 = new Date(2099, 11, 31); -if (Date.prototype !== x103.constructor.prototype) { - throw new Test262Error("#10.3: Date.prototype === x103.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x103.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x103.constructor.prototype' +); var x111 = new Date(2099, 12, 1); -if (typeof x111.constructor.prototype !== "object") { - throw new Test262Error("#11.1: typeof x111.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x111.constructor.prototype, + "object", + 'The value of `typeof x111.constructor.prototype` is expected to be "object"' +); var x112 = new Date(2099, 12, 1); -if (!Date.prototype.isPrototypeOf(x112)) { - throw new Test262Error('#11.2: Date.prototype.isPrototypeOf(x112)'); -} +assert(Date.prototype.isPrototypeOf(x112), 'Date.prototype.isPrototypeOf(x112) must return true'); var x113 = new Date(2099, 12, 1); -if (Date.prototype !== x113.constructor.prototype) { - throw new Test262Error("#11.3: Date.prototype === x113.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x113.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x113.constructor.prototype' +); var x121 = new Date(2100, 0, 1); -if (typeof x121.constructor.prototype !== "object") { - throw new Test262Error("#12.1: typeof x121.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x121.constructor.prototype, + "object", + 'The value of `typeof x121.constructor.prototype` is expected to be "object"' +); var x122 = new Date(2100, 0, 1); -if (!Date.prototype.isPrototypeOf(x122)) { - throw new Test262Error('#12.2: Date.prototype.isPrototypeOf(x122)'); -} +assert(Date.prototype.isPrototypeOf(x122), 'Date.prototype.isPrototypeOf(x122) must return true'); var x123 = new Date(2100, 0, 1); -if (Date.prototype !== x123.constructor.prototype) { - throw new Test262Error("#12.3: Date.prototype === x123.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x123.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x123.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T3.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T3.js index 550bb48b0b12..4e720182c78e 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T3.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T3.js @@ -11,183 +11,231 @@ description: 4 arguments, (year, month, date, hours) ---*/ var x11 = new Date(1899, 11, 31, 23); -if (typeof x11.constructor.prototype !== "object") { - throw new Test262Error("#1.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x11.constructor.prototype, + "object", + 'The value of `typeof x11.constructor.prototype` is expected to be "object"' +); var x12 = new Date(1899, 11, 31, 23); -if (!Date.prototype.isPrototypeOf(x12)) { - throw new Test262Error('#1.2: Date.prototype.isPrototypeOf(x12)'); -} +assert(Date.prototype.isPrototypeOf(x12), 'Date.prototype.isPrototypeOf(x12) must return true'); var x13 = new Date(1899, 11, 31, 23); -if (Date.prototype !== x13.constructor.prototype) { - throw new Test262Error("#1.3: Date.prototype === x13.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x13.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x13.constructor.prototype' +); var x21 = new Date(1899, 12, 1, 0); -if (typeof x21.constructor.prototype !== "object") { - throw new Test262Error("#2.1: typeof x21.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x21.constructor.prototype, + "object", + 'The value of `typeof x21.constructor.prototype` is expected to be "object"' +); var x22 = new Date(1899, 12, 1, 0); -if (!Date.prototype.isPrototypeOf(x22)) { - throw new Test262Error('#2.2: Date.prototype.isPrototypeOf(x22)'); -} +assert(Date.prototype.isPrototypeOf(x22), 'Date.prototype.isPrototypeOf(x22) must return true'); var x23 = new Date(1899, 12, 1, 0); -if (Date.prototype !== x23.constructor.prototype) { - throw new Test262Error("#2.3: Date.prototype === x23.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x23.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x23.constructor.prototype' +); var x31 = new Date(1900, 0, 1, 0); -if (typeof x31.constructor.prototype !== "object") { - throw new Test262Error("#3.1: typeof x31.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x31.constructor.prototype, + "object", + 'The value of `typeof x31.constructor.prototype` is expected to be "object"' +); var x32 = new Date(1900, 0, 1, 0); -if (!Date.prototype.isPrototypeOf(x32)) { - throw new Test262Error('#3.2: Date.prototype.isPrototypeOf(x32)'); -} +assert(Date.prototype.isPrototypeOf(x32), 'Date.prototype.isPrototypeOf(x32) must return true'); var x33 = new Date(1900, 0, 1, 0); -if (Date.prototype !== x33.constructor.prototype) { - throw new Test262Error("#3.3: Date.prototype === x33.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x33.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x33.constructor.prototype' +); var x41 = new Date(1969, 11, 31, 23); -if (typeof x41.constructor.prototype !== "object") { - throw new Test262Error("#4.1: typeof x41.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x41.constructor.prototype, + "object", + 'The value of `typeof x41.constructor.prototype` is expected to be "object"' +); var x42 = new Date(1969, 11, 31, 23); -if (!Date.prototype.isPrototypeOf(x42)) { - throw new Test262Error('#4.2: Date.prototype.isPrototypeOf(x42)'); -} +assert(Date.prototype.isPrototypeOf(x42), 'Date.prototype.isPrototypeOf(x42) must return true'); var x43 = new Date(1969, 11, 31, 23); -if (Date.prototype !== x43.constructor.prototype) { - throw new Test262Error("#4.3: Date.prototype === x43.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x43.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x43.constructor.prototype' +); var x51 = new Date(1969, 12, 1, 0); -if (typeof x51.constructor.prototype !== "object") { - throw new Test262Error("#5.1: typeof x51.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x51.constructor.prototype, + "object", + 'The value of `typeof x51.constructor.prototype` is expected to be "object"' +); var x52 = new Date(1969, 12, 1, 0); -if (!Date.prototype.isPrototypeOf(x52)) { - throw new Test262Error('#5.2: Date.prototype.isPrototypeOf(x52)'); -} +assert(Date.prototype.isPrototypeOf(x52), 'Date.prototype.isPrototypeOf(x52) must return true'); var x53 = new Date(1969, 12, 1, 0); -if (Date.prototype !== x53.constructor.prototype) { - throw new Test262Error("#5.3: Date.prototype === x53.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x53.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x53.constructor.prototype' +); var x61 = new Date(1970, 0, 1, 0); -if (typeof x61.constructor.prototype !== "object") { - throw new Test262Error("#6.1: typeof x61.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x61.constructor.prototype, + "object", + 'The value of `typeof x61.constructor.prototype` is expected to be "object"' +); var x62 = new Date(1970, 0, 1, 0); -if (!Date.prototype.isPrototypeOf(x62)) { - throw new Test262Error('#6.2: Date.prototype.isPrototypeOf(x62)'); -} +assert(Date.prototype.isPrototypeOf(x62), 'Date.prototype.isPrototypeOf(x62) must return true'); var x63 = new Date(1970, 0, 1, 0); -if (Date.prototype !== x63.constructor.prototype) { - throw new Test262Error("#6.3: Date.prototype === x63.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x63.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x63.constructor.prototype' +); var x71 = new Date(1999, 11, 31, 23); -if (typeof x71.constructor.prototype !== "object") { - throw new Test262Error("#7.1: typeof x71.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x71.constructor.prototype, + "object", + 'The value of `typeof x71.constructor.prototype` is expected to be "object"' +); var x72 = new Date(1999, 11, 31, 23); -if (!Date.prototype.isPrototypeOf(x72)) { - throw new Test262Error('#7.2: Date.prototype.isPrototypeOf(x72)'); -} +assert(Date.prototype.isPrototypeOf(x72), 'Date.prototype.isPrototypeOf(x72) must return true'); var x73 = new Date(1999, 11, 31, 23); -if (Date.prototype !== x73.constructor.prototype) { - throw new Test262Error("#7.3: Date.prototype === x73.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x73.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x73.constructor.prototype' +); var x81 = new Date(1999, 12, 1, 0); -if (typeof x81.constructor.prototype !== "object") { - throw new Test262Error("#8.1: typeof x81.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x81.constructor.prototype, + "object", + 'The value of `typeof x81.constructor.prototype` is expected to be "object"' +); var x82 = new Date(1999, 12, 1, 0); -if (!Date.prototype.isPrototypeOf(x82)) { - throw new Test262Error('#8.2: Date.prototype.isPrototypeOf(x82)'); -} +assert(Date.prototype.isPrototypeOf(x82), 'Date.prototype.isPrototypeOf(x82) must return true'); var x83 = new Date(1999, 12, 1, 0); -if (Date.prototype !== x83.constructor.prototype) { - throw new Test262Error("#8.3: Date.prototype === x83.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x83.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x83.constructor.prototype' +); var x91 = new Date(2000, 0, 1, 0); -if (typeof x91.constructor.prototype !== "object") { - throw new Test262Error("#9.1: typeof x91.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x91.constructor.prototype, + "object", + 'The value of `typeof x91.constructor.prototype` is expected to be "object"' +); var x92 = new Date(2000, 0, 1, 0); -if (!Date.prototype.isPrototypeOf(x92)) { - throw new Test262Error('#9.2: Date.prototype.isPrototypeOf(x92)'); -} +assert(Date.prototype.isPrototypeOf(x92), 'Date.prototype.isPrototypeOf(x92) must return true'); var x93 = new Date(2000, 0, 1, 0); -if (Date.prototype !== x93.constructor.prototype) { - throw new Test262Error("#9.3: Date.prototype === x93.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x93.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x93.constructor.prototype' +); var x101 = new Date(2099, 11, 31, 23); -if (typeof x101.constructor.prototype !== "object") { - throw new Test262Error("#10.1: typeof x101.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x101.constructor.prototype, + "object", + 'The value of `typeof x101.constructor.prototype` is expected to be "object"' +); var x102 = new Date(2099, 11, 31, 23); -if (!Date.prototype.isPrototypeOf(x102)) { - throw new Test262Error('#10.2: Date.prototype.isPrototypeOf(x102)'); -} +assert(Date.prototype.isPrototypeOf(x102), 'Date.prototype.isPrototypeOf(x102) must return true'); var x103 = new Date(2099, 11, 31, 23); -if (Date.prototype !== x103.constructor.prototype) { - throw new Test262Error("#10.3: Date.prototype === x103.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x103.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x103.constructor.prototype' +); var x111 = new Date(2099, 12, 1, 0); -if (typeof x111.constructor.prototype !== "object") { - throw new Test262Error("#11.1: typeof x111.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x111.constructor.prototype, + "object", + 'The value of `typeof x111.constructor.prototype` is expected to be "object"' +); var x112 = new Date(2099, 12, 1, 0); -if (!Date.prototype.isPrototypeOf(x112)) { - throw new Test262Error('#11.2: Date.prototype.isPrototypeOf(x112)'); -} +assert(Date.prototype.isPrototypeOf(x112), 'Date.prototype.isPrototypeOf(x112) must return true'); var x113 = new Date(2099, 12, 1, 0); -if (Date.prototype !== x113.constructor.prototype) { - throw new Test262Error("#11.3: Date.prototype === x113.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x113.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x113.constructor.prototype' +); var x121 = new Date(2100, 0, 1, 0); -if (typeof x121.constructor.prototype !== "object") { - throw new Test262Error("#12.1: typeof x121.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x121.constructor.prototype, + "object", + 'The value of `typeof x121.constructor.prototype` is expected to be "object"' +); var x122 = new Date(2100, 0, 1, 0); -if (!Date.prototype.isPrototypeOf(x122)) { - throw new Test262Error('#12.2: Date.prototype.isPrototypeOf(x122)'); -} +assert(Date.prototype.isPrototypeOf(x122), 'Date.prototype.isPrototypeOf(x122) must return true'); var x123 = new Date(2100, 0, 1, 0); -if (Date.prototype !== x123.constructor.prototype) { - throw new Test262Error("#12.3: Date.prototype === x123.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x123.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x123.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T4.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T4.js index 32722d50d5b6..74f6c89a8546 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T4.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T4.js @@ -11,183 +11,231 @@ description: 5 arguments, (year, month, date, hours, minutes) ---*/ var x11 = new Date(1899, 11, 31, 23, 59); -if (typeof x11.constructor.prototype !== "object") { - throw new Test262Error("#1.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x11.constructor.prototype, + "object", + 'The value of `typeof x11.constructor.prototype` is expected to be "object"' +); var x12 = new Date(1899, 11, 31, 23, 59); -if (!Date.prototype.isPrototypeOf(x12)) { - throw new Test262Error('#1.2: Date.prototype.isPrototypeOf(x12)'); -} +assert(Date.prototype.isPrototypeOf(x12), 'Date.prototype.isPrototypeOf(x12) must return true'); var x13 = new Date(1899, 11, 31, 23, 59); -if (Date.prototype !== x13.constructor.prototype) { - throw new Test262Error("#1.3: Date.prototype === x13.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x13.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x13.constructor.prototype' +); var x21 = new Date(1899, 12, 1, 0, 0); -if (typeof x21.constructor.prototype !== "object") { - throw new Test262Error("#2.1: typeof x21.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x21.constructor.prototype, + "object", + 'The value of `typeof x21.constructor.prototype` is expected to be "object"' +); var x22 = new Date(1899, 12, 1, 0, 0); -if (!Date.prototype.isPrototypeOf(x22)) { - throw new Test262Error('#2.2: Date.prototype.isPrototypeOf(x22)'); -} +assert(Date.prototype.isPrototypeOf(x22), 'Date.prototype.isPrototypeOf(x22) must return true'); var x23 = new Date(1899, 12, 1, 0, 0); -if (Date.prototype !== x23.constructor.prototype) { - throw new Test262Error("#2.3: Date.prototype === x23.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x23.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x23.constructor.prototype' +); var x31 = new Date(1900, 0, 1, 0, 0); -if (typeof x31.constructor.prototype !== "object") { - throw new Test262Error("#3.1: typeof x31.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x31.constructor.prototype, + "object", + 'The value of `typeof x31.constructor.prototype` is expected to be "object"' +); var x32 = new Date(1900, 0, 1, 0, 0); -if (!Date.prototype.isPrototypeOf(x32)) { - throw new Test262Error('#3.2: Date.prototype.isPrototypeOf(x32)'); -} +assert(Date.prototype.isPrototypeOf(x32), 'Date.prototype.isPrototypeOf(x32) must return true'); var x33 = new Date(1900, 0, 1, 0, 0); -if (Date.prototype !== x33.constructor.prototype) { - throw new Test262Error("#3.3: Date.prototype === x33.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x33.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x33.constructor.prototype' +); var x41 = new Date(1969, 11, 31, 23, 59); -if (typeof x41.constructor.prototype !== "object") { - throw new Test262Error("#4.1: typeof x41.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x41.constructor.prototype, + "object", + 'The value of `typeof x41.constructor.prototype` is expected to be "object"' +); var x42 = new Date(1969, 11, 31, 23, 59); -if (!Date.prototype.isPrototypeOf(x42)) { - throw new Test262Error('#4.2: Date.prototype.isPrototypeOf(x42)'); -} +assert(Date.prototype.isPrototypeOf(x42), 'Date.prototype.isPrototypeOf(x42) must return true'); var x43 = new Date(1969, 11, 31, 23, 59); -if (Date.prototype !== x43.constructor.prototype) { - throw new Test262Error("#4.3: Date.prototype === x43.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x43.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x43.constructor.prototype' +); var x51 = new Date(1969, 12, 1, 0, 0); -if (typeof x51.constructor.prototype !== "object") { - throw new Test262Error("#5.1: typeof x51.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x51.constructor.prototype, + "object", + 'The value of `typeof x51.constructor.prototype` is expected to be "object"' +); var x52 = new Date(1969, 12, 1, 0, 0); -if (!Date.prototype.isPrototypeOf(x52)) { - throw new Test262Error('#5.2: Date.prototype.isPrototypeOf(x52)'); -} +assert(Date.prototype.isPrototypeOf(x52), 'Date.prototype.isPrototypeOf(x52) must return true'); var x53 = new Date(1969, 12, 1, 0, 0); -if (Date.prototype !== x53.constructor.prototype) { - throw new Test262Error("#5.3: Date.prototype === x53.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x53.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x53.constructor.prototype' +); var x61 = new Date(1970, 0, 1, 0, 0); -if (typeof x61.constructor.prototype !== "object") { - throw new Test262Error("#6.1: typeof x61.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x61.constructor.prototype, + "object", + 'The value of `typeof x61.constructor.prototype` is expected to be "object"' +); var x62 = new Date(1970, 0, 1, 0, 0); -if (!Date.prototype.isPrototypeOf(x62)) { - throw new Test262Error('#6.2: Date.prototype.isPrototypeOf(x62)'); -} +assert(Date.prototype.isPrototypeOf(x62), 'Date.prototype.isPrototypeOf(x62) must return true'); var x63 = new Date(1970, 0, 1, 0, 0); -if (Date.prototype !== x63.constructor.prototype) { - throw new Test262Error("#6.3: Date.prototype === x63.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x63.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x63.constructor.prototype' +); var x71 = new Date(1999, 11, 31, 23, 59); -if (typeof x71.constructor.prototype !== "object") { - throw new Test262Error("#7.1: typeof x71.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x71.constructor.prototype, + "object", + 'The value of `typeof x71.constructor.prototype` is expected to be "object"' +); var x72 = new Date(1999, 11, 31, 23, 59); -if (!Date.prototype.isPrototypeOf(x72)) { - throw new Test262Error('#7.2: Date.prototype.isPrototypeOf(x72)'); -} +assert(Date.prototype.isPrototypeOf(x72), 'Date.prototype.isPrototypeOf(x72) must return true'); var x73 = new Date(1999, 11, 31, 23, 59); -if (Date.prototype !== x73.constructor.prototype) { - throw new Test262Error("#7.3: Date.prototype === x73.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x73.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x73.constructor.prototype' +); var x81 = new Date(1999, 12, 1, 0, 0); -if (typeof x81.constructor.prototype !== "object") { - throw new Test262Error("#8.1: typeof x81.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x81.constructor.prototype, + "object", + 'The value of `typeof x81.constructor.prototype` is expected to be "object"' +); var x82 = new Date(1999, 12, 1, 0, 0); -if (!Date.prototype.isPrototypeOf(x82)) { - throw new Test262Error('#8.2: Date.prototype.isPrototypeOf(x82)'); -} +assert(Date.prototype.isPrototypeOf(x82), 'Date.prototype.isPrototypeOf(x82) must return true'); var x83 = new Date(1999, 12, 1, 0, 0); -if (Date.prototype !== x83.constructor.prototype) { - throw new Test262Error("#8.3: Date.prototype === x83.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x83.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x83.constructor.prototype' +); var x91 = new Date(2000, 0, 1, 0, 0); -if (typeof x91.constructor.prototype !== "object") { - throw new Test262Error("#9.1: typeof x91.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x91.constructor.prototype, + "object", + 'The value of `typeof x91.constructor.prototype` is expected to be "object"' +); var x92 = new Date(2000, 0, 1, 0, 0); -if (!Date.prototype.isPrototypeOf(x92)) { - throw new Test262Error('#9.2: Date.prototype.isPrototypeOf(x92)'); -} +assert(Date.prototype.isPrototypeOf(x92), 'Date.prototype.isPrototypeOf(x92) must return true'); var x93 = new Date(2000, 0, 1, 0, 0); -if (Date.prototype !== x93.constructor.prototype) { - throw new Test262Error("#9.3: Date.prototype === x93.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x93.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x93.constructor.prototype' +); var x101 = new Date(2099, 11, 31, 23, 59); -if (typeof x101.constructor.prototype !== "object") { - throw new Test262Error("#10.1: typeof x101.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x101.constructor.prototype, + "object", + 'The value of `typeof x101.constructor.prototype` is expected to be "object"' +); var x102 = new Date(2099, 11, 31, 23, 59); -if (!Date.prototype.isPrototypeOf(x102)) { - throw new Test262Error('#10.2: Date.prototype.isPrototypeOf(x102)'); -} +assert(Date.prototype.isPrototypeOf(x102), 'Date.prototype.isPrototypeOf(x102) must return true'); var x103 = new Date(2099, 11, 31, 23, 59); -if (Date.prototype !== x103.constructor.prototype) { - throw new Test262Error("#10.3: Date.prototype === x103.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x103.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x103.constructor.prototype' +); var x111 = new Date(2099, 12, 1, 0, 0); -if (typeof x111.constructor.prototype !== "object") { - throw new Test262Error("#11.1: typeof x111.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x111.constructor.prototype, + "object", + 'The value of `typeof x111.constructor.prototype` is expected to be "object"' +); var x112 = new Date(2099, 12, 1, 0, 0); -if (!Date.prototype.isPrototypeOf(x112)) { - throw new Test262Error('#11.2: Date.prototype.isPrototypeOf(x112)'); -} +assert(Date.prototype.isPrototypeOf(x112), 'Date.prototype.isPrototypeOf(x112) must return true'); var x113 = new Date(2099, 12, 1, 0, 0); -if (Date.prototype !== x113.constructor.prototype) { - throw new Test262Error("#11.3: Date.prototype === x113.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x113.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x113.constructor.prototype' +); var x121 = new Date(2100, 0, 1, 0, 0); -if (typeof x121.constructor.prototype !== "object") { - throw new Test262Error("#12.1: typeof x121.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x121.constructor.prototype, + "object", + 'The value of `typeof x121.constructor.prototype` is expected to be "object"' +); var x122 = new Date(2100, 0, 1, 0, 0); -if (!Date.prototype.isPrototypeOf(x122)) { - throw new Test262Error('#12.2: Date.prototype.isPrototypeOf(x122)'); -} +assert(Date.prototype.isPrototypeOf(x122), 'Date.prototype.isPrototypeOf(x122) must return true'); var x123 = new Date(2100, 0, 1, 0, 0); -if (Date.prototype !== x123.constructor.prototype) { - throw new Test262Error("#12.3: Date.prototype === x123.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x123.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x123.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T5.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T5.js index 22bea50e3e68..047f8a7077d2 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T5.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T5.js @@ -11,183 +11,231 @@ description: 6 arguments, (year, month, date, hours, minutes, seconds) ---*/ var x11 = new Date(1899, 11, 31, 23, 59, 59); -if (typeof x11.constructor.prototype !== "object") { - throw new Test262Error("#1.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x11.constructor.prototype, + "object", + 'The value of `typeof x11.constructor.prototype` is expected to be "object"' +); var x12 = new Date(1899, 11, 31, 23, 59, 59); -if (!Date.prototype.isPrototypeOf(x12)) { - throw new Test262Error('#1.2: Date.prototype.isPrototypeOf(x12)'); -} +assert(Date.prototype.isPrototypeOf(x12), 'Date.prototype.isPrototypeOf(x12) must return true'); var x13 = new Date(1899, 11, 31, 23, 59, 59); -if (Date.prototype !== x13.constructor.prototype) { - throw new Test262Error("#1.3: Date.prototype === x13.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x13.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x13.constructor.prototype' +); var x21 = new Date(1899, 12, 1, 0, 0, 0); -if (typeof x21.constructor.prototype !== "object") { - throw new Test262Error("#2.1: typeof x21.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x21.constructor.prototype, + "object", + 'The value of `typeof x21.constructor.prototype` is expected to be "object"' +); var x22 = new Date(1899, 12, 1, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x22)) { - throw new Test262Error('#2.2: Date.prototype.isPrototypeOf(x22)'); -} +assert(Date.prototype.isPrototypeOf(x22), 'Date.prototype.isPrototypeOf(x22) must return true'); var x23 = new Date(1899, 12, 1, 0, 0, 0); -if (Date.prototype !== x23.constructor.prototype) { - throw new Test262Error("#2.3: Date.prototype === x23.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x23.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x23.constructor.prototype' +); var x31 = new Date(1900, 0, 1, 0, 0, 0); -if (typeof x31.constructor.prototype !== "object") { - throw new Test262Error("#3.1: typeof x31.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x31.constructor.prototype, + "object", + 'The value of `typeof x31.constructor.prototype` is expected to be "object"' +); var x32 = new Date(1900, 0, 1, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x32)) { - throw new Test262Error('#3.2: Date.prototype.isPrototypeOf(x32)'); -} +assert(Date.prototype.isPrototypeOf(x32), 'Date.prototype.isPrototypeOf(x32) must return true'); var x33 = new Date(1900, 0, 1, 0, 0, 0); -if (Date.prototype !== x33.constructor.prototype) { - throw new Test262Error("#3.3: Date.prototype === x33.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x33.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x33.constructor.prototype' +); var x41 = new Date(1969, 11, 31, 23, 59, 59); -if (typeof x41.constructor.prototype !== "object") { - throw new Test262Error("#4.1: typeof x41.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x41.constructor.prototype, + "object", + 'The value of `typeof x41.constructor.prototype` is expected to be "object"' +); var x42 = new Date(1969, 11, 31, 23, 59, 59); -if (!Date.prototype.isPrototypeOf(x42)) { - throw new Test262Error('#4.2: Date.prototype.isPrototypeOf(x42)'); -} +assert(Date.prototype.isPrototypeOf(x42), 'Date.prototype.isPrototypeOf(x42) must return true'); var x43 = new Date(1969, 11, 31, 23, 59, 59); -if (Date.prototype !== x43.constructor.prototype) { - throw new Test262Error("#4.3: Date.prototype === x43.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x43.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x43.constructor.prototype' +); var x51 = new Date(1969, 12, 1, 0, 0, 0); -if (typeof x51.constructor.prototype !== "object") { - throw new Test262Error("#5.1: typeof x51.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x51.constructor.prototype, + "object", + 'The value of `typeof x51.constructor.prototype` is expected to be "object"' +); var x52 = new Date(1969, 12, 1, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x52)) { - throw new Test262Error('#5.2: Date.prototype.isPrototypeOf(x52)'); -} +assert(Date.prototype.isPrototypeOf(x52), 'Date.prototype.isPrototypeOf(x52) must return true'); var x53 = new Date(1969, 12, 1, 0, 0, 0); -if (Date.prototype !== x53.constructor.prototype) { - throw new Test262Error("#5.3: Date.prototype === x53.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x53.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x53.constructor.prototype' +); var x61 = new Date(1970, 0, 1, 0, 0, 0); -if (typeof x61.constructor.prototype !== "object") { - throw new Test262Error("#6.1: typeof x61.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x61.constructor.prototype, + "object", + 'The value of `typeof x61.constructor.prototype` is expected to be "object"' +); var x62 = new Date(1970, 0, 1, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x62)) { - throw new Test262Error('#6.2: Date.prototype.isPrototypeOf(x62)'); -} +assert(Date.prototype.isPrototypeOf(x62), 'Date.prototype.isPrototypeOf(x62) must return true'); var x63 = new Date(1970, 0, 1, 0, 0, 0); -if (Date.prototype !== x63.constructor.prototype) { - throw new Test262Error("#6.3: Date.prototype === x63.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x63.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x63.constructor.prototype' +); var x71 = new Date(1999, 11, 31, 23, 59, 59); -if (typeof x71.constructor.prototype !== "object") { - throw new Test262Error("#7.1: typeof x71.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x71.constructor.prototype, + "object", + 'The value of `typeof x71.constructor.prototype` is expected to be "object"' +); var x72 = new Date(1999, 11, 31, 23, 59, 59); -if (!Date.prototype.isPrototypeOf(x72)) { - throw new Test262Error('#7.2: Date.prototype.isPrototypeOf(x72)'); -} +assert(Date.prototype.isPrototypeOf(x72), 'Date.prototype.isPrototypeOf(x72) must return true'); var x73 = new Date(1999, 11, 31, 23, 59, 59); -if (Date.prototype !== x73.constructor.prototype) { - throw new Test262Error("#7.3: Date.prototype === x73.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x73.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x73.constructor.prototype' +); var x81 = new Date(1999, 12, 1, 0, 0, 0); -if (typeof x81.constructor.prototype !== "object") { - throw new Test262Error("#8.1: typeof x81.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x81.constructor.prototype, + "object", + 'The value of `typeof x81.constructor.prototype` is expected to be "object"' +); var x82 = new Date(1999, 12, 1, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x82)) { - throw new Test262Error('#8.2: Date.prototype.isPrototypeOf(x82)'); -} +assert(Date.prototype.isPrototypeOf(x82), 'Date.prototype.isPrototypeOf(x82) must return true'); var x83 = new Date(1999, 12, 1, 0, 0, 0); -if (Date.prototype !== x83.constructor.prototype) { - throw new Test262Error("#8.3: Date.prototype === x83.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x83.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x83.constructor.prototype' +); var x91 = new Date(2000, 0, 1, 0, 0, 0); -if (typeof x91.constructor.prototype !== "object") { - throw new Test262Error("#9.1: typeof x91.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x91.constructor.prototype, + "object", + 'The value of `typeof x91.constructor.prototype` is expected to be "object"' +); var x92 = new Date(2000, 0, 1, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x92)) { - throw new Test262Error('#9.2: Date.prototype.isPrototypeOf(x92)'); -} +assert(Date.prototype.isPrototypeOf(x92), 'Date.prototype.isPrototypeOf(x92) must return true'); var x93 = new Date(2000, 0, 1, 0, 0, 0); -if (Date.prototype !== x93.constructor.prototype) { - throw new Test262Error("#9.3: Date.prototype === x93.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x93.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x93.constructor.prototype' +); var x101 = new Date(2099, 11, 31, 23, 59, 59); -if (typeof x101.constructor.prototype !== "object") { - throw new Test262Error("#10.1: typeof x101.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x101.constructor.prototype, + "object", + 'The value of `typeof x101.constructor.prototype` is expected to be "object"' +); var x102 = new Date(2099, 11, 31, 23, 59, 59); -if (!Date.prototype.isPrototypeOf(x102)) { - throw new Test262Error('#10.2: Date.prototype.isPrototypeOf(x102)'); -} +assert(Date.prototype.isPrototypeOf(x102), 'Date.prototype.isPrototypeOf(x102) must return true'); var x103 = new Date(2099, 11, 31, 23, 59, 59); -if (Date.prototype !== x103.constructor.prototype) { - throw new Test262Error("#10.3: Date.prototype === x103.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x103.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x103.constructor.prototype' +); var x111 = new Date(2099, 12, 1, 0, 0, 0); -if (typeof x111.constructor.prototype !== "object") { - throw new Test262Error("#11.1: typeof x111.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x111.constructor.prototype, + "object", + 'The value of `typeof x111.constructor.prototype` is expected to be "object"' +); var x112 = new Date(2099, 12, 1, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x112)) { - throw new Test262Error('#11.2: Date.prototype.isPrototypeOf(x112)'); -} +assert(Date.prototype.isPrototypeOf(x112), 'Date.prototype.isPrototypeOf(x112) must return true'); var x113 = new Date(2099, 12, 1, 0, 0, 0); -if (Date.prototype !== x113.constructor.prototype) { - throw new Test262Error("#11.3: Date.prototype === x113.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x113.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x113.constructor.prototype' +); var x121 = new Date(2100, 0, 1, 0, 0, 0); -if (typeof x121.constructor.prototype !== "object") { - throw new Test262Error("#12.1: typeof x121.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x121.constructor.prototype, + "object", + 'The value of `typeof x121.constructor.prototype` is expected to be "object"' +); var x122 = new Date(2100, 0, 1, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x122)) { - throw new Test262Error('#12.2: Date.prototype.isPrototypeOf(x122)'); -} +assert(Date.prototype.isPrototypeOf(x122), 'Date.prototype.isPrototypeOf(x122) must return true'); var x123 = new Date(2100, 0, 1, 0, 0, 0); -if (Date.prototype !== x123.constructor.prototype) { - throw new Test262Error("#12.3: Date.prototype === x123.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x123.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x123.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T6.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T6.js index ca1d2916a3e3..526c1f9d4242 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T6.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A2_T6.js @@ -11,183 +11,231 @@ description: 7 arguments, (year, month, date, hours, minutes, seconds, ms) ---*/ var x11 = new Date(1899, 11, 31, 23, 59, 59, 999); -if (typeof x11.constructor.prototype !== "object") { - throw new Test262Error("#1.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x11.constructor.prototype, + "object", + 'The value of `typeof x11.constructor.prototype` is expected to be "object"' +); var x12 = new Date(1899, 11, 31, 23, 59, 59, 999); -if (!Date.prototype.isPrototypeOf(x12)) { - throw new Test262Error('#1.2: Date.prototype.isPrototypeOf(x12)'); -} +assert(Date.prototype.isPrototypeOf(x12), 'Date.prototype.isPrototypeOf(x12) must return true'); var x13 = new Date(1899, 11, 31, 23, 59, 59, 999); -if (Date.prototype !== x13.constructor.prototype) { - throw new Test262Error("#1.3: Date.prototype === x13.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x13.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x13.constructor.prototype' +); var x21 = new Date(1899, 12, 1, 0, 0, 0, 0); -if (typeof x21.constructor.prototype !== "object") { - throw new Test262Error("#2.1: typeof x21.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x21.constructor.prototype, + "object", + 'The value of `typeof x21.constructor.prototype` is expected to be "object"' +); var x22 = new Date(1899, 12, 1, 0, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x22)) { - throw new Test262Error('#2.2: Date.prototype.isPrototypeOf(x22)'); -} +assert(Date.prototype.isPrototypeOf(x22), 'Date.prototype.isPrototypeOf(x22) must return true'); var x23 = new Date(1899, 12, 1, 0, 0, 0, 0); -if (Date.prototype !== x23.constructor.prototype) { - throw new Test262Error("#2.3: Date.prototype === x23.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x23.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x23.constructor.prototype' +); var x31 = new Date(1900, 0, 1, 0, 0, 0, 0); -if (typeof x31.constructor.prototype !== "object") { - throw new Test262Error("#3.1: typeof x31.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x31.constructor.prototype, + "object", + 'The value of `typeof x31.constructor.prototype` is expected to be "object"' +); var x32 = new Date(1900, 0, 1, 0, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x32)) { - throw new Test262Error('#3.2: Date.prototype.isPrototypeOf(x32)'); -} +assert(Date.prototype.isPrototypeOf(x32), 'Date.prototype.isPrototypeOf(x32) must return true'); var x33 = new Date(1900, 0, 1, 0, 0, 0, 0); -if (Date.prototype !== x33.constructor.prototype) { - throw new Test262Error("#3.3: Date.prototype === x33.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x33.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x33.constructor.prototype' +); var x41 = new Date(1969, 11, 31, 23, 59, 59, 999); -if (typeof x41.constructor.prototype !== "object") { - throw new Test262Error("#4.1: typeof x41.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x41.constructor.prototype, + "object", + 'The value of `typeof x41.constructor.prototype` is expected to be "object"' +); var x42 = new Date(1969, 11, 31, 23, 59, 59, 999); -if (!Date.prototype.isPrototypeOf(x42)) { - throw new Test262Error('#4.2: Date.prototype.isPrototypeOf(x42)'); -} +assert(Date.prototype.isPrototypeOf(x42), 'Date.prototype.isPrototypeOf(x42) must return true'); var x43 = new Date(1969, 11, 31, 23, 59, 59, 999); -if (Date.prototype !== x43.constructor.prototype) { - throw new Test262Error("#4.3: Date.prototype === x43.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x43.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x43.constructor.prototype' +); var x51 = new Date(1969, 12, 1, 0, 0, 0, 0); -if (typeof x51.constructor.prototype !== "object") { - throw new Test262Error("#5.1: typeof x51.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x51.constructor.prototype, + "object", + 'The value of `typeof x51.constructor.prototype` is expected to be "object"' +); var x52 = new Date(1969, 12, 1, 0, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x52)) { - throw new Test262Error('#5.2: Date.prototype.isPrototypeOf(x52)'); -} +assert(Date.prototype.isPrototypeOf(x52), 'Date.prototype.isPrototypeOf(x52) must return true'); var x53 = new Date(1969, 12, 1, 0, 0, 0, 0); -if (Date.prototype !== x53.constructor.prototype) { - throw new Test262Error("#5.3: Date.prototype === x53.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x53.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x53.constructor.prototype' +); var x61 = new Date(1970, 0, 1, 0, 0, 0, 0); -if (typeof x61.constructor.prototype !== "object") { - throw new Test262Error("#6.1: typeof x61.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x61.constructor.prototype, + "object", + 'The value of `typeof x61.constructor.prototype` is expected to be "object"' +); var x62 = new Date(1970, 0, 1, 0, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x62)) { - throw new Test262Error('#6.2: Date.prototype.isPrototypeOf(x62)'); -} +assert(Date.prototype.isPrototypeOf(x62), 'Date.prototype.isPrototypeOf(x62) must return true'); var x63 = new Date(1970, 0, 1, 0, 0, 0, 0); -if (Date.prototype !== x63.constructor.prototype) { - throw new Test262Error("#6.3: Date.prototype === x63.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x63.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x63.constructor.prototype' +); var x71 = new Date(1999, 11, 31, 23, 59, 59, 999); -if (typeof x71.constructor.prototype !== "object") { - throw new Test262Error("#7.1: typeof x71.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x71.constructor.prototype, + "object", + 'The value of `typeof x71.constructor.prototype` is expected to be "object"' +); var x72 = new Date(1999, 11, 31, 23, 59, 59, 999); -if (!Date.prototype.isPrototypeOf(x72)) { - throw new Test262Error('#7.2: Date.prototype.isPrototypeOf(x72)'); -} +assert(Date.prototype.isPrototypeOf(x72), 'Date.prototype.isPrototypeOf(x72) must return true'); var x73 = new Date(1999, 11, 31, 23, 59, 59, 999); -if (Date.prototype !== x73.constructor.prototype) { - throw new Test262Error("#7.3: Date.prototype === x73.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x73.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x73.constructor.prototype' +); var x81 = new Date(1999, 12, 1, 0, 0, 0, 0); -if (typeof x81.constructor.prototype !== "object") { - throw new Test262Error("#8.1: typeof x81.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x81.constructor.prototype, + "object", + 'The value of `typeof x81.constructor.prototype` is expected to be "object"' +); var x82 = new Date(1999, 12, 1, 0, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x82)) { - throw new Test262Error('#8.2: Date.prototype.isPrototypeOf(x82)'); -} +assert(Date.prototype.isPrototypeOf(x82), 'Date.prototype.isPrototypeOf(x82) must return true'); var x83 = new Date(1999, 12, 1, 0, 0, 0, 0); -if (Date.prototype !== x83.constructor.prototype) { - throw new Test262Error("#8.3: Date.prototype === x83.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x83.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x83.constructor.prototype' +); var x91 = new Date(2000, 0, 1, 0, 0, 0, 0); -if (typeof x91.constructor.prototype !== "object") { - throw new Test262Error("#9.1: typeof x91.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x91.constructor.prototype, + "object", + 'The value of `typeof x91.constructor.prototype` is expected to be "object"' +); var x92 = new Date(2000, 0, 1, 0, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x92)) { - throw new Test262Error('#9.2: Date.prototype.isPrototypeOf(x92)'); -} +assert(Date.prototype.isPrototypeOf(x92), 'Date.prototype.isPrototypeOf(x92) must return true'); var x93 = new Date(2000, 0, 1, 0, 0, 0, 0); -if (Date.prototype !== x93.constructor.prototype) { - throw new Test262Error("#9.3: Date.prototype === x93.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x93.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x93.constructor.prototype' +); var x101 = new Date(2099, 11, 31, 23, 59, 59, 999); -if (typeof x101.constructor.prototype !== "object") { - throw new Test262Error("#10.1: typeof x101.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x101.constructor.prototype, + "object", + 'The value of `typeof x101.constructor.prototype` is expected to be "object"' +); var x102 = new Date(2099, 11, 31, 23, 59, 59, 999); -if (!Date.prototype.isPrototypeOf(x102)) { - throw new Test262Error('#10.2: Date.prototype.isPrototypeOf(x102)'); -} +assert(Date.prototype.isPrototypeOf(x102), 'Date.prototype.isPrototypeOf(x102) must return true'); var x103 = new Date(2099, 11, 31, 23, 59, 59, 999); -if (Date.prototype !== x103.constructor.prototype) { - throw new Test262Error("#10.3: Date.prototype === x103.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x103.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x103.constructor.prototype' +); var x111 = new Date(2099, 12, 1, 0, 0, 0, 0); -if (typeof x111.constructor.prototype !== "object") { - throw new Test262Error("#11.1: typeof x111.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x111.constructor.prototype, + "object", + 'The value of `typeof x111.constructor.prototype` is expected to be "object"' +); var x112 = new Date(2099, 12, 1, 0, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x112)) { - throw new Test262Error('#11.2: Date.prototype.isPrototypeOf(x112)'); -} +assert(Date.prototype.isPrototypeOf(x112), 'Date.prototype.isPrototypeOf(x112) must return true'); var x113 = new Date(2099, 12, 1, 0, 0, 0, 0); -if (Date.prototype !== x113.constructor.prototype) { - throw new Test262Error("#11.3: Date.prototype === x113.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x113.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x113.constructor.prototype' +); var x121 = new Date(2100, 0, 1, 0, 0, 0, 0); -if (typeof x121.constructor.prototype !== "object") { - throw new Test262Error("#12.1: typeof x121.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x121.constructor.prototype, + "object", + 'The value of `typeof x121.constructor.prototype` is expected to be "object"' +); var x122 = new Date(2100, 0, 1, 0, 0, 0, 0); -if (!Date.prototype.isPrototypeOf(x122)) { - throw new Test262Error('#12.2: Date.prototype.isPrototypeOf(x122)'); -} +assert(Date.prototype.isPrototypeOf(x122), 'Date.prototype.isPrototypeOf(x122) must return true'); var x123 = new Date(2100, 0, 1, 0, 0, 0, 0); -if (Date.prototype !== x123.constructor.prototype) { - throw new Test262Error("#12.3: Date.prototype === x123.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x123.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x123.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T1.1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T1.1.js index 9f009232cc24..34eef009a298 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T1.1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T1.1.js @@ -12,63 +12,99 @@ description: > ---*/ var x1 = new Date(1899, 11); -if (Object.prototype.toString.call(x1) !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x1), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 11)) must return "[object Date]"' +); var x2 = new Date(1899, 12); -if (Object.prototype.toString.call(x2) !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x2), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 12)) must return "[object Date]"' +); var x3 = new Date(1900, 0); -if (Object.prototype.toString.call(x3) !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x3), + "[object Date]", + 'Object.prototype.toString.call(new Date(1900, 0)) must return "[object Date]"' +); var x4 = new Date(1969, 11); -if (Object.prototype.toString.call(x4) !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x4), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 11)) must return "[object Date]"' +); var x5 = new Date(1969, 12); -if (Object.prototype.toString.call(x5) !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x5), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 12)) must return "[object Date]"' +); var x6 = new Date(1970, 0); -if (Object.prototype.toString.call(x6) !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x6), + "[object Date]", + 'Object.prototype.toString.call(new Date(1970, 0)) must return "[object Date]"' +); var x7 = new Date(1999, 11); -if (Object.prototype.toString.call(x7) !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x7), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 11)) must return "[object Date]"' +); var x8 = new Date(1999, 12); -if (Object.prototype.toString.call(x8) !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x8), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 12)) must return "[object Date]"' +); var x9 = new Date(2000, 0); -if (Object.prototype.toString.call(x9) !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x9), + "[object Date]", + 'Object.prototype.toString.call(new Date(2000, 0)) must return "[object Date]"' +); var x10 = new Date(2099, 11); -if (Object.prototype.toString.call(x10) !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x10), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 11)) must return "[object Date]"' +); var x11 = new Date(2099, 12); -if (Object.prototype.toString.call(x11) !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x11), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 12)) must return "[object Date]"' +); var x12 = new Date(2100, 0); -if (Object.prototype.toString.call(x12) !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x12), + "[object Date]", + 'Object.prototype.toString.call(new Date(2100, 0)) must return "[object Date]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T1.2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T1.2.js index 39bd022eb405..abc6e7a2f4e7 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T1.2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T1.2.js @@ -14,63 +14,39 @@ description: > Date.prototype.toString = Object.prototype.toString; var x1 = new Date(1899, 11); -if (x1.toString() !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x1.toString(), "[object Date]", 'x1.toString() must return "[object Date]"'); var x2 = new Date(1899, 12); -if (x2.toString() !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x2.toString(), "[object Date]", 'x2.toString() must return "[object Date]"'); var x3 = new Date(1900, 0); -if (x3.toString() !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x3.toString(), "[object Date]", 'x3.toString() must return "[object Date]"'); var x4 = new Date(1969, 11); -if (x4.toString() !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x4.toString(), "[object Date]", 'x4.toString() must return "[object Date]"'); var x5 = new Date(1969, 12); -if (x5.toString() !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x5.toString(), "[object Date]", 'x5.toString() must return "[object Date]"'); var x6 = new Date(1970, 0); -if (x6.toString() !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x6.toString(), "[object Date]", 'x6.toString() must return "[object Date]"'); var x7 = new Date(1999, 11); -if (x7.toString() !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x7.toString(), "[object Date]", 'x7.toString() must return "[object Date]"'); var x8 = new Date(1999, 12); -if (x8.toString() !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x8.toString(), "[object Date]", 'x8.toString() must return "[object Date]"'); var x9 = new Date(2000, 0); -if (x9.toString() !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x9.toString(), "[object Date]", 'x9.toString() must return "[object Date]"'); var x10 = new Date(2099, 11); -if (x10.toString() !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x10.toString(), "[object Date]", 'x10.toString() must return "[object Date]"'); var x11 = new Date(2099, 12); -if (x11.toString() !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x11.toString(), "[object Date]", 'x11.toString() must return "[object Date]"'); var x12 = new Date(2100, 0); -if (x12.toString() !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x12.toString(), "[object Date]", 'x12.toString() must return "[object Date]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T2.1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T2.1.js index 776aa2099d67..97bdfc01d16f 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T2.1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T2.1.js @@ -12,63 +12,99 @@ description: > ---*/ var x1 = new Date(1899, 11, 31); -if (Object.prototype.toString.call(x1) !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x1), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 11, 31)) must return "[object Date]"' +); var x2 = new Date(1899, 12, 1); -if (Object.prototype.toString.call(x2) !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x2), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 12, 1)) must return "[object Date]"' +); var x3 = new Date(1900, 0, 1); -if (Object.prototype.toString.call(x3) !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x3), + "[object Date]", + 'Object.prototype.toString.call(new Date(1900, 0, 1)) must return "[object Date]"' +); var x4 = new Date(1969, 11, 31); -if (Object.prototype.toString.call(x4) !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x4), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 11, 31)) must return "[object Date]"' +); var x5 = new Date(1969, 12, 1); -if (Object.prototype.toString.call(x5) !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x5), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 12, 1)) must return "[object Date]"' +); var x6 = new Date(1970, 0, 1); -if (Object.prototype.toString.call(x6) !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x6), + "[object Date]", + 'Object.prototype.toString.call(new Date(1970, 0, 1)) must return "[object Date]"' +); var x7 = new Date(1999, 11, 31); -if (Object.prototype.toString.call(x7) !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x7), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 11, 31)) must return "[object Date]"' +); var x8 = new Date(1999, 12, 1); -if (Object.prototype.toString.call(x8) !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x8), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 12, 1)) must return "[object Date]"' +); var x9 = new Date(2000, 0, 1); -if (Object.prototype.toString.call(x9) !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x9), + "[object Date]", + 'Object.prototype.toString.call(new Date(2000, 0, 1)) must return "[object Date]"' +); var x10 = new Date(2099, 11, 31); -if (Object.prototype.toString.call(x10) !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x10), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 11, 31)) must return "[object Date]"' +); var x11 = new Date(2099, 12, 1); -if (Object.prototype.toString.call(x11) !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x11), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 12, 1)) must return "[object Date]"' +); var x12 = new Date(2100, 0, 1); -if (Object.prototype.toString.call(x12) !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x12), + "[object Date]", + 'Object.prototype.toString.call(new Date(2100, 0, 1)) must return "[object Date]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T2.2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T2.2.js index 20acdb4bfaca..6720987a6880 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T2.2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T2.2.js @@ -14,63 +14,39 @@ description: > Date.prototype.toString = Object.prototype.toString; var x1 = new Date(1899, 11, 31); -if (x1.toString() !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x1.toString(), "[object Date]", 'x1.toString() must return "[object Date]"'); var x2 = new Date(1899, 12, 1); -if (x2.toString() !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x2.toString(), "[object Date]", 'x2.toString() must return "[object Date]"'); var x3 = new Date(1900, 0, 1); -if (x3.toString() !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x3.toString(), "[object Date]", 'x3.toString() must return "[object Date]"'); var x4 = new Date(1969, 11, 31); -if (x4.toString() !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x4.toString(), "[object Date]", 'x4.toString() must return "[object Date]"'); var x5 = new Date(1969, 12, 1); -if (x5.toString() !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x5.toString(), "[object Date]", 'x5.toString() must return "[object Date]"'); var x6 = new Date(1970, 0, 1); -if (x6.toString() !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x6.toString(), "[object Date]", 'x6.toString() must return "[object Date]"'); var x7 = new Date(1999, 11, 31); -if (x7.toString() !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x7.toString(), "[object Date]", 'x7.toString() must return "[object Date]"'); var x8 = new Date(1999, 12, 1); -if (x8.toString() !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x8.toString(), "[object Date]", 'x8.toString() must return "[object Date]"'); var x9 = new Date(2000, 0, 1); -if (x9.toString() !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x9.toString(), "[object Date]", 'x9.toString() must return "[object Date]"'); var x10 = new Date(2099, 11, 31); -if (x10.toString() !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x10.toString(), "[object Date]", 'x10.toString() must return "[object Date]"'); var x11 = new Date(2099, 12, 1); -if (x11.toString() !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x11.toString(), "[object Date]", 'x11.toString() must return "[object Date]"'); var x12 = new Date(2100, 0, 1); -if (x12.toString() !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x12.toString(), "[object Date]", 'x12.toString() must return "[object Date]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T3.1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T3.1.js index 1b2f60f77104..6d647529313e 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T3.1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T3.1.js @@ -12,63 +12,99 @@ description: > ---*/ var x1 = new Date(1899, 11, 31, 23); -if (Object.prototype.toString.call(x1) !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x1), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 11, 31, 23)) must return "[object Date]"' +); var x2 = new Date(1899, 12, 1, 0); -if (Object.prototype.toString.call(x2) !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x2), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 12, 1, 0)) must return "[object Date]"' +); var x3 = new Date(1900, 0, 1, 0); -if (Object.prototype.toString.call(x3) !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x3), + "[object Date]", + 'Object.prototype.toString.call(new Date(1900, 0, 1, 0)) must return "[object Date]"' +); var x4 = new Date(1969, 11, 31, 23); -if (Object.prototype.toString.call(x4) !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x4), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 11, 31, 23)) must return "[object Date]"' +); var x5 = new Date(1969, 12, 1, 0); -if (Object.prototype.toString.call(x5) !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x5), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 12, 1, 0)) must return "[object Date]"' +); var x6 = new Date(1970, 0, 1, 0); -if (Object.prototype.toString.call(x6) !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x6), + "[object Date]", + 'Object.prototype.toString.call(new Date(1970, 0, 1, 0)) must return "[object Date]"' +); var x7 = new Date(1999, 11, 31, 23); -if (Object.prototype.toString.call(x7) !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x7), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 11, 31, 23)) must return "[object Date]"' +); var x8 = new Date(1999, 12, 1, 0); -if (Object.prototype.toString.call(x8) !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x8), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 12, 1, 0)) must return "[object Date]"' +); var x9 = new Date(2000, 0, 1, 0); -if (Object.prototype.toString.call(x9) !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x9), + "[object Date]", + 'Object.prototype.toString.call(new Date(2000, 0, 1, 0)) must return "[object Date]"' +); var x10 = new Date(2099, 11, 31, 23); -if (Object.prototype.toString.call(x10) !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x10), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 11, 31, 23)) must return "[object Date]"' +); var x11 = new Date(2099, 12, 1, 0); -if (Object.prototype.toString.call(x11) !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x11), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 12, 1, 0)) must return "[object Date]"' +); var x12 = new Date(2100, 0, 1, 0); -if (Object.prototype.toString.call(x12) !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x12), + "[object Date]", + 'Object.prototype.toString.call(new Date(2100, 0, 1, 0)) must return "[object Date]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T3.2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T3.2.js index 23e72dbe4f37..25cf161728c2 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T3.2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T3.2.js @@ -14,63 +14,39 @@ description: > Date.prototype.toString = Object.prototype.toString; var x1 = new Date(1899, 11, 31, 23); -if (x1.toString() !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x1.toString(), "[object Date]", 'x1.toString() must return "[object Date]"'); var x2 = new Date(1899, 12, 1, 0); -if (x2.toString() !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x2.toString(), "[object Date]", 'x2.toString() must return "[object Date]"'); var x3 = new Date(1900, 0, 1, 0); -if (x3.toString() !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x3.toString(), "[object Date]", 'x3.toString() must return "[object Date]"'); var x4 = new Date(1969, 11, 31, 23); -if (x4.toString() !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x4.toString(), "[object Date]", 'x4.toString() must return "[object Date]"'); var x5 = new Date(1969, 12, 1, 0); -if (x5.toString() !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x5.toString(), "[object Date]", 'x5.toString() must return "[object Date]"'); var x6 = new Date(1970, 0, 1, 0); -if (x6.toString() !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x6.toString(), "[object Date]", 'x6.toString() must return "[object Date]"'); var x7 = new Date(1999, 11, 31, 23); -if (x7.toString() !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x7.toString(), "[object Date]", 'x7.toString() must return "[object Date]"'); var x8 = new Date(1999, 12, 1, 0); -if (x8.toString() !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x8.toString(), "[object Date]", 'x8.toString() must return "[object Date]"'); var x9 = new Date(2000, 0, 1, 0); -if (x9.toString() !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x9.toString(), "[object Date]", 'x9.toString() must return "[object Date]"'); var x10 = new Date(2099, 11, 31, 23); -if (x10.toString() !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x10.toString(), "[object Date]", 'x10.toString() must return "[object Date]"'); var x11 = new Date(2099, 12, 1, 0); -if (x11.toString() !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x11.toString(), "[object Date]", 'x11.toString() must return "[object Date]"'); var x12 = new Date(2100, 0, 1, 0); -if (x12.toString() !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x12.toString(), "[object Date]", 'x12.toString() must return "[object Date]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T4.1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T4.1.js index d9673add07af..35c92fe30ba3 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T4.1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T4.1.js @@ -12,63 +12,99 @@ description: > ---*/ var x1 = new Date(1899, 11, 31, 23, 59); -if (Object.prototype.toString.call(x1) !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x1), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 11, 31, 23, 59)) must return "[object Date]"' +); var x2 = new Date(1899, 12, 1, 0, 0); -if (Object.prototype.toString.call(x2) !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x2), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 12, 1, 0, 0)) must return "[object Date]"' +); var x3 = new Date(1900, 0, 1, 0, 0); -if (Object.prototype.toString.call(x3) !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x3), + "[object Date]", + 'Object.prototype.toString.call(new Date(1900, 0, 1, 0, 0)) must return "[object Date]"' +); var x4 = new Date(1969, 11, 31, 23, 59); -if (Object.prototype.toString.call(x4) !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x4), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 11, 31, 23, 59)) must return "[object Date]"' +); var x5 = new Date(1969, 12, 1, 0, 0); -if (Object.prototype.toString.call(x5) !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x5), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 12, 1, 0, 0)) must return "[object Date]"' +); var x6 = new Date(1970, 0, 1, 0, 0); -if (Object.prototype.toString.call(x6) !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x6), + "[object Date]", + 'Object.prototype.toString.call(new Date(1970, 0, 1, 0, 0)) must return "[object Date]"' +); var x7 = new Date(1999, 11, 31, 23, 59); -if (Object.prototype.toString.call(x7) !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x7), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 11, 31, 23, 59)) must return "[object Date]"' +); var x8 = new Date(1999, 12, 1, 0, 0); -if (Object.prototype.toString.call(x8) !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x8), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 12, 1, 0, 0)) must return "[object Date]"' +); var x9 = new Date(2000, 0, 1, 0, 0); -if (Object.prototype.toString.call(x9) !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x9), + "[object Date]", + 'Object.prototype.toString.call(new Date(2000, 0, 1, 0, 0)) must return "[object Date]"' +); var x10 = new Date(2099, 11, 31, 23, 59); -if (Object.prototype.toString.call(x10) !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x10), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 11, 31, 23, 59)) must return "[object Date]"' +); var x11 = new Date(2099, 12, 1, 0, 0); -if (Object.prototype.toString.call(x11) !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x11), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 12, 1, 0, 0)) must return "[object Date]"' +); var x12 = new Date(2100, 0, 1, 0, 0); -if (Object.prototype.toString.call(x12) !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x12), + "[object Date]", + 'Object.prototype.toString.call(new Date(2100, 0, 1, 0, 0)) must return "[object Date]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T4.2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T4.2.js index ccdc85feed3f..455e1dde8fd4 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T4.2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T4.2.js @@ -14,63 +14,39 @@ description: > Date.prototype.toString = Object.prototype.toString; var x1 = new Date(1899, 11, 31, 23, 59); -if (x1.toString() !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x1.toString(), "[object Date]", 'x1.toString() must return "[object Date]"'); var x2 = new Date(1899, 12, 1, 0, 0); -if (x2.toString() !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x2.toString(), "[object Date]", 'x2.toString() must return "[object Date]"'); var x3 = new Date(1900, 0, 1, 0, 0); -if (x3.toString() !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x3.toString(), "[object Date]", 'x3.toString() must return "[object Date]"'); var x4 = new Date(1969, 11, 31, 23, 59); -if (x4.toString() !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x4.toString(), "[object Date]", 'x4.toString() must return "[object Date]"'); var x5 = new Date(1969, 12, 1, 0, 0); -if (x5.toString() !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x5.toString(), "[object Date]", 'x5.toString() must return "[object Date]"'); var x6 = new Date(1970, 0, 1, 0, 0); -if (x6.toString() !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x6.toString(), "[object Date]", 'x6.toString() must return "[object Date]"'); var x7 = new Date(1999, 11, 31, 23, 59); -if (x7.toString() !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x7.toString(), "[object Date]", 'x7.toString() must return "[object Date]"'); var x8 = new Date(1999, 12, 1, 0, 0); -if (x8.toString() !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x8.toString(), "[object Date]", 'x8.toString() must return "[object Date]"'); var x9 = new Date(2000, 0, 1, 0, 0); -if (x9.toString() !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x9.toString(), "[object Date]", 'x9.toString() must return "[object Date]"'); var x10 = new Date(2099, 11, 31, 23, 59); -if (x10.toString() !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x10.toString(), "[object Date]", 'x10.toString() must return "[object Date]"'); var x11 = new Date(2099, 12, 1, 0, 0); -if (x11.toString() !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x11.toString(), "[object Date]", 'x11.toString() must return "[object Date]"'); var x12 = new Date(2100, 0, 1, 0, 0); -if (x12.toString() !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x12.toString(), "[object Date]", 'x12.toString() must return "[object Date]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T5.1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T5.1.js index 8918637b1a28..ce501bf066d8 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T5.1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T5.1.js @@ -10,63 +10,99 @@ description: 6 arguments, (year, month, date, hours, minutes, seconds) ---*/ var x1 = new Date(1899, 11, 31, 23, 59, 59); -if (Object.prototype.toString.call(x1) !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x1), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 11, 31, 23, 59, 59)) must return "[object Date]"' +); var x2 = new Date(1899, 12, 1, 0, 0, 0); -if (Object.prototype.toString.call(x2) !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x2), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 12, 1, 0, 0, 0)) must return "[object Date]"' +); var x3 = new Date(1900, 0, 1, 0, 0, 0); -if (Object.prototype.toString.call(x3) !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x3), + "[object Date]", + 'Object.prototype.toString.call(new Date(1900, 0, 1, 0, 0, 0)) must return "[object Date]"' +); var x4 = new Date(1969, 11, 31, 23, 59, 59); -if (Object.prototype.toString.call(x4) !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x4), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 11, 31, 23, 59, 59)) must return "[object Date]"' +); var x5 = new Date(1969, 12, 1, 0, 0, 0); -if (Object.prototype.toString.call(x5) !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x5), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 12, 1, 0, 0, 0)) must return "[object Date]"' +); var x6 = new Date(1970, 0, 1, 0, 0, 0); -if (Object.prototype.toString.call(x6) !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x6), + "[object Date]", + 'Object.prototype.toString.call(new Date(1970, 0, 1, 0, 0, 0)) must return "[object Date]"' +); var x7 = new Date(1999, 11, 31, 23, 59, 59); -if (Object.prototype.toString.call(x7) !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x7), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 11, 31, 23, 59, 59)) must return "[object Date]"' +); var x8 = new Date(1999, 12, 1, 0, 0, 0); -if (Object.prototype.toString.call(x8) !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x8), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 12, 1, 0, 0, 0)) must return "[object Date]"' +); var x9 = new Date(2000, 0, 1, 0, 0, 0); -if (Object.prototype.toString.call(x9) !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x9), + "[object Date]", + 'Object.prototype.toString.call(new Date(2000, 0, 1, 0, 0, 0)) must return "[object Date]"' +); var x10 = new Date(2099, 11, 31, 23, 59, 59); -if (Object.prototype.toString.call(x10) !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x10), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 11, 31, 23, 59, 59)) must return "[object Date]"' +); var x11 = new Date(2099, 12, 1, 0, 0, 0); -if (Object.prototype.toString.call(x11) !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x11), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 12, 1, 0, 0, 0)) must return "[object Date]"' +); var x12 = new Date(2100, 0, 1, 0, 0, 0); -if (Object.prototype.toString.call(x12) !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x12), + "[object Date]", + 'Object.prototype.toString.call(new Date(2100, 0, 1, 0, 0, 0)) must return "[object Date]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T5.2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T5.2.js index fa0318c15a85..3be5840ac2e9 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T5.2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T5.2.js @@ -14,63 +14,39 @@ description: > Date.prototype.toString = Object.prototype.toString; var x1 = new Date(1899, 11, 31, 23, 59, 59); -if (x1.toString() !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x1.toString(), "[object Date]", 'x1.toString() must return "[object Date]"'); var x2 = new Date(1899, 12, 1, 0, 0, 0); -if (x2.toString() !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x2.toString(), "[object Date]", 'x2.toString() must return "[object Date]"'); var x3 = new Date(1900, 0, 1, 0, 0, 0); -if (x3.toString() !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x3.toString(), "[object Date]", 'x3.toString() must return "[object Date]"'); var x4 = new Date(1969, 11, 31, 23, 59, 59); -if (x4.toString() !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x4.toString(), "[object Date]", 'x4.toString() must return "[object Date]"'); var x5 = new Date(1969, 12, 1, 0, 0, 0); -if (x5.toString() !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x5.toString(), "[object Date]", 'x5.toString() must return "[object Date]"'); var x6 = new Date(1970, 0, 1, 0, 0, 0); -if (x6.toString() !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x6.toString(), "[object Date]", 'x6.toString() must return "[object Date]"'); var x7 = new Date(1999, 11, 31, 23, 59, 59); -if (x7.toString() !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x7.toString(), "[object Date]", 'x7.toString() must return "[object Date]"'); var x8 = new Date(1999, 12, 1, 0, 0, 0); -if (x8.toString() !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x8.toString(), "[object Date]", 'x8.toString() must return "[object Date]"'); var x9 = new Date(2000, 0, 1, 0, 0, 0); -if (x9.toString() !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x9.toString(), "[object Date]", 'x9.toString() must return "[object Date]"'); var x10 = new Date(2099, 11, 31, 23, 59, 59); -if (x10.toString() !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x10.toString(), "[object Date]", 'x10.toString() must return "[object Date]"'); var x11 = new Date(2099, 12, 1, 0, 0, 0); -if (x11.toString() !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x11.toString(), "[object Date]", 'x11.toString() must return "[object Date]"'); var x12 = new Date(2100, 0, 1, 0, 0, 0); -if (x12.toString() !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x12.toString(), "[object Date]", 'x12.toString() must return "[object Date]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T6.1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T6.1.js index 39cd7a20977b..64e23c493c95 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T6.1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T6.1.js @@ -10,63 +10,99 @@ description: 7 arguments, (year, month, date, hours, minutes, seconds, ms) ---*/ var x1 = new Date(1899, 11, 31, 23, 59, 59, 999); -if (Object.prototype.toString.call(x1) !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x1), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 11, 31, 23, 59, 59, 999)) must return "[object Date]"' +); var x2 = new Date(1899, 12, 1, 0, 0, 0, 0); -if (Object.prototype.toString.call(x2) !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x2), + "[object Date]", + 'Object.prototype.toString.call(new Date(1899, 12, 1, 0, 0, 0, 0)) must return "[object Date]"' +); var x3 = new Date(1900, 0, 1, 0, 0, 0, 0); -if (Object.prototype.toString.call(x3) !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x3), + "[object Date]", + 'Object.prototype.toString.call(new Date(1900, 0, 1, 0, 0, 0, 0)) must return "[object Date]"' +); var x4 = new Date(1969, 11, 31, 23, 59, 59, 999); -if (Object.prototype.toString.call(x4) !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x4), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 11, 31, 23, 59, 59, 999)) must return "[object Date]"' +); var x5 = new Date(1969, 12, 1, 0, 0, 0, 0); -if (Object.prototype.toString.call(x5) !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x5), + "[object Date]", + 'Object.prototype.toString.call(new Date(1969, 12, 1, 0, 0, 0, 0)) must return "[object Date]"' +); var x6 = new Date(1970, 0, 1, 0, 0, 0, 0); -if (Object.prototype.toString.call(x6) !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x6), + "[object Date]", + 'Object.prototype.toString.call(new Date(1970, 0, 1, 0, 0, 0, 0)) must return "[object Date]"' +); var x7 = new Date(1999, 11, 31, 23, 59, 59, 999); -if (Object.prototype.toString.call(x7) !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x7), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 11, 31, 23, 59, 59, 999)) must return "[object Date]"' +); var x8 = new Date(1999, 12, 1, 0, 0, 0, 0); -if (Object.prototype.toString.call(x8) !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x8), + "[object Date]", + 'Object.prototype.toString.call(new Date(1999, 12, 1, 0, 0, 0, 0)) must return "[object Date]"' +); var x9 = new Date(2000, 0, 1, 0, 0, 0, 0); -if (Object.prototype.toString.call(x9) !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x9), + "[object Date]", + 'Object.prototype.toString.call(new Date(2000, 0, 1, 0, 0, 0, 0)) must return "[object Date]"' +); var x10 = new Date(2099, 11, 31, 23, 59, 59, 999); -if (Object.prototype.toString.call(x10) !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x10), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 11, 31, 23, 59, 59, 999)) must return "[object Date]"' +); var x11 = new Date(2099, 12, 1, 0, 0, 0, 0); -if (Object.prototype.toString.call(x11) !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x11), + "[object Date]", + 'Object.prototype.toString.call(new Date(2099, 12, 1, 0, 0, 0, 0)) must return "[object Date]"' +); var x12 = new Date(2100, 0, 1, 0, 0, 0, 0); -if (Object.prototype.toString.call(x12) !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x12), + "[object Date]", + 'Object.prototype.toString.call(new Date(2100, 0, 1, 0, 0, 0, 0)) must return "[object Date]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T6.2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T6.2.js index c169f0023c18..2948d766ab9c 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T6.2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A3_T6.2.js @@ -14,63 +14,39 @@ description: > Date.prototype.toString = Object.prototype.toString; var x1 = new Date(1899, 11, 31, 23, 59, 59, 999); -if (x1.toString() !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x1.toString(), "[object Date]", 'x1.toString() must return "[object Date]"'); var x2 = new Date(1899, 12, 1, 0, 0, 0, 0); -if (x2.toString() !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x2.toString(), "[object Date]", 'x2.toString() must return "[object Date]"'); var x3 = new Date(1900, 0, 1, 0, 0, 0, 0); -if (x3.toString() !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x3.toString(), "[object Date]", 'x3.toString() must return "[object Date]"'); var x4 = new Date(1969, 11, 31, 23, 59, 59, 999); -if (x4.toString() !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x4.toString(), "[object Date]", 'x4.toString() must return "[object Date]"'); var x5 = new Date(1969, 12, 1, 0, 0, 0, 0); -if (x5.toString() !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x5.toString(), "[object Date]", 'x5.toString() must return "[object Date]"'); var x6 = new Date(1970, 0, 1, 0, 0, 0, 0); -if (x6.toString() !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x6.toString(), "[object Date]", 'x6.toString() must return "[object Date]"'); var x7 = new Date(1999, 11, 31, 23, 59, 59, 999); -if (x7.toString() !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x7.toString(), "[object Date]", 'x7.toString() must return "[object Date]"'); var x8 = new Date(1999, 12, 1, 0, 0, 0, 0); -if (x8.toString() !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x8.toString(), "[object Date]", 'x8.toString() must return "[object Date]"'); var x9 = new Date(2000, 0, 1, 0, 0, 0, 0); -if (x9.toString() !== "[object Date]") { - throw new Test262Error("#9: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x9.toString(), "[object Date]", 'x9.toString() must return "[object Date]"'); var x10 = new Date(2099, 11, 31, 23, 59, 59, 999); -if (x10.toString() !== "[object Date]") { - throw new Test262Error("#10: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x10.toString(), "[object Date]", 'x10.toString() must return "[object Date]"'); var x11 = new Date(2099, 12, 1, 0, 0, 0, 0); -if (x11.toString() !== "[object Date]") { - throw new Test262Error("#11: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x11.toString(), "[object Date]", 'x11.toString() must return "[object Date]"'); var x12 = new Date(2100, 0, 1, 0, 0, 0, 0); -if (x12.toString() !== "[object Date]") { - throw new Test262Error("#12: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x12.toString(), "[object Date]", 'x12.toString() must return "[object Date]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T0.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T0.js new file mode 100644 index 000000000000..240edee3ed54 --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T0.js @@ -0,0 +1,31 @@ +// Copyright 2009 the Sputnik authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: | + The [[Value]] property of the newly constructed object + is set by following steps: + 1. Call ToNumber(year) + 2. Call ToNumber(month) + 3. If date is supplied use ToNumber(date) + 4. If hours is supplied use ToNumber(hours) + 5. If minutes is supplied use ToNumber(minutes) + 6. If seconds is supplied use ToNumber(seconds) + 7. If ms is supplied use ToNumber(ms) +esid: sec-date-year-month-date-hours-minutes-seconds-ms +description: 1 argument (year) +---*/ + +function PoisonedValueOf(val) { + this.value = val; + this.valueOf = function() { + throw new Test262Error(); + }; + this.toString = function() {}; +} + +assert.throws(Test262Error, () => { + new Date(new PoisonedValueOf(1)); +}, '`new Date(new PoisonedValueOf(1))` throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T1.js index 471ae606d00f..1614b8cc86d8 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T1.js @@ -16,36 +16,20 @@ esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 2 arguments, (year, month) ---*/ -var myObj = function(val) { +function PoisonedValueOf(val) { this.value = val; this.valueOf = function() { - throw "valueOf-" + this.value; + throw new Test262Error(); }; - this.toString = function() { - throw "toString-" + this.value; - }; -}; - -//CHECK#1 -try { - var x1 = new Date(new myObj(1), new myObj(2)); - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); -} -catch (e) { - if (e !== "valueOf-1") { - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); - } + this.toString = function() {}; } -//CHECK#2 -try { - var x2 = new Date(1, new myObj(2)); - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); -} -catch (e) { - if (e !== "valueOf-2") { - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); - } -} +assert.throws(Test262Error, () => { + new Date(new PoisonedValueOf(1), new PoisonedValueOf(2)); +}, '`new Date(new PoisonedValueOf(1), new PoisonedValueOf(2))` throws a Test262Error exception'); + +assert.throws(Test262Error, () => { + new Date(1, new PoisonedValueOf(2)); +}, '`new Date(1, new PoisonedValueOf(2))` throws a Test262Error exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T2.js index ccf92ef01528..8b8d4a9dd406 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T2.js @@ -16,47 +16,24 @@ esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 3 arguments, (year, month, date) ---*/ -var myObj = function(val) { +function PoisonedValueOf(val) { this.value = val; this.valueOf = function() { - throw "valueOf-" + this.value; + throw new Test262Error(); }; - this.toString = function() { - throw "toString-" + this.value; - }; -}; - -//CHECK#1 -try { - var x1 = new Date(new myObj(1), new myObj(2), new myObj(3)); - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); -} -catch (e) { - if (e !== "valueOf-1") { - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); - } + this.toString = function() {}; } -//CHECK#2 -try { - var x2 = new Date(1, new myObj(2), new myObj(3)); - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); -} -catch (e) { - if (e !== "valueOf-2") { - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); - } -} +assert.throws(Test262Error, () => { + new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3)); +}, '`new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3))` throws a Test262Error exception'); -//CHECK#3 -try { - var x3 = new Date(1, 2, new myObj(3)); - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); -} -catch (e) { - if (e !== "valueOf-3") { - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3)); +}, '`new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3))` throws a Test262Error exception'); + +assert.throws(Test262Error, () => { + new Date(1, 2, new PoisonedValueOf(3)); +}, '`new Date(1, 2, new PoisonedValueOf(3))` throws a Test262Error exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T3.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T3.js index 6272351543ca..99b3cc076ab6 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T3.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T3.js @@ -16,58 +16,28 @@ esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 4 arguments, (year, month, date, hours) ---*/ -var myObj = function(val) { +function PoisonedValueOf(val) { this.value = val; this.valueOf = function() { - throw "valueOf-" + this.value; + throw new Test262Error(); }; - this.toString = function() { - throw "toString-" + this.value; - }; -}; - -//CHECK#1 -try { - var x1 = new Date(new myObj(1), new myObj(2), new myObj(3), new myObj(4)); - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); -} -catch (e) { - if (e !== "valueOf-1") { - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); - } + this.toString = function() {}; } -//CHECK#2 -try { - var x2 = new Date(1, new myObj(2), new myObj(3), new myObj(4)); - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); -} -catch (e) { - if (e !== "valueOf-2") { - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); - } -} +assert.throws(Test262Error, () => { + new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4)); +}, '`new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4))` throws a Test262Error exception'); -//CHECK#3 -try { - var x3 = new Date(1, 2, new myObj(3), new myObj(4)); - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); -} -catch (e) { - if (e !== "valueOf-3") { - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4)); +}, '`new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4))` throws a Test262Error exception'); -//CHECK#4 -try { - var x4 = new Date(1, 2, 3, new myObj(4)); - throw new Test262Error("#4: The 4th step is calling ToNumber(hours)"); -} -catch (e) { - if (e !== "valueOf-4") { - throw new Test262Error("#4: The 4th step is calling ToNumber(hours)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, new PoisonedValueOf(3), new PoisonedValueOf(4)); +}, '`new Date(1, 2, new PoisonedValueOf(3), new PoisonedValueOf(4))` throws a Test262Error exception'); + +assert.throws(Test262Error, () => { + new Date(1, 2, 3, new PoisonedValueOf(4)); +}, '`new Date(1, 2, 3, new PoisonedValueOf(4))` throws a Test262Error exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T4.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T4.js index bab7809c0382..2decd9834877 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T4.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T4.js @@ -16,69 +16,32 @@ esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 5 arguments, (year, month, date, hours, minutes) ---*/ -var myObj = function(val) { +function PoisonedValueOf(val) { this.value = val; this.valueOf = function() { - throw "valueOf-" + this.value; + throw new Test262Error(); }; - this.toString = function() { - throw "toString-" + this.value; - }; -}; - -//CHECK#1 -try { - var x1 = new Date(new myObj(1), new myObj(2), new myObj(3), new myObj(4), new myObj(5)); - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); -} -catch (e) { - if (e !== "valueOf-1") { - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); - } + this.toString = function() {}; } -//CHECK#2 -try { - var x2 = new Date(1, new myObj(2), new myObj(3), new myObj(4), new myObj(5)); - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); -} -catch (e) { - if (e !== "valueOf-2") { - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); - } -} +assert.throws(Test262Error, () => { + new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5)); +}, '`new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5))` throws a Test262Error exception'); -//CHECK#3 -try { - var x3 = new Date(1, 2, new myObj(3), new myObj(4), new myObj(5)); - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); -} -catch (e) { - if (e !== "valueOf-3") { - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5)); +}, '`new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5))` throws a Test262Error exception'); -//CHECK#4 -try { - var x4 = new Date(1, 2, 3, new myObj(4), new myObj(5)); - throw new Test262Error("#4: The 4th step is calling ToNumber(hours)"); -} -catch (e) { - if (e !== "valueOf-4") { - throw new Test262Error("#4: The 4th step is calling ToNumber(hours)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5)); +}, '`new Date(1, 2, new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5))` throws a Test262Error exception'); -//CHECK#5 -try { - var x5 = new Date(1, 2, 3, 4, new myObj(5)); - throw new Test262Error("#5: The 5th step is calling ToNumber(minutes)"); -} -catch (e) { - if (e !== "valueOf-5") { - throw new Test262Error("#5: The 5th step is calling ToNumber(minutes)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, 3, new PoisonedValueOf(4), new PoisonedValueOf(5)); +}, '`new Date(1, 2, 3, new PoisonedValueOf(4), new PoisonedValueOf(5))` throws a Test262Error exception'); + +assert.throws(Test262Error, () => { + new Date(1, 2, 3, 4, new PoisonedValueOf(5)); +}, '`new Date(1, 2, 3, 4, new PoisonedValueOf(5))` throws a Test262Error exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T5.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T5.js index 116d8107c527..6908797a6835 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T5.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T5.js @@ -16,80 +16,36 @@ esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 6 arguments, (year, month, date, hours, minutes, seconds) ---*/ -var myObj = function(val) { +function PoisonedValueOf(val) { this.value = val; this.valueOf = function() { - throw "valueOf-" + this.value; + throw new Test262Error(); }; - this.toString = function() { - throw "toString-" + this.value; - }; -}; - -//CHECK#1 -try { - var x1 = new Date(new myObj(1), new myObj(2), new myObj(3), new myObj(4), new myObj(5), new myObj(6)); - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); -} -catch (e) { - if (e !== "valueOf-1") { - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); - } + this.toString = function() {}; } -//CHECK#2 -try { - var x2 = new Date(1, new myObj(2), new myObj(3), new myObj(4), new myObj(5), new myObj(6)); - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); -} -catch (e) { - if (e !== "valueOf-2") { - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); - } -} +assert.throws(Test262Error, () => { + new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6)); +}, '`new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6))` throws a Test262Error exception'); -//CHECK#3 -try { - var x3 = new Date(1, 2, new myObj(3), new myObj(4), new myObj(5), new myObj(6)); - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); -} -catch (e) { - if (e !== "valueOf-3") { - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6)); +}, '`new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6))` throws a Test262Error exception'); -//CHECK#4 -try { - var x4 = new Date(1, 2, 3, new myObj(4), new myObj(5), new myObj(6)); - throw new Test262Error("#4: The 4th step is calling ToNumber(hours)"); -} -catch (e) { - if (e !== "valueOf-4") { - throw new Test262Error("#4: The 4th step is calling ToNumber(hours)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6)); +}, '`new Date(1, 2, new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6))` throws a Test262Error exception'); -//CHECK#5 -try { - var x5 = new Date(1, 2, 3, 4, new myObj(5), new myObj(6)); - throw new Test262Error("#5: The 5th step is calling ToNumber(minutes)"); -} -catch (e) { - if (e !== "valueOf-5") { - throw new Test262Error("#5: The 5th step is calling ToNumber(minutes)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, 3, new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6)); +}, '`new Date(1, 2, 3, new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6))` throws a Test262Error exception'); -//CHECK#6 -try { - var x6 = new Date(1, 2, 3, 4, 5, new myObj(6)); - throw new Test262Error("#6: The 6th step is calling ToNumber(seconds)"); -} -catch (e) { - if (e !== "valueOf-6") { - throw new Test262Error("#6: The 6th step is calling ToNumber(seconds)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, 3, 4, new PoisonedValueOf(5), new PoisonedValueOf(6)); +}, '`new Date(1, 2, 3, 4, new PoisonedValueOf(5), new PoisonedValueOf(6))` throws a Test262Error exception'); + +assert.throws(Test262Error, () => { + new Date(1, 2, 3, 4, 5, new PoisonedValueOf(6)); +}, '`new Date(1, 2, 3, 4, 5, new PoisonedValueOf(6))` throws a Test262Error exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T6.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T6.js index b396d00ed679..bc0de6ac5c82 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T6.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A4_T6.js @@ -16,91 +16,40 @@ esid: sec-date-year-month-date-hours-minutes-seconds-ms description: 7 arguments, (year, month, date, hours, minutes, seconds, ms) ---*/ -var myObj = function(val) { +function PoisonedValueOf(val) { this.value = val; this.valueOf = function() { - throw "valueOf-" + this.value; + throw new Test262Error(); }; - this.toString = function() { - throw "toString-" + this.value; - }; -}; - -//CHECK#1 -try { - var x1 = new Date(new myObj(1), new myObj(2), new myObj(3), new myObj(4), new myObj(5), new myObj(6), new myObj(7)); - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); -} -catch (e) { - if (e !== "valueOf-1") { - throw new Test262Error("#1: The 1st step is calling ToNumber(year)"); - } + this.toString = function() {}; } -//CHECK#2 -try { - var x2 = new Date(1, new myObj(2), new myObj(3), new myObj(4), new myObj(5), new myObj(6), new myObj(7)); - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); -} -catch (e) { - if (e !== "valueOf-2") { - throw new Test262Error("#2: The 2nd step is calling ToNumber(month)"); - } -} +assert.throws(Test262Error, () => { + new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7)); +}, '`new Date(new PoisonedValueOf(1), new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7))` throws a Test262Error exception'); -//CHECK#3 -try { - var x3 = new Date(1, 2, new myObj(3), new myObj(4), new myObj(5), new myObj(6), new myObj(7)); - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); -} -catch (e) { - if (e !== "valueOf-3") { - throw new Test262Error("#3: The 3rd step is calling ToNumber(date)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7)); +}, '`new Date(1, new PoisonedValueOf(2), new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7))` throws a Test262Error exception'); -//CHECK#4 -try { - var x4 = new Date(1, 2, 3, new myObj(4), new myObj(5), new myObj(6), new myObj(7)); - throw new Test262Error("#4: The 4th step is calling ToNumber(hours)"); -} -catch (e) { - if (e !== "valueOf-4") { - throw new Test262Error("#4: The 4th step is calling ToNumber(hours)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7)); +}, '`new Date(1, 2, new PoisonedValueOf(3), new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7))` throws a Test262Error exception'); -//CHECK#5 -try { - var x5 = new Date(1, 2, 3, 4, new myObj(5), new myObj(6), new myObj(7)); - throw new Test262Error("#5: The 5th step is calling ToNumber(minutes)"); -} -catch (e) { - if (e !== "valueOf-5") { - throw new Test262Error("#5: The 5th step is calling ToNumber(minutes)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, 3, new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7)); +}, '`new Date(1, 2, 3, new PoisonedValueOf(4), new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7))` throws a Test262Error exception'); -//CHECK#6 -try { - var x6 = new Date(1, 2, 3, 4, 5, new myObj(6), new myObj(7)); - throw new Test262Error("#6: The 6th step is calling ToNumber(seconds)"); -} -catch (e) { - if (e !== "valueOf-6") { - throw new Test262Error("#6: The 6th step is calling ToNumber(seconds)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, 3, 4, new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7)); +}, '`new Date(1, 2, 3, 4, new PoisonedValueOf(5), new PoisonedValueOf(6), new PoisonedValueOf(7))` throws a Test262Error exception'); -//CHECK#7 -try { - var x7 = new Date(1, 2, 3, 4, 5, 6, new myObj(7)); - throw new Test262Error("#7: The 7th step is calling ToNumber(ms)"); -} -catch (e) { - if (e !== "valueOf-7") { - throw new Test262Error("#7: The 7th step is calling ToNumber(ms)"); - } -} +assert.throws(Test262Error, () => { + new Date(1, 2, 3, 4, 5, new PoisonedValueOf(6), new PoisonedValueOf(7)); +}, '`new Date(1, 2, 3, 4, 5, new PoisonedValueOf(6), new PoisonedValueOf(7))` throws a Test262Error exception'); + +assert.throws(Test262Error, () => { + new Date(1, 2, 3, 4, 5, 6, new PoisonedValueOf(7)); +}, '`new Date(1, 2, 3, 4, 5, 6, new PoisonedValueOf(7))` throws a Test262Error exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T1.js index 580277d79bcd..9b0baad700aa 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T1.js @@ -15,39 +15,39 @@ function DateValue(year, month, date, hours, minutes, seconds, ms) { var x; x = DateValue(1899, 11); -assert.sameValue(x, NaN, "(1899, 11)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1899, 12); -assert.sameValue(x, NaN, "(1899, 12)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1900, 0); -assert.sameValue(x, NaN, "(1900, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 11); -assert.sameValue(x, NaN, "(1969, 11)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 12); -assert.sameValue(x, NaN, "(1969, 12)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1970, 0); -assert.sameValue(x, NaN, "(1970, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 11); -assert.sameValue(x, NaN, "(1999, 11)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 12); -assert.sameValue(x, NaN, "(1999, 12)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2000, 0); -assert.sameValue(x, NaN, "(2000, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 11); -assert.sameValue(x, NaN, "(2099, 11)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 12); -assert.sameValue(x, NaN, "(2099, 12)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2100, 0); -assert.sameValue(x, NaN, "(2100, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T2.js index 57400f61bd64..c5c181361ab5 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T2.js @@ -15,39 +15,39 @@ function DateValue(year, month, date, hours, minutes, seconds, ms) { var x; x = DateValue(1899, 11, 31); -assert.sameValue(x, NaN, "(1899, 11, 31)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1899, 12, 1); -assert.sameValue(x, NaN, "(1899, 12, 1)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1900, 0, 1); -assert.sameValue(x, NaN, "(1900, 0, 1)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 11, 31); -assert.sameValue(x, NaN, "(1969, 11, 31)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 12, 1); -assert.sameValue(x, NaN, "(1969, 12, 1)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1970, 0, 1); -assert.sameValue(x, NaN, "(1970, 0, 1)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 11, 31); -assert.sameValue(x, NaN, "(1999, 11, 31)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 12, 1); -assert.sameValue(x, NaN, "(1999, 12, 1)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2000, 0, 1); -assert.sameValue(x, NaN, "(2000, 0, 1)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 11, 31); -assert.sameValue(x, NaN, "(2099, 11, 31)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 12, 1); -assert.sameValue(x, NaN, "(2099, 12, 1)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2100, 0, 1); -assert.sameValue(x, NaN, "(2100, 0, 1)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T3.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T3.js index fa91428df691..b011be91efb1 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T3.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T3.js @@ -15,39 +15,39 @@ function DateValue(year, month, date, hours, minutes, seconds, ms) { var x; x = DateValue(1899, 11, 31, 23); -assert.sameValue(x, NaN, "(1899, 11, 31, 23)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1899, 12, 1, 0); -assert.sameValue(x, NaN, "(1899, 12, 1, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1900, 0, 1, 0); -assert.sameValue(x, NaN, "(1900, 0, 1, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 11, 31, 23); -assert.sameValue(x, NaN, "(1969, 11, 31, 23)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 12, 1, 0); -assert.sameValue(x, NaN, "(1969, 12, 1, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1970, 0, 1, 0); -assert.sameValue(x, NaN, "(1970, 0, 1, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 11, 31, 23); -assert.sameValue(x, NaN, "(1999, 11, 31, 23)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 12, 1, 0); -assert.sameValue(x, NaN, "(1999, 12, 1, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2000, 0, 1, 0); -assert.sameValue(x, NaN, "(2000, 0, 1, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 11, 31, 23); -assert.sameValue(x, NaN, "(2099, 11, 31, 23)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 12, 1, 0); -assert.sameValue(x, NaN, "(2099, 12, 1, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2100, 0, 1, 0); -assert.sameValue(x, NaN, "(2100, 0, 1, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T4.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T4.js index 11535a5f44fa..d482aab2b1fc 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T4.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T4.js @@ -15,39 +15,39 @@ function DateValue(year, month, date, hours, minutes, seconds, ms) { var x; x = DateValue(1899, 11, 31, 23, 59); -assert.sameValue(x, NaN, "(1899, 11, 31, 23, 59)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1899, 12, 1, 0, 0); -assert.sameValue(x, NaN, "(1899, 12, 1, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1900, 0, 1, 0, 0); -assert.sameValue(x, NaN, "(1900, 0, 1, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 11, 31, 23, 59); -assert.sameValue(x, NaN, "(1969, 11, 31, 23, 59)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 12, 1, 0, 0); -assert.sameValue(x, NaN, "(1969, 12, 1, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1970, 0, 1, 0, 0); -assert.sameValue(x, NaN, "(1970, 0, 1, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 11, 31, 23, 59); -assert.sameValue(x, NaN, "(1999, 11, 31, 23, 59)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 12, 1, 0, 0); -assert.sameValue(x, NaN, "(1999, 12, 1, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2000, 0, 1, 0, 0); -assert.sameValue(x, NaN, "(2000, 0, 1, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 11, 31, 23, 59); -assert.sameValue(x, NaN, "(2099, 11, 31, 23, 59)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 12, 1, 0, 0); -assert.sameValue(x, NaN, "(2099, 12, 1, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2100, 0, 1, 0, 0); -assert.sameValue(x, NaN, "(2100, 0, 1, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T5.js b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T5.js index 825174b7619f..41480d29d7bf 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T5.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.1_A6_T5.js @@ -15,39 +15,39 @@ function DateValue(year, month, date, hours, minutes, seconds, ms) { var x; x = DateValue(1899, 11, 31, 23, 59, 59); -assert.sameValue(x, NaN, "(1899, 11, 31, 23, 59, 59)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1899, 12, 1, 0, 0, 0); -assert.sameValue(x, NaN, "(1899, 12, 1, 0, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1900, 0, 1, 0, 0, 0); -assert.sameValue(x, NaN, "(1900, 0, 1, 0, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 11, 31, 23, 59, 59); -assert.sameValue(x, NaN, "(1969, 11, 31, 23, 59, 59)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1969, 12, 1, 0, 0, 0); -assert.sameValue(x, NaN, "(1969, 12, 1, 0, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1970, 0, 1, 0, 0, 0); -assert.sameValue(x, NaN, "(1970, 0, 1, 0, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 11, 31, 23, 59, 59); -assert.sameValue(x, NaN, "(1999, 11, 31, 23, 59, 59)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(1999, 12, 1, 0, 0, 0); -assert.sameValue(x, NaN, "(1999, 12, 1, 0, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2000, 0, 1, 0, 0, 0); -assert.sameValue(x, NaN, "(2000, 0, 1, 0, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 11, 31, 23, 59, 59); -assert.sameValue(x, NaN, "(2099, 11, 31, 23, 59, 59)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2099, 12, 1, 0, 0, 0); -assert.sameValue(x, NaN, "(2099, 12, 1, 0, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); x = DateValue(2100, 0, 1, 0, 0, 0); -assert.sameValue(x, NaN, "(2100, 0, 1, 0, 0, 0)"); +assert.sameValue(x, NaN, 'The value of x is expected to equal NaN'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.2_A1_T1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.2_A1_T1.js index 33aea2995b86..ed603baee722 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.2_A1_T1.js @@ -9,149 +9,132 @@ esid: sec-date-value description: Checking types of newly created objects and it values includes: [dateConstants.js] ---*/ +assert.sameValue( + typeof new Date(date_1899_end), + "object", + 'The value of `typeof new Date(date_1899_end)` is expected to be "object"' +); -if (typeof new Date(date_1899_end) !== "object") { - throw new Test262Error("#1.1: typeof new Date(date_1899_end) === 'object'"); -} - -if (new Date(date_1899_end) === undefined) { - throw new Test262Error("#1.2: new Date(date_1899_end) === undefined"); -} +assert.notSameValue(new Date(date_1899_end), undefined, 'new Date(date_1899_end) is expected to not equal ``undefined``'); var x13 = new Date(date_1899_end); -if (typeof x13 !== "object") { - throw new Test262Error("#1.3: typeof new Date(date_1899_end) !== 'object'"); -} +assert.sameValue(typeof x13, "object", 'The value of `typeof x13` is expected to be "object"'); var x14 = new Date(date_1899_end); -if (x14 === undefined) { - throw new Test262Error("#1.4: new Date(date_1899_end) !== undefined"); -} +assert.notSameValue(x14, undefined, 'The value of x14 is expected to not equal ``undefined``'); -if (typeof new Date(date_1900_start) !== "object") { - throw new Test262Error("#2.1: typeof new Date(date_1900_start) === 'object'"); -} +assert.sameValue( + typeof new Date(date_1900_start), + "object", + 'The value of `typeof new Date(date_1900_start)` is expected to be "object"' +); -if (new Date(date_1900_start) === undefined) { - throw new Test262Error("#2.2: new Date(date_1900_start) === undefined"); -} +assert.notSameValue( + new Date(date_1900_start), + undefined, + 'new Date(date_1900_start) is expected to not equal ``undefined``' +); var x23 = new Date(date_1900_start); -if (typeof x23 !== "object") { - throw new Test262Error("#2.3: typeof new Date(date_1900_start) !== 'object'"); -} +assert.sameValue(typeof x23, "object", 'The value of `typeof x23` is expected to be "object"'); var x24 = new Date(date_1900_start); -if (x24 === undefined) { - throw new Test262Error("#2.4: new Date(date_1900_start) !== undefined"); -} +assert.notSameValue(x24, undefined, 'The value of x24 is expected to not equal ``undefined``'); -if (typeof new Date(date_1969_end) !== "object") { - throw new Test262Error("#3.1: typeof new Date(date_1969_end) === 'object'"); -} +assert.sameValue( + typeof new Date(date_1969_end), + "object", + 'The value of `typeof new Date(date_1969_end)` is expected to be "object"' +); -if (new Date(date_1969_end) === undefined) { - throw new Test262Error("#3.2: new Date(date_1969_end) === undefined"); -} +assert.notSameValue(new Date(date_1969_end), undefined, 'new Date(date_1969_end) is expected to not equal ``undefined``'); var x33 = new Date(date_1969_end); -if (typeof x33 !== "object") { - throw new Test262Error("#3.3: typeof new Date(date_1969_end) !== 'object'"); -} +assert.sameValue(typeof x33, "object", 'The value of `typeof x33` is expected to be "object"'); var x34 = new Date(date_1969_end); -if (x34 === undefined) { - throw new Test262Error("#3.4: new Date(date_1969_end) !== undefined"); -} +assert.notSameValue(x34, undefined, 'The value of x34 is expected to not equal ``undefined``'); -if (typeof new Date(date_1970_start) !== "object") { - throw new Test262Error("#4.1: typeof new Date(date_1970_start) === 'object'"); -} +assert.sameValue( + typeof new Date(date_1970_start), + "object", + 'The value of `typeof new Date(date_1970_start)` is expected to be "object"' +); -if (new Date(date_1970_start) === undefined) { - throw new Test262Error("#4.2: new Date(date_1970_start) === undefined"); -} +assert.notSameValue( + new Date(date_1970_start), + undefined, + 'new Date(date_1970_start) is expected to not equal ``undefined``' +); var x43 = new Date(date_1970_start); -if (typeof x43 !== "object") { - throw new Test262Error("#4.3: typeof new Date(date_1970_start) !== 'object'"); -} +assert.sameValue(typeof x43, "object", 'The value of `typeof x43` is expected to be "object"'); var x44 = new Date(date_1970_start); -if (x44 === undefined) { - throw new Test262Error("#4.4: new Date(date_1970_start) !== undefined"); -} +assert.notSameValue(x44, undefined, 'The value of x44 is expected to not equal ``undefined``'); -if (typeof new Date(date_1999_end) !== "object") { - throw new Test262Error("#5.1: typeof new Date(date_1999_end) === 'object'"); -} +assert.sameValue( + typeof new Date(date_1999_end), + "object", + 'The value of `typeof new Date(date_1999_end)` is expected to be "object"' +); -if (new Date(date_1999_end) === undefined) { - throw new Test262Error("#5.2: new Date(date_1999_end) === undefined"); -} +assert.notSameValue(new Date(date_1999_end), undefined, 'new Date(date_1999_end) is expected to not equal ``undefined``'); var x53 = new Date(date_1999_end); -if (typeof x53 !== "object") { - throw new Test262Error("#5.3: typeof new Date(date_1999_end) !== 'object'"); -} +assert.sameValue(typeof x53, "object", 'The value of `typeof x53` is expected to be "object"'); var x54 = new Date(date_1999_end); -if (x54 === undefined) { - throw new Test262Error("#5.4: new Date(date_1999_end) !== undefined"); -} +assert.notSameValue(x54, undefined, 'The value of x54 is expected to not equal ``undefined``'); -if (typeof new Date(date_2000_start) !== "object") { - throw new Test262Error("#6.1: typeof new Date(date_2000_start) === 'object'"); -} +assert.sameValue( + typeof new Date(date_2000_start), + "object", + 'The value of `typeof new Date(date_2000_start)` is expected to be "object"' +); -if (new Date(date_2000_start) === undefined) { - throw new Test262Error("#6.2: new Date(date_2000_start) === undefined"); -} +assert.notSameValue( + new Date(date_2000_start), + undefined, + 'new Date(date_2000_start) is expected to not equal ``undefined``' +); var x63 = new Date(date_2000_start); -if (typeof x63 !== "object") { - throw new Test262Error("#6.3: typeof new Date(date_2000_start) !== 'object'"); -} +assert.sameValue(typeof x63, "object", 'The value of `typeof x63` is expected to be "object"'); var x64 = new Date(date_2000_start); -if (x64 === undefined) { - throw new Test262Error("#6.4: new Date(date_2000_start) !== undefined"); -} +assert.notSameValue(x64, undefined, 'The value of x64 is expected to not equal ``undefined``'); -if (typeof new Date(date_2099_end) !== "object") { - throw new Test262Error("#7.1: typeof new Date(date_2099_end) === 'object'"); -} +assert.sameValue( + typeof new Date(date_2099_end), + "object", + 'The value of `typeof new Date(date_2099_end)` is expected to be "object"' +); -if (new Date(date_2099_end) === undefined) { - throw new Test262Error("#7.2: new Date(date_2099_end) === undefined"); -} +assert.notSameValue(new Date(date_2099_end), undefined, 'new Date(date_2099_end) is expected to not equal ``undefined``'); var x73 = new Date(date_2099_end); -if (typeof x73 !== "object") { - throw new Test262Error("#7.3: typeof new Date(date_2099_end) !== 'object'"); -} +assert.sameValue(typeof x73, "object", 'The value of `typeof x73` is expected to be "object"'); var x74 = new Date(date_2099_end); -if (x74 === undefined) { - throw new Test262Error("#7.4: new Date(date_2099_end) !== undefined"); -} +assert.notSameValue(x74, undefined, 'The value of x74 is expected to not equal ``undefined``'); -if (typeof new Date(date_2100_start) !== "object") { - throw new Test262Error("#8.1: typeof new Date(date_2100_start) === 'object'"); -} +assert.sameValue( + typeof new Date(date_2100_start), + "object", + 'The value of `typeof new Date(date_2100_start)` is expected to be "object"' +); -if (new Date(date_2100_start) === undefined) { - throw new Test262Error("#8.2: new Date(date_2100_start) === undefined"); -} +assert.notSameValue( + new Date(date_2100_start), + undefined, + 'new Date(date_2100_start) is expected to not equal ``undefined``' +); var x83 = new Date(date_2100_start); -if (typeof x83 !== "object") { - throw new Test262Error("#8.3: typeof new Date(date_2100_start) !== 'object'"); -} +assert.sameValue(typeof x83, "object", 'The value of `typeof x83` is expected to be "object"'); var x84 = new Date(date_2100_start); -if (x84 === undefined) { - throw new Test262Error("#8.4: new Date(date_2100_start) !== undefined"); -} +assert.notSameValue(x84, undefined, 'The value of x84 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.2_A2_T1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.2_A2_T1.js index 381be5e30b6b..6ec8fb0ff0d4 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.2_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.2_A2_T1.js @@ -12,123 +12,155 @@ includes: [dateConstants.js] ---*/ var x11 = new Date(date_1899_end); -if (typeof x11.constructor.prototype !== "object") { - throw new Test262Error("#1.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x11.constructor.prototype, + "object", + 'The value of `typeof x11.constructor.prototype` is expected to be "object"' +); var x12 = new Date(date_1899_end); -if (!Date.prototype.isPrototypeOf(x12)) { - throw new Test262Error('#1.2: Date.prototype.isPrototypeOf(x12)'); -} +assert(Date.prototype.isPrototypeOf(x12), 'Date.prototype.isPrototypeOf(x12) must return true'); var x13 = new Date(date_1899_end); -if (Date.prototype !== x13.constructor.prototype) { - throw new Test262Error("#1.3: Date.prototype !== x13.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x13.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x13.constructor.prototype' +); var x21 = new Date(date_1900_start); -if (typeof x21.constructor.prototype !== "object") { - throw new Test262Error("#2.1: typeof x21.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x21.constructor.prototype, + "object", + 'The value of `typeof x21.constructor.prototype` is expected to be "object"' +); var x22 = new Date(date_1900_start); -if (!Date.prototype.isPrototypeOf(x22)) { - throw new Test262Error('#2.2: Date.prototype.isPrototypeOf(x22)'); -} +assert(Date.prototype.isPrototypeOf(x22), 'Date.prototype.isPrototypeOf(x22) must return true'); var x23 = new Date(date_1900_start); -if (Date.prototype !== x23.constructor.prototype) { - throw new Test262Error("#2.3: Date.prototype !== x23.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x23.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x23.constructor.prototype' +); var x31 = new Date(date_1969_end); -if (typeof x31.constructor.prototype !== "object") { - throw new Test262Error("#3.1: typeof x31.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x31.constructor.prototype, + "object", + 'The value of `typeof x31.constructor.prototype` is expected to be "object"' +); var x32 = new Date(date_1969_end); -if (!Date.prototype.isPrototypeOf(x32)) { - throw new Test262Error('#3.2: Date.prototype.isPrototypeOf(x32)'); -} +assert(Date.prototype.isPrototypeOf(x32), 'Date.prototype.isPrototypeOf(x32) must return true'); var x33 = new Date(date_1969_end); -if (Date.prototype !== x33.constructor.prototype) { - throw new Test262Error("#3.3: Date.prototype !== x33.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x33.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x33.constructor.prototype' +); var x41 = new Date(date_1970_start); -if (typeof x41.constructor.prototype !== "object") { - throw new Test262Error("#4.1: typeof x11.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x41.constructor.prototype, + "object", + 'The value of `typeof x41.constructor.prototype` is expected to be "object"' +); var x42 = new Date(date_1970_start); -if (!Date.prototype.isPrototypeOf(x42)) { - throw new Test262Error('#4.2: Date.prototype.isPrototypeOf(x42)'); -} +assert(Date.prototype.isPrototypeOf(x42), 'Date.prototype.isPrototypeOf(x42) must return true'); var x43 = new Date(date_1970_start); -if (Date.prototype !== x43.constructor.prototype) { - throw new Test262Error("#4.3: Date.prototype !== x43.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x43.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x43.constructor.prototype' +); var x51 = new Date(date_1999_end); -if (typeof x51.constructor.prototype !== "object") { - throw new Test262Error("#5.1: typeof x51.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x51.constructor.prototype, + "object", + 'The value of `typeof x51.constructor.prototype` is expected to be "object"' +); var x52 = new Date(date_1999_end); -if (!Date.prototype.isPrototypeOf(x52)) { - throw new Test262Error('#5.2: Date.prototype.isPrototypeOf(x52)'); -} +assert(Date.prototype.isPrototypeOf(x52), 'Date.prototype.isPrototypeOf(x52) must return true'); var x53 = new Date(date_1999_end); -if (Date.prototype !== x53.constructor.prototype) { - throw new Test262Error("#5.3: Date.prototype !== x53.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x53.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x53.constructor.prototype' +); var x61 = new Date(date_2000_start); -if (typeof x61.constructor.prototype !== "object") { - throw new Test262Error("#6.1: typeof x61.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x61.constructor.prototype, + "object", + 'The value of `typeof x61.constructor.prototype` is expected to be "object"' +); var x62 = new Date(date_2000_start); -if (!Date.prototype.isPrototypeOf(x62)) { - throw new Test262Error('#6.2: Date.prototype.isPrototypeOf(x62)'); -} +assert(Date.prototype.isPrototypeOf(x62), 'Date.prototype.isPrototypeOf(x62) must return true'); var x63 = new Date(date_2000_start); -if (Date.prototype !== x63.constructor.prototype) { - throw new Test262Error("#6.3: Date.prototype !== x63.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x63.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x63.constructor.prototype' +); var x71 = new Date(date_2099_end); -if (typeof x71.constructor.prototype !== "object") { - throw new Test262Error("#7.1: typeof x71.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x71.constructor.prototype, + "object", + 'The value of `typeof x71.constructor.prototype` is expected to be "object"' +); var x72 = new Date(date_2099_end); -if (!Date.prototype.isPrototypeOf(x72)) { - throw new Test262Error('#7.2: Date.prototype.isPrototypeOf(x72)'); -} +assert(Date.prototype.isPrototypeOf(x72), 'Date.prototype.isPrototypeOf(x72) must return true'); var x73 = new Date(date_2099_end); -if (Date.prototype !== x73.constructor.prototype) { - throw new Test262Error("#7.3: Date.prototype !== x73.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x73.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x73.constructor.prototype' +); var x81 = new Date(date_2100_start); -if (typeof x81.constructor.prototype !== "object") { - throw new Test262Error("#8.1: typeof x81.constructor.prototype === 'object'"); -} + +assert.sameValue( + typeof x81.constructor.prototype, + "object", + 'The value of `typeof x81.constructor.prototype` is expected to be "object"' +); var x82 = new Date(date_2100_start); -if (!Date.prototype.isPrototypeOf(x82)) { - throw new Test262Error('#8.2: Date.prototype.isPrototypeOf(x82)'); -} +assert(Date.prototype.isPrototypeOf(x82), 'Date.prototype.isPrototypeOf(x82) must return true'); var x83 = new Date(date_2100_start); -if (Date.prototype !== x83.constructor.prototype) { - throw new Test262Error("#8.3: Date.prototype !== x83.constructor.prototype"); -} + +assert.sameValue( + Date.prototype, + x83.constructor.prototype, + 'The value of Date.prototype is expected to equal the value of x83.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.2_A3_T1.1.js b/js/src/tests/test262/built-ins/Date/S15.9.3.2_A3_T1.1.js index 9dc59a4db762..3e52511561bc 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.2_A3_T1.1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.2_A3_T1.1.js @@ -11,43 +11,67 @@ includes: [dateConstants.js] ---*/ var x1 = new Date(date_1899_end); -if (Object.prototype.toString.call(x1) !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x1), + "[object Date]", + 'Object.prototype.toString.call(new Date(date_1899_end)) must return "[object Date]"' +); var x2 = new Date(date_1900_start); -if (Object.prototype.toString.call(x2) !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x2), + "[object Date]", + 'Object.prototype.toString.call(new Date(date_1900_start)) must return "[object Date]"' +); var x3 = new Date(date_1969_end); -if (Object.prototype.toString.call(x3) !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x3), + "[object Date]", + 'Object.prototype.toString.call(new Date(date_1969_end)) must return "[object Date]"' +); var x4 = new Date(date_1970_start); -if (Object.prototype.toString.call(x4) !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x4), + "[object Date]", + 'Object.prototype.toString.call(new Date(date_1970_start)) must return "[object Date]"' +); var x5 = new Date(date_1999_end); -if (Object.prototype.toString.call(x5) !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x5), + "[object Date]", + 'Object.prototype.toString.call(new Date(date_1999_end)) must return "[object Date]"' +); var x6 = new Date(date_2000_start); -if (Object.prototype.toString.call(x6) !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x6), + "[object Date]", + 'Object.prototype.toString.call(new Date(date_2000_start)) must return "[object Date]"' +); var x7 = new Date(date_2099_end); -if (Object.prototype.toString.call(x7) !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x7), + "[object Date]", + 'Object.prototype.toString.call(new Date(date_2099_end)) must return "[object Date]"' +); var x8 = new Date(date_2100_start); -if (Object.prototype.toString.call(x8) !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} + +assert.sameValue( + Object.prototype.toString.call(x8), + "[object Date]", + 'Object.prototype.toString.call(new Date(date_2100_start)) must return "[object Date]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.3.2_A3_T1.2.js b/js/src/tests/test262/built-ins/Date/S15.9.3.2_A3_T1.2.js index a0d831e95c8b..78f451277a0e 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.3.2_A3_T1.2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.3.2_A3_T1.2.js @@ -13,43 +13,27 @@ includes: [dateConstants.js] Date.prototype.toString = Object.prototype.toString; var x1 = new Date(date_1899_end); -if (x1.toString() !== "[object Date]") { - throw new Test262Error("#1: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x1.toString(), "[object Date]", 'x1.toString() must return "[object Date]"'); var x2 = new Date(date_1900_start); -if (x2.toString() !== "[object Date]") { - throw new Test262Error("#2: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x2.toString(), "[object Date]", 'x2.toString() must return "[object Date]"'); var x3 = new Date(date_1969_end); -if (x3.toString() !== "[object Date]") { - throw new Test262Error("#3: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x3.toString(), "[object Date]", 'x3.toString() must return "[object Date]"'); var x4 = new Date(date_1970_start); -if (x4.toString() !== "[object Date]") { - throw new Test262Error("#4: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x4.toString(), "[object Date]", 'x4.toString() must return "[object Date]"'); var x5 = new Date(date_1999_end); -if (x5.toString() !== "[object Date]") { - throw new Test262Error("#5: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x5.toString(), "[object Date]", 'x5.toString() must return "[object Date]"'); var x6 = new Date(date_2000_start); -if (x6.toString() !== "[object Date]") { - throw new Test262Error("#6: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x6.toString(), "[object Date]", 'x6.toString() must return "[object Date]"'); var x7 = new Date(date_2099_end); -if (x7.toString() !== "[object Date]") { - throw new Test262Error("#7: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x7.toString(), "[object Date]", 'x7.toString() must return "[object Date]"'); var x8 = new Date(date_2100_start); -if (x8.toString() !== "[object Date]") { - throw new Test262Error("#8: The [[Class]] property of the newly constructed object is set to 'Date'"); -} +assert.sameValue(x8.toString(), "[object Date]", 'x8.toString() must return "[object Date]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.4_A1.js b/js/src/tests/test262/built-ins/Date/S15.9.4_A1.js index 17c10fce7ca4..cc810add6223 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.4_A1.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.4_A1.js @@ -6,9 +6,6 @@ info: The Date constructor has the property "prototype" esid: sec-date-constructor description: Checking existence of the property "prototype" ---*/ - -if (!Date.hasOwnProperty("prototype")) { - throw new Test262Error('#1: The Date constructor has the property "prototype"'); -} +assert(Date.hasOwnProperty("prototype"), 'Date.hasOwnProperty("prototype") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.4_A2.js b/js/src/tests/test262/built-ins/Date/S15.9.4_A2.js index f751a681f615..efa6e9386333 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.4_A2.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.4_A2.js @@ -6,9 +6,6 @@ info: The Date constructor has the property "parse" esid: sec-date-constructor description: Checking existence of the property "parse" ---*/ - -if (!Date.hasOwnProperty("parse")) { - throw new Test262Error('#1: The Date constructor has the property "parse"'); -} +assert(Date.hasOwnProperty("parse"), 'Date.hasOwnProperty("parse") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.4_A3.js b/js/src/tests/test262/built-ins/Date/S15.9.4_A3.js index 5565f65d4186..381b4d16dc16 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.4_A3.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.4_A3.js @@ -6,9 +6,6 @@ info: The Date constructor has the property "UTC" esid: sec-date-constructor description: Checking existence of the property "UTC" ---*/ - -if (!Date.hasOwnProperty("UTC")) { - throw new Test262Error('#1: The Date constructor has the property "UTC"'); -} +assert(Date.hasOwnProperty("UTC"), 'Date.hasOwnProperty("UTC") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.4_A4.js b/js/src/tests/test262/built-ins/Date/S15.9.4_A4.js index 3acf8f94a3a8..2d7445628ccc 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.4_A4.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.4_A4.js @@ -8,10 +8,6 @@ info: | esid: sec-date-constructor description: Checking Function.prototype.isPrototypeOf(Date) ---*/ - -//CHECK#1 -if (!(Function.prototype.isPrototypeOf(Date))) { - throw new Test262Error('#1: the value of the internal [[Prototype]] property of the Date constructor is the Function prototype object.'); -} +assert(Function.prototype.isPrototypeOf(Date), 'Function.prototype.isPrototypeOf(Date) must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/S15.9.4_A5.js b/js/src/tests/test262/built-ins/Date/S15.9.4_A5.js index dbe1d2f03ae4..6e5619ad58d3 100644 --- a/js/src/tests/test262/built-ins/Date/S15.9.4_A5.js +++ b/js/src/tests/test262/built-ins/Date/S15.9.4_A5.js @@ -6,15 +6,7 @@ info: Date constructor has length property whose value is 7 esid: sec-date-constructor description: Checking Date.length property ---*/ - -//CHECK#1 -if (!Date.hasOwnProperty("length")) { - throw new Test262Error('#1: Date constructor has length property'); -} - -//CHECK#2 -if (Date.length !== 7) { - throw new Test262Error('#2: Date constructor length property value should be 7'); -} +assert(Date.hasOwnProperty("length"), 'Date.hasOwnProperty("length") must return true'); +assert.sameValue(Date.length, 7, 'The value of Date.length is expected to be 7'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T1.js b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T1.js index 3a85396cf946..5f2531e1c23c 100644 --- a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T1.js @@ -9,12 +9,13 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.UTC; -if (x === 1) +if (x === 1) { Date.UTC = 2; -else +} else { Date.UTC = 1; -if (Date.UTC === x) { - throw new Test262Error('#1: The Date.UTC has not the attribute ReadOnly'); } +assert.notSameValue(Date.UTC, x, 'The value of Date.UTC is expected to not equal the value of `x`'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T2.js b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T2.js index 70293f54c9c8..f859e0b452fd 100644 --- a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T2.js @@ -7,13 +7,9 @@ info: The Date property "UTC" has { DontEnum } attributes es5id: 15.9.4.3_A1_T2 description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.UTC, false, 'The value of delete Date.UTC is not false'); +assert(!Date.hasOwnProperty('UTC'), 'The value of !Date.hasOwnProperty(\'UTC\') is expected to be true'); -if (delete Date.UTC === false) { - throw new Test262Error('#1: The Date.UTC property has not the attributes DontDelete'); -} - -if (Date.hasOwnProperty('UTC')) { - throw new Test262Error('#2: The Date.UTC property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T3.js b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T3.js index 455e51f51302..43b8ccb055c1 100644 --- a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A1_T3.js @@ -7,15 +7,15 @@ info: The Date property "UTC" has { DontEnum } attributes es5id: 15.9.4.3_A1_T3 description: Checking DontEnum attribute ---*/ - -if (Date.propertyIsEnumerable('UTC')) { - throw new Test262Error('#1: The Date.UTC property has the attribute DontEnum'); -} +assert( + !Date.propertyIsEnumerable('UTC'), + 'The value of !Date.propertyIsEnumerable(\'UTC\') is expected to be true' +); for (var x in Date) { - if (x === "UTC") { - throw new Test262Error('#2: The Date.UTC has the attribute DontEnum'); - } + assert.notSameValue(x, "UTC", 'The value of x is not "UTC"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A2_T1.js b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A2_T1.js index 6371a686d0b9..49e39e4d11da 100644 --- a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A2_T1.js @@ -7,13 +7,7 @@ info: The "length" property of the "UTC" is 7 es5id: 15.9.4.3_A2_T1 description: The "length" property of the "UTC" is 7 ---*/ - -if (Date.UTC.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The UTC has a "length" property'); -} - -if (Date.UTC.length !== 7) { - throw new Test262Error('#2: The "length" property of the UTC is 7'); -} +assert.sameValue(Date.UTC.hasOwnProperty("length"), true, 'Date.UTC.hasOwnProperty("length") must return true'); +assert.sameValue(Date.UTC.length, 7, 'The value of Date.UTC.length is expected to be 7'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T1.js b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T1.js index 2ec0ae7b9922..c9261a5a5b52 100644 --- a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T1.js @@ -13,8 +13,8 @@ includes: [propertyHelper.js] var x = Date.UTC.length; verifyNotWritable(Date.UTC, "length", null, 1); -if (Date.UTC.length !== x) { - throw new Test262Error('#1: The Date.UTC.length has the attribute ReadOnly'); -} +assert.sameValue(Date.UTC.length, x, 'The value of Date.UTC.length is expected to equal the value of x'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T2.js b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T2.js index 291254ebda11..07ecc37b20b5 100644 --- a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T2.js @@ -10,12 +10,13 @@ es5id: 15.9.4.3_A3_T2 description: Checking DontDelete attribute ---*/ -if (delete Date.UTC.length !== true) { - throw new Test262Error('#1: The Date.UTC.length property does not have the attributes DontDelete'); -} +assert.sameValue(delete Date.UTC.length, true, 'The value of `delete Date.UTC.length` is expected to be true'); -if (Date.UTC.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.UTC.length property does not have the attributes DontDelete'); -} +assert( + !Date.UTC.hasOwnProperty('length'), + 'The value of !Date.UTC.hasOwnProperty(\'length\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T3.js b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T3.js index 06ce7abe4c16..f5d155d8a525 100644 --- a/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/UTC/S15.9.4.3_A3_T3.js @@ -9,15 +9,15 @@ info: | es5id: 15.9.4.3_A3_T3 description: Checking DontEnum attribute ---*/ - -if (Date.UTC.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.UTC.length property has the attribute DontEnum'); -} +assert( + !Date.UTC.propertyIsEnumerable('length'), + 'The value of !Date.UTC.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.UTC) { - if (x === "length") { - throw new Test262Error('#2: The Date.UTC.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T1.js b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T1.js index f1bbce628720..3409d2dfffdb 100644 --- a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T1.js @@ -8,12 +8,13 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.parse; -if (x === 1) +if (x === 1) { Date.parse = 2; -else +} else { Date.parse = 1; -if (Date.parse === x) { - throw new Test262Error('#1: The Date.parse has not the attribute ReadOnly'); } +assert.notSameValue(Date.parse, x, 'The value of Date.parse is expected to not equal the value of `x`'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T2.js b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T2.js index 8f68e4b1bbcf..c0991c97d420 100644 --- a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T2.js @@ -6,13 +6,9 @@ info: The Date property "parse" has { DontEnum } attributes esid: sec-date.parse description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.parse, false, 'The value of delete Date.parse is not false'); +assert(!Date.hasOwnProperty('parse'), 'The value of !Date.hasOwnProperty(\'parse\') is expected to be true'); -if (delete Date.parse === false) { - throw new Test262Error('#1: The Date.parse property has not the attributes DontDelete'); -} - -if (Date.hasOwnProperty('parse')) { - throw new Test262Error('#2: The Date.parse property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T3.js b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T3.js index 61bb288221fd..e5f252313750 100644 --- a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A1_T3.js @@ -6,15 +6,15 @@ info: The Date property "parse" has { DontEnum } attributes esid: sec-date.parse description: Checking DontEnum attribute ---*/ - -if (Date.propertyIsEnumerable('parse')) { - throw new Test262Error('#1: The Date.parse property has the attribute DontEnum'); -} +assert( + !Date.propertyIsEnumerable('parse'), + 'The value of !Date.propertyIsEnumerable(\'parse\') is expected to be true' +); for (var x in Date) { - if (x === "parse") { - throw new Test262Error('#2: The Date.parse has the attribute DontEnum'); - } + assert.notSameValue(x, "parse", 'The value of x is not "parse"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A2_T1.js b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A2_T1.js index b6aa2aeb6fec..d066cbbd07b0 100644 --- a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A2_T1.js @@ -6,13 +6,7 @@ info: The "length" property of the "parse" is 1 esid: sec-date.parse description: The "length" property of the "parse" is 1 ---*/ - -if (Date.parse.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The parse has a "length" property'); -} - -if (Date.parse.length !== 1) { - throw new Test262Error('#2: The "length" property of the parse is 1'); -} +assert.sameValue(Date.parse.hasOwnProperty("length"), true, 'Date.parse.hasOwnProperty("length") must return true'); +assert.sameValue(Date.parse.length, 1, 'The value of Date.parse.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T1.js b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T1.js index 455e5d9b844f..0c0929164c52 100644 --- a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T1.js @@ -12,8 +12,8 @@ includes: [propertyHelper.js] var x = Date.parse.length; verifyNotWritable(Date.parse, "length", null, 1); -if (Date.parse.length !== x) { - throw new Test262Error('#1: The Date.parse.length has the attribute ReadOnly'); -} +assert.sameValue(Date.parse.length, x, 'The value of Date.parse.length is expected to equal the value of x'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T2.js b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T2.js index 408027a63c91..f224b1fbc297 100644 --- a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T2.js @@ -8,13 +8,13 @@ info: | esid: sec-date.parse description: Checking DontDelete attribute ---*/ +assert.sameValue(delete Date.parse.length, true, 'The value of `delete Date.parse.length` is expected to be true'); -if (delete Date.parse.length !== true) { - throw new Test262Error('#1: The Date.parse.length property does not have the attributes DontDelete'); -} +assert( + !Date.parse.hasOwnProperty('length'), + 'The value of !Date.parse.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.parse.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.parse.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T3.js b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T3.js index 4126253b05f4..4c7735de225f 100644 --- a/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/parse/S15.9.4.2_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.parse description: Checking DontEnum attribute ---*/ - -if (Date.parse.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.parse.length property has the attribute DontEnum'); -} +assert( + !Date.parse.propertyIsEnumerable('length'), + 'The value of !Date.parse.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.parse) { - if (x === "length") { - throw new Test262Error('#2: The Date.parse.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T1.js index b9c766bfce0e..20b8f72b642b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T1.js @@ -12,8 +12,8 @@ includes: [propertyHelper.js] var x = Date.prototype; verifyNotWritable(Date, "prototype", null, 1); -if (Date.prototype !== x) { - throw new Test262Error('#1: The Date.prototype has the attribute ReadOnly'); -} +assert.sameValue(Date.prototype, x, 'The value of Date.prototype is expected to equal the value of x'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T2.js index 5fb31366ae72..8696fba7d68f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T2.js @@ -13,11 +13,11 @@ includes: [propertyHelper.js] verifyNotConfigurable(Date, "prototype"); try { - if (delete Date.prototype !== false) { - throw new Test262Error('#1: The Date.prototype property has the attributes DontDelete'); - } + assert.sameValue(delete Date.prototype, false); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } assert(e instanceof TypeError); } @@ -25,4 +25,6 @@ if (!Date.hasOwnProperty('prototype')) { throw new Test262Error('#2: The Date.prototype property has the attributes DontDelete'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T3.js index 268f3a210508..183ac600b4df 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.4.1_A1_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype description: Checking DontEnum attribute ---*/ - -if (Date.propertyIsEnumerable('prototype')) { - throw new Test262Error('#1: The Date.prototype property has the attribute DontEnum'); -} +assert( + !Date.propertyIsEnumerable('prototype'), + 'The value of !Date.propertyIsEnumerable(\'prototype\') is expected to be true' +); for (var x in Date) { - if (x === "prototype") { - throw new Test262Error('#2: The Date.prototype has the attribute DontEnum'); - } + assert.notSameValue(x, "prototype", 'The value of x is not "prototype"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A01_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A01_T1.js index 9d35d80c52a8..af08da626137 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A01_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A01_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "constructor" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "constructor" ---*/ - -if (Date.prototype.hasOwnProperty("constructor") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "constructor"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("constructor"), + true, + 'Date.prototype.hasOwnProperty("constructor") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A02_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A02_T1.js index 313eaec779be..e6ea7e46e3c7 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A02_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A02_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "toString" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "toString" ---*/ - -if (Date.prototype.hasOwnProperty("toString") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "toString"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("toString"), + true, + 'Date.prototype.hasOwnProperty("toString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A03_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A03_T1.js index 3cec1d631bc8..cefff137370d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A03_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A03_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "toDateString" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "toDateString" ---*/ - -if (Date.prototype.hasOwnProperty("toDateString") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "toDateString"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("toDateString"), + true, + 'Date.prototype.hasOwnProperty("toDateString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A04_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A04_T1.js index d3077537a0fe..49029ad9e6b2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A04_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A04_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "toTimeString" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "toTimeString" ---*/ - -if (Date.prototype.hasOwnProperty("toTimeString") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "toTimeString"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("toTimeString"), + true, + 'Date.prototype.hasOwnProperty("toTimeString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A05_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A05_T1.js index aba1a93dfd51..2085801083f2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A05_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A05_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "toLocaleString" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "toLocaleString" ---*/ - -if (Date.prototype.hasOwnProperty("toLocaleString") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "toLocaleString"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("toLocaleString"), + true, + 'Date.prototype.hasOwnProperty("toLocaleString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A06_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A06_T1.js index a9469dc2e5ae..8717c97ea0da 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A06_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A06_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "toLocaleDateString" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "toLocaleDateString" ---*/ - -if (Date.prototype.hasOwnProperty("toLocaleDateString") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "toLocaleDateString"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("toLocaleDateString"), + true, + 'Date.prototype.hasOwnProperty("toLocaleDateString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A07_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A07_T1.js index e76955a485f7..551e01e16b67 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A07_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A07_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "toLocaleTimeString" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "toLocaleTimeString" ---*/ - -if (Date.prototype.hasOwnProperty("toLocaleTimeString") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "toLocaleTimeString"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("toLocaleTimeString"), + true, + 'Date.prototype.hasOwnProperty("toLocaleTimeString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A08_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A08_T1.js index 093e0f9fb422..cb063000336b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A08_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A08_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "valueOf" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "valueOf" ---*/ - -if (Date.prototype.hasOwnProperty("valueOf") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "valueOf"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("valueOf"), + true, + 'Date.prototype.hasOwnProperty("valueOf") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A09_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A09_T1.js index bc2077674465..9e5f93709500 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A09_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A09_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getTime" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getTime" ---*/ - -if (Date.prototype.hasOwnProperty("getTime") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getTime"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getTime"), + true, + 'Date.prototype.hasOwnProperty("getTime") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A10_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A10_T1.js index 8a36035f8818..aab91858d3eb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A10_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A10_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getFullYear" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getFullYear" ---*/ - -if (Date.prototype.hasOwnProperty("getFullYear") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getFullYear"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getFullYear"), + true, + 'Date.prototype.hasOwnProperty("getFullYear") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A11_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A11_T1.js index 29fde58b5d83..163b509df8f4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A11_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A11_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getUTCFullYear" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getUTCFullYear" ---*/ - -if (Date.prototype.hasOwnProperty("getUTCFullYear") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getUTCFullYear"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getUTCFullYear"), + true, + 'Date.prototype.hasOwnProperty("getUTCFullYear") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A12_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A12_T1.js index c979240b0b7f..20bd6222e108 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A12_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A12_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getMonth" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getMonth" ---*/ - -if (Date.prototype.hasOwnProperty("getMonth") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getMonth"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getMonth"), + true, + 'Date.prototype.hasOwnProperty("getMonth") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A13_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A13_T1.js index dd09bd79cc52..4eb17696993b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A13_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A13_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getUTCMonth" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getUTCMonth" ---*/ - -if (Date.prototype.hasOwnProperty("getUTCMonth") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getUTCMonth"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getUTCMonth"), + true, + 'Date.prototype.hasOwnProperty("getUTCMonth") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A14_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A14_T1.js index 9e27b35b1348..3bb94bbc7135 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A14_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A14_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getDate" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getDate" ---*/ - -if (Date.prototype.hasOwnProperty("getDate") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getDate"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getDate"), + true, + 'Date.prototype.hasOwnProperty("getDate") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A15_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A15_T1.js index d1a8fc50bb84..3a4e4c2adc9b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A15_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A15_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getUTCDate" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getUTCDate" ---*/ - -if (Date.prototype.hasOwnProperty("getUTCDate") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getUTCDate"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getUTCDate"), + true, + 'Date.prototype.hasOwnProperty("getUTCDate") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A16_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A16_T1.js index 2e7713bc5670..7f9de5c682a8 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A16_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A16_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getDay" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getDay" ---*/ - -if (Date.prototype.hasOwnProperty("getDay") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getDay"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getDay"), + true, + 'Date.prototype.hasOwnProperty("getDay") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A17_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A17_T1.js index ff8fdf7277df..e1ddb8d672d9 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A17_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A17_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getUTCDay" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getUTCDay" ---*/ - -if (Date.prototype.hasOwnProperty("getUTCDay") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getUTCDay"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getUTCDay"), + true, + 'Date.prototype.hasOwnProperty("getUTCDay") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A18_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A18_T1.js index 7566e7c2c3b7..be23a2dd3634 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A18_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A18_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getHours" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getHours" ---*/ - -if (Date.prototype.hasOwnProperty("getHours") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getHours"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getHours"), + true, + 'Date.prototype.hasOwnProperty("getHours") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A19_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A19_T1.js index 7ed29df92b7f..27d9c68a18fc 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A19_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A19_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getUTCHours" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getUTCHours" ---*/ - -if (Date.prototype.hasOwnProperty("getUTCHours") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getUTCHours"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getUTCHours"), + true, + 'Date.prototype.hasOwnProperty("getUTCHours") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A20_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A20_T1.js index e30424786abf..43a9ac8f1ceb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A20_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A20_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getMinutes" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getMinutes" ---*/ - -if (Date.prototype.hasOwnProperty("getMinutes") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getMinutes"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getMinutes"), + true, + 'Date.prototype.hasOwnProperty("getMinutes") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A21_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A21_T1.js index 0c7ed301cc8e..eeee6d1b0e40 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A21_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A21_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getUTCMinutes" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getUTCMinutes" ---*/ - -if (Date.prototype.hasOwnProperty("getUTCMinutes") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getUTCMinutes"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getUTCMinutes"), + true, + 'Date.prototype.hasOwnProperty("getUTCMinutes") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A22_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A22_T1.js index 5b04eceb4ae5..433e6f9cceea 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A22_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A22_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getSeconds" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getSeconds" ---*/ - -if (Date.prototype.hasOwnProperty("getSeconds") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getSeconds"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getSeconds"), + true, + 'Date.prototype.hasOwnProperty("getSeconds") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A23_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A23_T1.js index 4ebafc88bd38..c8810bc29800 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A23_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A23_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getUTCSeconds" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getUTCSeconds" ---*/ - -if (Date.prototype.hasOwnProperty("getUTCSeconds") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getUTCSeconds"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getUTCSeconds"), + true, + 'Date.prototype.hasOwnProperty("getUTCSeconds") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A24_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A24_T1.js index 66301efa586a..c11983d1d7cb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A24_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A24_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getMilliseconds" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getMilliseconds" ---*/ - -if (Date.prototype.hasOwnProperty("getMilliseconds") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getMilliseconds"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getMilliseconds"), + true, + 'Date.prototype.hasOwnProperty("getMilliseconds") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A25_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A25_T1.js index 328e3b3a7ad6..10aa185fd5cd 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A25_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A25_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getUTCMilliseconds" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getUTCMilliseconds" ---*/ - -if (Date.prototype.hasOwnProperty("getUTCMilliseconds") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getUTCMilliseconds"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getUTCMilliseconds"), + true, + 'Date.prototype.hasOwnProperty("getUTCMilliseconds") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A26_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A26_T1.js index 75b377c0144a..a7ff1e0f9815 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A26_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A26_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "getTimezoneOffset" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "getTimezoneOffset" ---*/ - -if (Date.prototype.hasOwnProperty("getTimezoneOffset") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "getTimezoneOffset"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("getTimezoneOffset"), + true, + 'Date.prototype.hasOwnProperty("getTimezoneOffset") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A27_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A27_T1.js index d04a7071239b..2178c458a3e0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A27_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A27_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setTime" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setTime" ---*/ - -if (Date.prototype.hasOwnProperty("setTime") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setTime"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setTime"), + true, + 'Date.prototype.hasOwnProperty("setTime") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A28_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A28_T1.js index 73e5df147861..9d17f88883ad 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A28_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A28_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setMilliseconds" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setMilliseconds" ---*/ - -if (Date.prototype.hasOwnProperty("setMilliseconds") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setMilliseconds"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setMilliseconds"), + true, + 'Date.prototype.hasOwnProperty("setMilliseconds") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A29_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A29_T1.js index 4c9bc426b079..22c323c2493c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A29_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A29_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setUTCMilliseconds" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setUTCMilliseconds" ---*/ - -if (Date.prototype.hasOwnProperty("setUTCMilliseconds") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setUTCMilliseconds"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setUTCMilliseconds"), + true, + 'Date.prototype.hasOwnProperty("setUTCMilliseconds") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A30_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A30_T1.js index ef791ff8c0b0..5d1de66b74d5 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A30_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A30_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setSeconds" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setSeconds" ---*/ - -if (Date.prototype.hasOwnProperty("setSeconds") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setSeconds"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setSeconds"), + true, + 'Date.prototype.hasOwnProperty("setSeconds") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A31_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A31_T1.js index 5c5618d03e67..aab6a583cf60 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A31_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A31_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setUTCSeconds" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setUTCSeconds" ---*/ - -if (Date.prototype.hasOwnProperty("setUTCSeconds") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setUTCSeconds"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setUTCSeconds"), + true, + 'Date.prototype.hasOwnProperty("setUTCSeconds") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A32_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A32_T1.js index 975535c79913..9ab447571d1f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A32_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A32_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setMinutes" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setMinutes" ---*/ - -if (Date.prototype.hasOwnProperty("setMinutes") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setMinutes"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setMinutes"), + true, + 'Date.prototype.hasOwnProperty("setMinutes") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A33_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A33_T1.js index 7de446cd5bfb..6730e51d0937 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A33_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A33_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setUTCMinutes" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setUTCMinutes" ---*/ - -if (Date.prototype.hasOwnProperty("setUTCMinutes") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setUTCMinutes"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setUTCMinutes"), + true, + 'Date.prototype.hasOwnProperty("setUTCMinutes") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A34_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A34_T1.js index 83c5e9a6ec49..5c87f3aa6736 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A34_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A34_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setHours" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setHours" ---*/ - -if (Date.prototype.hasOwnProperty("setHours") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setHours"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setHours"), + true, + 'Date.prototype.hasOwnProperty("setHours") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A35_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A35_T1.js index ef196dd48761..b190a8049183 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A35_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A35_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setUTCHours" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setUTCHours" ---*/ - -if (Date.prototype.hasOwnProperty("setUTCHours") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setUTCHours"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setUTCHours"), + true, + 'Date.prototype.hasOwnProperty("setUTCHours") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A36_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A36_T1.js index 92dddf3b38fc..5ace73d7d0d2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A36_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A36_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setDate" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setDate" ---*/ - -if (Date.prototype.hasOwnProperty("setDate") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setDate"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setDate"), + true, + 'Date.prototype.hasOwnProperty("setDate") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A37_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A37_T1.js index 51fa1ed30b3b..5185a5bf4679 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A37_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A37_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setUTCDate" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setUTCDate" ---*/ - -if (Date.prototype.hasOwnProperty("setUTCDate") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setUTCDate"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setUTCDate"), + true, + 'Date.prototype.hasOwnProperty("setUTCDate") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A38_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A38_T1.js index 1dbd4da499f4..2adb512ccf03 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A38_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A38_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setMonth" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setMonth" ---*/ - -if (Date.prototype.hasOwnProperty("setMonth") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setMonth"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setMonth"), + true, + 'Date.prototype.hasOwnProperty("setMonth") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A39_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A39_T1.js index d8a47907557b..f2d7f80bc3d4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A39_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A39_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setUTCMonth" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setUTCMonth" ---*/ - -if (Date.prototype.hasOwnProperty("setUTCMonth") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setUTCMonth"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setUTCMonth"), + true, + 'Date.prototype.hasOwnProperty("setUTCMonth") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A40_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A40_T1.js index bc1607f4bcc2..d449d232aee3 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A40_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A40_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setFullYear" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setFullYear" ---*/ - -if (Date.prototype.hasOwnProperty("setFullYear") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setFullYear"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setFullYear"), + true, + 'Date.prototype.hasOwnProperty("setFullYear") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A41_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A41_T1.js index b3a6c2bd8144..d2178a8f2f05 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A41_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A41_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "setUTCFullYear" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "setUTCFullYear" ---*/ - -if (Date.prototype.hasOwnProperty("setUTCFullYear") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "setUTCFullYear"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("setUTCFullYear"), + true, + 'Date.prototype.hasOwnProperty("setUTCFullYear") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A42_T1.js b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A42_T1.js index 72fce11f03f1..498c326b71f0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A42_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/S15.9.5_A42_T1.js @@ -6,9 +6,10 @@ info: The Date.prototype has the property "toUTCString" esid: sec-properties-of-the-date-prototype-object description: The Date.prototype has the property "toUTCString" ---*/ - -if (Date.prototype.hasOwnProperty("toUTCString") !== true) { - throw new Test262Error('#1: The Date.prototype has the property "toUTCString"'); -} +assert.sameValue( + Date.prototype.hasOwnProperty("toUTCString"), + true, + 'Date.prototype.hasOwnProperty("toUTCString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T1.js index a6ca47d6edb8..3eb5e9e73bbd 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.constructor; -if (x === 1) +if (x === 1) { Date.prototype.constructor = 2; -else +} else { Date.prototype.constructor = 1; -if (Date.prototype.constructor === x) { - throw new Test262Error('#1: The Date.prototype.constructor has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.constructor, + x, + 'The value of Date.prototype.constructor is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T2.js index 3162684d95bd..5c5c11a6ca8c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "constructor" has { DontEnum } attributes esid: sec-date.prototype.constructor description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.constructor, + false, + 'The value of delete Date.prototype.constructor is not false' +); -if (delete Date.prototype.constructor === false) { - throw new Test262Error('#1: The Date.prototype.constructor property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('constructor'), + 'The value of !Date.prototype.hasOwnProperty(\'constructor\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('constructor')) { - throw new Test262Error('#2: The Date.prototype.constructor property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T3.js index 97b3a1882174..4836a6f517f8 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "constructor" has { DontEnum } attributes esid: sec-date.prototype.constructor description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('constructor')) { - throw new Test262Error('#1: The Date.prototype.constructor property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('constructor'), + 'The value of !Date.prototype.propertyIsEnumerable(\'constructor\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "constructor") { - throw new Test262Error('#2: The Date.prototype.constructor has the attribute DontEnum'); - } + assert.notSameValue(x, "constructor", 'The value of x is not "constructor"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A2_T1.js index 16ee99eeff2b..8bc40b00c623 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "constructor" is 7 esid: sec-date.prototype.constructor description: The "length" property of the "constructor" is 7 ---*/ +assert.sameValue( + Date.prototype.constructor.hasOwnProperty("length"), + true, + 'Date.prototype.constructor.hasOwnProperty("length") must return true' +); -if (Date.prototype.constructor.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The constructor has a "length" property'); -} - -if (Date.prototype.constructor.length !== 7) { - throw new Test262Error('#2: The "length" property of the constructor is 7'); -} +assert.sameValue( + Date.prototype.constructor.length, + 7, + 'The value of Date.prototype.constructor.length is expected to be 7' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T1.js index 7264ba592792..fd40dfb3de21 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.constructor.length; verifyNotWritable(Date.prototype.constructor, "length", null, 1); -if (Date.prototype.constructor.length !== x) { - throw new Test262Error('#1: The Date.prototype.constructor.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.constructor.length, + x, + 'The value of Date.prototype.constructor.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T2.js index 56187588d47b..c47d0ec99663 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.constructor description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.constructor.length, + true, + 'The value of `delete Date.prototype.constructor.length` is expected to be true' +); -if (delete Date.prototype.constructor.length !== true) { - throw new Test262Error('#1: The Date.prototype.constructor.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.constructor.hasOwnProperty('length'), + 'The value of !Date.prototype.constructor.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.constructor.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.constructor.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T3.js index caaf8d5b9a0b..3821e5da7664 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/constructor/S15.9.5.1_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.constructor description: Checking DontEnum attribute ---*/ - -if (Date.prototype.constructor.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.constructor.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.constructor.propertyIsEnumerable('length'), + 'The value of !Date.prototype.constructor.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.constructor) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.constructor.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T1.js index ef2816554ff0..b87c3db9ccd4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getDate; -if (x === 1) +if (x === 1) { Date.prototype.getDate = 2; -else +} else { Date.prototype.getDate = 1; -if (Date.prototype.getDate === x) { - throw new Test262Error('#1: The Date.prototype.getDate has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getDate, + x, + 'The value of Date.prototype.getDate is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T2.js index 9d5497b8a4c2..57ffd0b6f6ce 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T2.js @@ -6,13 +6,13 @@ info: The Date.prototype property "getDate" has { DontEnum } attributes esid: sec-date.prototype.getdate description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.getDate, false, 'The value of delete Date.prototype.getDate is not false'); -if (delete Date.prototype.getDate === false) { - throw new Test262Error('#1: The Date.prototype.getDate property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getDate'), + 'The value of !Date.prototype.hasOwnProperty(\'getDate\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getDate')) { - throw new Test262Error('#2: The Date.prototype.getDate property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T3.js index f989b00df30f..f094cafad8fc 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getDate" has { DontEnum } attributes esid: sec-date.prototype.getdate description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getDate')) { - throw new Test262Error('#1: The Date.prototype.getDate property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getDate'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getDate\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getDate") { - throw new Test262Error('#2: The Date.prototype.getDate has the attribute DontEnum'); - } + assert.notSameValue(x, "getDate", 'The value of x is not "getDate"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A2_T1.js index b8a12abb5777..48dc9be48d5f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A2_T1.js @@ -6,13 +6,12 @@ info: The "length" property of the "getDate" is 0 esid: sec-date.prototype.getdate description: The "length" property of the "getDate" is 0 ---*/ +assert.sameValue( + Date.prototype.getDate.hasOwnProperty("length"), + true, + 'Date.prototype.getDate.hasOwnProperty("length") must return true' +); -if (Date.prototype.getDate.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getDate has a "length" property'); -} - -if (Date.prototype.getDate.length !== 0) { - throw new Test262Error('#2: The "length" property of the getDate is 0'); -} +assert.sameValue(Date.prototype.getDate.length, 0, 'The value of Date.prototype.getDate.length is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T1.js index 31fb479c2772..910e6edaf891 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getDate.length; verifyNotWritable(Date.prototype.getDate, "length", null, 1); -if (Date.prototype.getDate.length !== x) { - throw new Test262Error('#1: The Date.prototype.getDate.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getDate.length, + x, + 'The value of Date.prototype.getDate.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T2.js index 8b0c0621de64..3edcd8fe2eba 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getdate description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getDate.length, + true, + 'The value of `delete Date.prototype.getDate.length` is expected to be true' +); -if (delete Date.prototype.getDate.length !== true) { - throw new Test262Error('#1: The Date.prototype.getDate.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getDate.hasOwnProperty('length'), + 'The value of !Date.prototype.getDate.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getDate.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getDate.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T3.js index 8b6092ad7b05..4b9f0503efed 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDate/S15.9.5.14_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getdate description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getDate.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getDate.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getDate.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getDate.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getDate) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getDate.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T1.js index 90cd25a411c4..7fc24d1c492f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T1.js @@ -9,12 +9,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getDay; -if (x === 1) +if (x === 1) { Date.prototype.getDay = 2; -else +} else { Date.prototype.getDay = 1; -if (Date.prototype.getDay === x) { - throw new Test262Error('#1: The Date.prototype.getDay has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getDay, + x, + 'The value of Date.prototype.getDay is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T2.js index 412b0225ca9b..d7e7f2b9c55e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T2.js @@ -7,13 +7,13 @@ info: The Date.prototype property "getDay" has { DontEnum } attributes es5id: 15.9.5.16_A1_T2 description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.getDay, false, 'The value of delete Date.prototype.getDay is not false'); -if (delete Date.prototype.getDay === false) { - throw new Test262Error('#1: The Date.prototype.getDay property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getDay'), + 'The value of !Date.prototype.hasOwnProperty(\'getDay\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getDay')) { - throw new Test262Error('#2: The Date.prototype.getDay property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T3.js index 3be297b4e45a..45b3e2956b18 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A1_T3.js @@ -7,15 +7,15 @@ info: The Date.prototype property "getDay" has { DontEnum } attributes es5id: 15.9.5.16_A1_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getDay')) { - throw new Test262Error('#1: The Date.prototype.getDay property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getDay'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getDay\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getDay") { - throw new Test262Error('#2: The Date.prototype.getDay has the attribute DontEnum'); - } + assert.notSameValue(x, "getDay", 'The value of x is not "getDay"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A2_T1.js index 7292229fefaa..420c63de1d5b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A2_T1.js @@ -7,13 +7,12 @@ info: The "length" property of the "getDay" is 0 es5id: 15.9.5.16_A2_T1 description: The "length" property of the "getDay" is 0 ---*/ +assert.sameValue( + Date.prototype.getDay.hasOwnProperty("length"), + true, + 'Date.prototype.getDay.hasOwnProperty("length") must return true' +); -if (Date.prototype.getDay.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getDay has a "length" property'); -} - -if (Date.prototype.getDay.length !== 0) { - throw new Test262Error('#2: The "length" property of the getDay is 0'); -} +assert.sameValue(Date.prototype.getDay.length, 0, 'The value of Date.prototype.getDay.length is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T1.js index 663530a00b9c..05e4b08b052e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T1.js @@ -13,8 +13,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getDay.length; verifyNotWritable(Date.prototype.getDay, "length", null, 1); -if (Date.prototype.getDay.length !== x) { - throw new Test262Error('#1: The Date.prototype.getDay.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getDay.length, + x, + 'The value of Date.prototype.getDay.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T2.js index 8bd1620eac8c..e133e5c31ebc 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T2.js @@ -9,13 +9,17 @@ info: | es5id: 15.9.5.16_A3_T2 description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getDay.length, + true, + 'The value of `delete Date.prototype.getDay.length` is expected to be true' +); -if (delete Date.prototype.getDay.length !== true) { - throw new Test262Error('#1: The Date.prototype.getDay.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getDay.hasOwnProperty('length'), + 'The value of !Date.prototype.getDay.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getDay.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getDay.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T3.js index 04a362b36535..56b83dbf9758 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getDay/S15.9.5.16_A3_T3.js @@ -9,15 +9,15 @@ info: | es5id: 15.9.5.16_A3_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getDay.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getDay.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getDay.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getDay.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getDay) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getDay.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T1.js index fb86c7cb01ad..7c5a812e3c4f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T1.js @@ -9,12 +9,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getFullYear; -if (x === 1) +if (x === 1) { Date.prototype.getFullYear = 2; -else +} else { Date.prototype.getFullYear = 1; -if (Date.prototype.getFullYear === x) { - throw new Test262Error('#1: The Date.prototype.getFullYear has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getFullYear, + x, + 'The value of Date.prototype.getFullYear is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T2.js index 4a6bfaed0a43..bb2f4ca35acd 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T2.js @@ -7,13 +7,17 @@ info: The Date.prototype property "getFullYear" has { DontEnum } attributes es5id: 15.9.5.10_A1_T2 description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getFullYear, + false, + 'The value of delete Date.prototype.getFullYear is not false' +); -if (delete Date.prototype.getFullYear === false) { - throw new Test262Error('#1: The Date.prototype.getFullYear property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getFullYear'), + 'The value of !Date.prototype.hasOwnProperty(\'getFullYear\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getFullYear')) { - throw new Test262Error('#2: The Date.prototype.getFullYear property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T3.js index a22b2d442f6b..0007014fc4b8 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A1_T3.js @@ -7,15 +7,15 @@ info: The Date.prototype property "getFullYear" has { DontEnum } attributes es5id: 15.9.5.10_A1_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getFullYear')) { - throw new Test262Error('#1: The Date.prototype.getFullYear property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getFullYear'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getFullYear\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getFullYear") { - throw new Test262Error('#2: The Date.prototype.getFullYear has the attribute DontEnum'); - } + assert.notSameValue(x, "getFullYear", 'The value of x is not "getFullYear"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A2_T1.js index d93893af879c..dfa43ba710e7 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A2_T1.js @@ -7,13 +7,16 @@ info: The "length" property of the "getFullYear" is 0 es5id: 15.9.5.10_A2_T1 description: The "length" property of the "getFullYear" is 0 ---*/ +assert.sameValue( + Date.prototype.getFullYear.hasOwnProperty("length"), + true, + 'Date.prototype.getFullYear.hasOwnProperty("length") must return true' +); -if (Date.prototype.getFullYear.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getFullYear has a "length" property'); -} - -if (Date.prototype.getFullYear.length !== 0) { - throw new Test262Error('#2: The "length" property of the getFullYear is 0'); -} +assert.sameValue( + Date.prototype.getFullYear.length, + 0, + 'The value of Date.prototype.getFullYear.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T1.js index 9689c55abf66..96612522fb97 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T1.js @@ -13,8 +13,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getFullYear.length; verifyNotWritable(Date.prototype.getFullYear, "length", null, 1); -if (Date.prototype.getFullYear.length !== x) { - throw new Test262Error('#1: The Date.prototype.getFullYear.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getFullYear.length, + x, + 'The value of Date.prototype.getFullYear.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T2.js index 621fb0dc44fa..7e3309aed25d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T2.js @@ -9,13 +9,17 @@ info: | es5id: 15.9.5.10_A3_T2 description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getFullYear.length, + true, + 'The value of `delete Date.prototype.getFullYear.length` is expected to be true' +); -if (delete Date.prototype.getFullYear.length !== true) { - throw new Test262Error('#1: The Date.prototype.getFullYear.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getFullYear.hasOwnProperty('length'), + 'The value of !Date.prototype.getFullYear.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getFullYear.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getFullYear.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T3.js index c36bedf45ce6..aa8696ea5612 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getFullYear/S15.9.5.10_A3_T3.js @@ -9,15 +9,15 @@ info: | es5id: 15.9.5.10_A3_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getFullYear.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getFullYear.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getFullYear.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getFullYear.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getFullYear) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getFullYear.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T1.js index cdf27df54071..b5d567e82b4c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T1.js @@ -9,12 +9,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getHours; -if (x === 1) +if (x === 1) { Date.prototype.getHours = 2; -else +} else { Date.prototype.getHours = 1; -if (Date.prototype.getHours === x) { - throw new Test262Error('#1: The Date.prototype.getHours has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getHours, + x, + 'The value of Date.prototype.getHours is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T2.js index 41df5bb2bf0b..6db23684586c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T2.js @@ -7,13 +7,13 @@ info: The Date.prototype property "getHours" has { DontEnum } attributes es5id: 15.9.5.18_A1_T2 description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.getHours, false, 'The value of delete Date.prototype.getHours is not false'); -if (delete Date.prototype.getHours === false) { - throw new Test262Error('#1: The Date.prototype.getHours property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getHours'), + 'The value of !Date.prototype.hasOwnProperty(\'getHours\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getHours')) { - throw new Test262Error('#2: The Date.prototype.getHours property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T3.js index 732564d2a82a..2e4a4cb504f3 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A1_T3.js @@ -7,15 +7,15 @@ info: The Date.prototype property "getHours" has { DontEnum } attributes es5id: 15.9.5.18_A1_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getHours')) { - throw new Test262Error('#1: The Date.prototype.getHours property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getHours'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getHours\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getHours") { - throw new Test262Error('#2: The Date.prototype.getHours has the attribute DontEnum'); - } + assert.notSameValue(x, "getHours", 'The value of x is not "getHours"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A2_T1.js index 60a3049d6101..7a10e7fa70ab 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A2_T1.js @@ -7,13 +7,12 @@ info: The "length" property of the "getHours" is 0 es5id: 15.9.5.18_A2_T1 description: The "length" property of the "getHours" is 0 ---*/ +assert.sameValue( + Date.prototype.getHours.hasOwnProperty("length"), + true, + 'Date.prototype.getHours.hasOwnProperty("length") must return true' +); -if (Date.prototype.getHours.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getHours has a "length" property'); -} - -if (Date.prototype.getHours.length !== 0) { - throw new Test262Error('#2: The "length" property of the getHours is 0'); -} +assert.sameValue(Date.prototype.getHours.length, 0, 'The value of Date.prototype.getHours.length is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T1.js index d144f6a00f87..91895b2dc40e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T1.js @@ -13,8 +13,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getHours.length; verifyNotWritable(Date.prototype.getHours, "length", null, 1); -if (Date.prototype.getHours.length !== x) { - throw new Test262Error('#1: The Date.prototype.getHours.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getHours.length, + x, + 'The value of Date.prototype.getHours.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T2.js index b635c34bdcd2..39c306667f01 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T2.js @@ -9,13 +9,17 @@ info: | es5id: 15.9.5.18_A3_T2 description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getHours.length, + true, + 'The value of `delete Date.prototype.getHours.length` is expected to be true' +); -if (delete Date.prototype.getHours.length !== true) { - throw new Test262Error('#1: The Date.prototype.getHours.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getHours.hasOwnProperty('length'), + 'The value of !Date.prototype.getHours.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getHours.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getHours.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T3.js index 472ab9faaa86..10d086579985 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getHours/S15.9.5.18_A3_T3.js @@ -9,15 +9,15 @@ info: | es5id: 15.9.5.18_A3_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getHours.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getHours.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getHours.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getHours.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getHours) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getHours.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T1.js index b5a423d464f7..d6ce91e98b1a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T1.js @@ -9,12 +9,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getMilliseconds; -if (x === 1) +if (x === 1) { Date.prototype.getMilliseconds = 2; -else +} else { Date.prototype.getMilliseconds = 1; -if (Date.prototype.getMilliseconds === x) { - throw new Test262Error('#1: The Date.prototype.getMilliseconds has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getMilliseconds, + x, + 'The value of Date.prototype.getMilliseconds is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T2.js index d53fc4984572..f8c8c27b8fb0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T2.js @@ -7,13 +7,17 @@ info: The Date.prototype property "getMilliseconds" has { DontEnum } attributes es5id: 15.9.5.24_A1_T2 description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getMilliseconds, + false, + 'The value of delete Date.prototype.getMilliseconds is not false' +); -if (delete Date.prototype.getMilliseconds === false) { - throw new Test262Error('#1: The Date.prototype.getMilliseconds property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getMilliseconds'), + 'The value of !Date.prototype.hasOwnProperty(\'getMilliseconds\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getMilliseconds')) { - throw new Test262Error('#2: The Date.prototype.getMilliseconds property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T3.js index 08835745cbb2..0f39980bce99 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A1_T3.js @@ -7,15 +7,15 @@ info: The Date.prototype property "getMilliseconds" has { DontEnum } attributes es5id: 15.9.5.24_A1_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getMilliseconds')) { - throw new Test262Error('#1: The Date.prototype.getMilliseconds property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getMilliseconds'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getMilliseconds\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getMilliseconds") { - throw new Test262Error('#2: The Date.prototype.getMilliseconds has the attribute DontEnum'); - } + assert.notSameValue(x, "getMilliseconds", 'The value of x is not "getMilliseconds"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A2_T1.js index f9722dd3da1f..84f0bba12514 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A2_T1.js @@ -7,13 +7,16 @@ info: The "length" property of the "getMilliseconds" is 0 es5id: 15.9.5.24_A2_T1 description: The "length" property of the "getMilliseconds" is 0 ---*/ +assert.sameValue( + Date.prototype.getMilliseconds.hasOwnProperty("length"), + true, + 'Date.prototype.getMilliseconds.hasOwnProperty("length") must return true' +); -if (Date.prototype.getMilliseconds.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getMilliseconds has a "length" property'); -} - -if (Date.prototype.getMilliseconds.length !== 0) { - throw new Test262Error('#2: The "length" property of the getMilliseconds is 0'); -} +assert.sameValue( + Date.prototype.getMilliseconds.length, + 0, + 'The value of Date.prototype.getMilliseconds.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T1.js index 310696a7dd5d..692247a28a22 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T1.js @@ -13,8 +13,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getMilliseconds.length; verifyNotWritable(Date.prototype.getMilliseconds, "length", null, 1); -if (Date.prototype.getMilliseconds.length !== x) { - throw new Test262Error('#1: The Date.prototype.getMilliseconds.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getMilliseconds.length, + x, + 'The value of Date.prototype.getMilliseconds.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T2.js index e98b7fbbcbf7..08208a9d9e7c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T2.js @@ -9,13 +9,17 @@ info: | es5id: 15.9.5.24_A3_T2 description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getMilliseconds.length, + true, + 'The value of `delete Date.prototype.getMilliseconds.length` is expected to be true' +); -if (delete Date.prototype.getMilliseconds.length !== true) { - throw new Test262Error('#1: The Date.prototype.getMilliseconds.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getMilliseconds.hasOwnProperty('length'), + 'The value of !Date.prototype.getMilliseconds.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getMilliseconds.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getMilliseconds.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T3.js index e6d418ab2419..337e72a7e204 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMilliseconds/S15.9.5.24_A3_T3.js @@ -9,15 +9,15 @@ info: | es5id: 15.9.5.24_A3_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getMilliseconds.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getMilliseconds.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getMilliseconds.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getMilliseconds.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getMilliseconds) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getMilliseconds.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T1.js index 0e20c554eee9..1568ec836cce 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T1.js @@ -9,12 +9,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getMinutes; -if (x === 1) +if (x === 1) { Date.prototype.getMinutes = 2; -else +} else { Date.prototype.getMinutes = 1; -if (Date.prototype.getMinutes === x) { - throw new Test262Error('#1: The Date.prototype.getMinutes has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getMinutes, + x, + 'The value of Date.prototype.getMinutes is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T2.js index 86fdb1c633e0..d792c65f1c43 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T2.js @@ -7,13 +7,17 @@ info: The Date.prototype property "getMinutes" has { DontEnum } attributes es5id: 15.9.5.20_A1_T2 description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getMinutes, + false, + 'The value of delete Date.prototype.getMinutes is not false' +); -if (delete Date.prototype.getMinutes === false) { - throw new Test262Error('#1: The Date.prototype.getMinutes property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getMinutes'), + 'The value of !Date.prototype.hasOwnProperty(\'getMinutes\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getMinutes')) { - throw new Test262Error('#2: The Date.prototype.getMinutes property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T3.js index 0184cfdb1683..2e79948084ca 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A1_T3.js @@ -7,15 +7,15 @@ info: The Date.prototype property "getMinutes" has { DontEnum } attributes es5id: 15.9.5.20_A1_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getMinutes')) { - throw new Test262Error('#1: The Date.prototype.getMinutes property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getMinutes'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getMinutes\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getMinutes") { - throw new Test262Error('#2: The Date.prototype.getMinutes has the attribute DontEnum'); - } + assert.notSameValue(x, "getMinutes", 'The value of x is not "getMinutes"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A2_T1.js index fdeafa94ba01..8a85f1211ab9 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A2_T1.js @@ -7,13 +7,16 @@ info: The "length" property of the "getMinutes" is 0 es5id: 15.9.5.20_A2_T1 description: The "length" property of the "getMinutes" is 0 ---*/ +assert.sameValue( + Date.prototype.getMinutes.hasOwnProperty("length"), + true, + 'Date.prototype.getMinutes.hasOwnProperty("length") must return true' +); -if (Date.prototype.getMinutes.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getMinutes has a "length" property'); -} - -if (Date.prototype.getMinutes.length !== 0) { - throw new Test262Error('#2: The "length" property of the getMinutes is 0'); -} +assert.sameValue( + Date.prototype.getMinutes.length, + 0, + 'The value of Date.prototype.getMinutes.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T1.js index d6422ee3d425..19b83040f6c1 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T1.js @@ -13,8 +13,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getMinutes.length; verifyNotWritable(Date.prototype.getMinutes, "length", null, 1); -if (Date.prototype.getMinutes.length !== x) { - throw new Test262Error('#1: The Date.prototype.getMinutes.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getMinutes.length, + x, + 'The value of Date.prototype.getMinutes.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T2.js index bc507a46f0a6..c81cd920e23e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T2.js @@ -9,13 +9,17 @@ info: | es5id: 15.9.5.20_A3_T2 description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getMinutes.length, + true, + 'The value of `delete Date.prototype.getMinutes.length` is expected to be true' +); -if (delete Date.prototype.getMinutes.length !== true) { - throw new Test262Error('#1: The Date.prototype.getMinutes.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getMinutes.hasOwnProperty('length'), + 'The value of !Date.prototype.getMinutes.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getMinutes.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getMinutes.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T3.js index 7e7b63b9dd38..d100261b046c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMinutes/S15.9.5.20_A3_T3.js @@ -9,15 +9,15 @@ info: | es5id: 15.9.5.20_A3_T3 description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getMinutes.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getMinutes.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getMinutes.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getMinutes.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getMinutes) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getMinutes.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T1.js index a1305f231363..746c749d4213 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getMonth; -if (x === 1) +if (x === 1) { Date.prototype.getMonth = 2; -else +} else { Date.prototype.getMonth = 1; -if (Date.prototype.getMonth === x) { - throw new Test262Error('#1: The Date.prototype.getMonth has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getMonth, + x, + 'The value of Date.prototype.getMonth is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T2.js index 5d230379a07d..d7cc73e91f7e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T2.js @@ -6,13 +6,13 @@ info: The Date.prototype property "getMonth" has { DontEnum } attributes esid: sec-date.prototype.getmonth description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.getMonth, false, 'The value of delete Date.prototype.getMonth is not false'); -if (delete Date.prototype.getMonth === false) { - throw new Test262Error('#1: The Date.prototype.getMonth property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getMonth'), + 'The value of !Date.prototype.hasOwnProperty(\'getMonth\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getMonth')) { - throw new Test262Error('#2: The Date.prototype.getMonth property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T3.js index d1078313f9de..24081e0d128d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getMonth" has { DontEnum } attributes esid: sec-date.prototype.getmonth description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getMonth')) { - throw new Test262Error('#1: The Date.prototype.getMonth property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getMonth'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getMonth\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getMonth") { - throw new Test262Error('#2: The Date.prototype.getMonth has the attribute DontEnum'); - } + assert.notSameValue(x, "getMonth", 'The value of x is not "getMonth"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A2_T1.js index 5066196d7b19..a7db351a63bf 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A2_T1.js @@ -6,13 +6,12 @@ info: The "length" property of the "getMonth" is 0 esid: sec-date.prototype.getmonth description: The "length" property of the "getMonth" is 0 ---*/ +assert.sameValue( + Date.prototype.getMonth.hasOwnProperty("length"), + true, + 'Date.prototype.getMonth.hasOwnProperty("length") must return true' +); -if (Date.prototype.getMonth.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getMonth has a "length" property'); -} - -if (Date.prototype.getMonth.length !== 0) { - throw new Test262Error('#2: The "length" property of the getMonth is 0'); -} +assert.sameValue(Date.prototype.getMonth.length, 0, 'The value of Date.prototype.getMonth.length is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T1.js index 5a5736278017..7c282d67e125 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getMonth.length; verifyNotWritable(Date.prototype.getMonth, "length", null, 1); -if (Date.prototype.getMonth.length !== x) { - throw new Test262Error('#1: The Date.prototype.getMonth.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getMonth.length, + x, + 'The value of Date.prototype.getMonth.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T2.js index b51fe4fa8468..b19fb31de022 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getmonth description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getMonth.length, + true, + 'The value of `delete Date.prototype.getMonth.length` is expected to be true' +); -if (delete Date.prototype.getMonth.length !== true) { - throw new Test262Error('#1: The Date.prototype.getMonth.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getMonth.hasOwnProperty('length'), + 'The value of !Date.prototype.getMonth.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getMonth.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getMonth.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T3.js index 53476a227158..05979ef2ea37 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getMonth/S15.9.5.12_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getmonth description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getMonth.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getMonth.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getMonth.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getMonth.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getMonth) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getMonth.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T1.js index 6b35205f0689..b372371f8732 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getSeconds; -if (x === 1) +if (x === 1) { Date.prototype.getSeconds = 2; -else +} else { Date.prototype.getSeconds = 1; -if (Date.prototype.getSeconds === x) { - throw new Test262Error('#1: The Date.prototype.getSeconds has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getSeconds, + x, + 'The value of Date.prototype.getSeconds is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T2.js index c6fef7a39751..0b096b7988e4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "getSeconds" has { DontEnum } attributes esid: sec-date.prototype.getseconds description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getSeconds, + false, + 'The value of delete Date.prototype.getSeconds is not false' +); -if (delete Date.prototype.getSeconds === false) { - throw new Test262Error('#1: The Date.prototype.getSeconds property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getSeconds'), + 'The value of !Date.prototype.hasOwnProperty(\'getSeconds\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getSeconds')) { - throw new Test262Error('#2: The Date.prototype.getSeconds property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T3.js index 87727cf76501..58daf773d859 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getSeconds" has { DontEnum } attributes esid: sec-date.prototype.getseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getSeconds')) { - throw new Test262Error('#1: The Date.prototype.getSeconds property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getSeconds'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getSeconds\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getSeconds") { - throw new Test262Error('#2: The Date.prototype.getSeconds has the attribute DontEnum'); - } + assert.notSameValue(x, "getSeconds", 'The value of x is not "getSeconds"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A2_T1.js index 3385106c6b15..54125a0509e7 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getSeconds" is 0 esid: sec-date.prototype.getseconds description: The "length" property of the "getSeconds" is 0 ---*/ +assert.sameValue( + Date.prototype.getSeconds.hasOwnProperty("length"), + true, + 'Date.prototype.getSeconds.hasOwnProperty("length") must return true' +); -if (Date.prototype.getSeconds.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getSeconds has a "length" property'); -} - -if (Date.prototype.getSeconds.length !== 0) { - throw new Test262Error('#2: The "length" property of the getSeconds is 0'); -} +assert.sameValue( + Date.prototype.getSeconds.length, + 0, + 'The value of Date.prototype.getSeconds.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T1.js index eeb6e78164c9..557aa5353150 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getSeconds.length; verifyNotWritable(Date.prototype.getSeconds, "length", null, 1); -if (Date.prototype.getSeconds.length !== x) { - throw new Test262Error('#1: The Date.prototype.getSeconds.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getSeconds.length, + x, + 'The value of Date.prototype.getSeconds.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T2.js index 047edbb49f3e..cb6f6497ae97 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getseconds description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getSeconds.length, + true, + 'The value of `delete Date.prototype.getSeconds.length` is expected to be true' +); -if (delete Date.prototype.getSeconds.length !== true) { - throw new Test262Error('#1: The Date.prototype.getSeconds.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getSeconds.hasOwnProperty('length'), + 'The value of !Date.prototype.getSeconds.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getSeconds.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getSeconds.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T3.js index ff39e1b27363..c6b40d5dba00 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getSeconds/S15.9.5.22_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getSeconds.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getSeconds.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getSeconds.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getSeconds.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getSeconds) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getSeconds.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T1.js index 5f89600914e9..988395a70911 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getTime; -if (x === 1) +if (x === 1) { Date.prototype.getTime = 2; -else +} else { Date.prototype.getTime = 1; -if (Date.prototype.getTime === x) { - throw new Test262Error('#1: The Date.prototype.getTime has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getTime, + x, + 'The value of Date.prototype.getTime is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T2.js index 9f41f45a7741..37072a751c64 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T2.js @@ -6,13 +6,13 @@ info: The Date.prototype property "getTime" has { DontEnum } attributes esid: sec-date.prototype.getseconds description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.getTime, false, 'The value of delete Date.prototype.getTime is not false'); -if (delete Date.prototype.getTime === false) { - throw new Test262Error('#1: The Date.prototype.getTime property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getTime'), + 'The value of !Date.prototype.hasOwnProperty(\'getTime\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getTime')) { - throw new Test262Error('#2: The Date.prototype.getTime property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T3.js index 6ee97e6987ff..db5608efbda5 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getTime" has { DontEnum } attributes esid: sec-date.prototype.getseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getTime')) { - throw new Test262Error('#1: The Date.prototype.getTime property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getTime'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getTime\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getTime") { - throw new Test262Error('#2: The Date.prototype.getTime has the attribute DontEnum'); - } + assert.notSameValue(x, "getTime", 'The value of x is not "getTime"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A2_T1.js index 15699ece93e0..0c5c84f24a1f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A2_T1.js @@ -6,13 +6,12 @@ info: The "length" property of the "getTime" is 0 esid: sec-date.prototype.getseconds description: The "length" property of the "getTime" is 0 ---*/ +assert.sameValue( + Date.prototype.getTime.hasOwnProperty("length"), + true, + 'Date.prototype.getTime.hasOwnProperty("length") must return true' +); -if (Date.prototype.getTime.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getTime has a "length" property'); -} - -if (Date.prototype.getTime.length !== 0) { - throw new Test262Error('#2: The "length" property of the getTime is 0'); -} +assert.sameValue(Date.prototype.getTime.length, 0, 'The value of Date.prototype.getTime.length is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T1.js index 32f63109ca46..05081b50ed28 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getTime.length; verifyNotWritable(Date.prototype.getTime, "length", null, 1); -if (Date.prototype.getTime.length !== x) { - throw new Test262Error('#1: The Date.prototype.getTime.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getTime.length, + x, + 'The value of Date.prototype.getTime.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T2.js index 9ee9c2c582b0..ef3c553cdb9a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getseconds description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getTime.length, + true, + 'The value of `delete Date.prototype.getTime.length` is expected to be true' +); -if (delete Date.prototype.getTime.length !== true) { - throw new Test262Error('#1: The Date.prototype.getTime.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getTime.hasOwnProperty('length'), + 'The value of !Date.prototype.getTime.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getTime.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getTime.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T3.js index 90e19a573da8..3df558d0ccdf 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTime/S15.9.5.9_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getTime.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getTime.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getTime.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getTime.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getTime) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getTime.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T1.js index 16f2b6ff5ac3..eb9033ac957f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T1.js @@ -10,12 +10,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getTimezoneOffset; -if (x === 1) +if (x === 1) { Date.prototype.getTimezoneOffset = 2; -else +} else { Date.prototype.getTimezoneOffset = 1; -if (Date.prototype.getTimezoneOffset === x) { - throw new Test262Error('#1: The Date.prototype.getTimezoneOffset has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getTimezoneOffset, + x, + 'The value of Date.prototype.getTimezoneOffset is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T2.js index ac21ce2ab213..d5f30d46e94a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.gettimezoneoffset description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getTimezoneOffset, + false, + 'The value of delete Date.prototype.getTimezoneOffset is not false' +); -if (delete Date.prototype.getTimezoneOffset === false) { - throw new Test262Error('#1: The Date.prototype.getTimezoneOffset property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getTimezoneOffset'), + 'The value of !Date.prototype.hasOwnProperty(\'getTimezoneOffset\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getTimezoneOffset')) { - throw new Test262Error('#2: The Date.prototype.getTimezoneOffset property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T3.js index 380ce40a243e..e0d1ee4a1414 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A1_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.gettimezoneoffset description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getTimezoneOffset')) { - throw new Test262Error('#1: The Date.prototype.getTimezoneOffset property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getTimezoneOffset'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getTimezoneOffset\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getTimezoneOffset") { - throw new Test262Error('#2: The Date.prototype.getTimezoneOffset has the attribute DontEnum'); - } + assert.notSameValue(x, "getTimezoneOffset", 'The value of x is not "getTimezoneOffset"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A2_T1.js index 805fa99b6a16..8e7b596a4246 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getTimezoneOffset" is 0 esid: sec-date.prototype.gettimezoneoffset description: The "length" property of the "getTimezoneOffset" is 0 ---*/ +assert.sameValue( + Date.prototype.getTimezoneOffset.hasOwnProperty("length"), + true, + 'Date.prototype.getTimezoneOffset.hasOwnProperty("length") must return true' +); -if (Date.prototype.getTimezoneOffset.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getTimezoneOffset has a "length" property'); -} - -if (Date.prototype.getTimezoneOffset.length !== 0) { - throw new Test262Error('#2: The "length" property of the getTimezoneOffset is 0'); -} +assert.sameValue( + Date.prototype.getTimezoneOffset.length, + 0, + 'The value of Date.prototype.getTimezoneOffset.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T1.js index 4b8f66da1598..9996c8e550fb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getTimezoneOffset.length; verifyNotWritable(Date.prototype.getTimezoneOffset, "length", null, 1); -if (Date.prototype.getTimezoneOffset.length !== x) { - throw new Test262Error('#1: The Date.prototype.getTimezoneOffset.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getTimezoneOffset.length, + x, + 'The value of Date.prototype.getTimezoneOffset.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T2.js index eea660847d7c..deeec64aa067 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.gettimezoneoffset description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getTimezoneOffset.length, + true, + 'The value of `delete Date.prototype.getTimezoneOffset.length` is expected to be true' +); -if (delete Date.prototype.getTimezoneOffset.length !== true) { - throw new Test262Error('#1: The Date.prototype.getTimezoneOffset.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getTimezoneOffset.hasOwnProperty('length'), + 'The value of !Date.prototype.getTimezoneOffset.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getTimezoneOffset.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getTimezoneOffset.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T3.js index 429d9d834e8f..3c9e7c9966dc 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getTimezoneOffset/S15.9.5.26_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.gettimezoneoffset description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getTimezoneOffset.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getTimezoneOffset.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getTimezoneOffset.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getTimezoneOffset.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getTimezoneOffset) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getTimezoneOffset.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T1.js index 16c86ba4617d..16aebb6fae8c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getUTCDate; -if (x === 1) +if (x === 1) { Date.prototype.getUTCDate = 2; -else +} else { Date.prototype.getUTCDate = 1; -if (Date.prototype.getUTCDate === x) { - throw new Test262Error('#1: The Date.prototype.getUTCDate has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getUTCDate, + x, + 'The value of Date.prototype.getUTCDate is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T2.js index 63a7942b5f02..b25440b9b0c8 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "getUTCDate" has { DontEnum } attributes esid: sec-date.prototype.getutcdate description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getUTCDate, + false, + 'The value of delete Date.prototype.getUTCDate is not false' +); -if (delete Date.prototype.getUTCDate === false) { - throw new Test262Error('#1: The Date.prototype.getUTCDate property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getUTCDate'), + 'The value of !Date.prototype.hasOwnProperty(\'getUTCDate\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getUTCDate')) { - throw new Test262Error('#2: The Date.prototype.getUTCDate property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T3.js index 5066e2776638..48e68cc14f8a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getUTCDate" has { DontEnum } attributes esid: sec-date.prototype.getutcdate description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getUTCDate')) { - throw new Test262Error('#1: The Date.prototype.getUTCDate property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getUTCDate'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getUTCDate\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getUTCDate") { - throw new Test262Error('#2: The Date.prototype.getUTCDate has the attribute DontEnum'); - } + assert.notSameValue(x, "getUTCDate", 'The value of x is not "getUTCDate"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A2_T1.js index fdf758c5cb82..0810fab7cecd 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getUTCDate" is 0 esid: sec-date.prototype.getutcdate description: The "length" property of the "getUTCDate" is 0 ---*/ +assert.sameValue( + Date.prototype.getUTCDate.hasOwnProperty("length"), + true, + 'Date.prototype.getUTCDate.hasOwnProperty("length") must return true' +); -if (Date.prototype.getUTCDate.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getUTCDate has a "length" property'); -} - -if (Date.prototype.getUTCDate.length !== 0) { - throw new Test262Error('#2: The "length" property of the getUTCDate is 0'); -} +assert.sameValue( + Date.prototype.getUTCDate.length, + 0, + 'The value of Date.prototype.getUTCDate.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T1.js index 7faed9693971..e71163dee841 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getUTCDate.length; verifyNotWritable(Date.prototype.getUTCDate, "length", null, 1); -if (Date.prototype.getUTCDate.length !== x) { - throw new Test262Error('#1: The Date.prototype.getUTCDate.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getUTCDate.length, + x, + 'The value of Date.prototype.getUTCDate.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T2.js index 5a373a17843d..e9dfd484db55 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutcdate description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getUTCDate.length, + true, + 'The value of `delete Date.prototype.getUTCDate.length` is expected to be true' +); -if (delete Date.prototype.getUTCDate.length !== true) { - throw new Test262Error('#1: The Date.prototype.getUTCDate.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getUTCDate.hasOwnProperty('length'), + 'The value of !Date.prototype.getUTCDate.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getUTCDate.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getUTCDate.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T3.js index 2dd4e69e3d4b..17f63b8d667c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDate/S15.9.5.15_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutcdate description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getUTCDate.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getUTCDate.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getUTCDate.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getUTCDate.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getUTCDate) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getUTCDate.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T1.js index 5bad968fff3c..cd9b0ff28790 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getUTCDay; -if (x === 1) +if (x === 1) { Date.prototype.getUTCDay = 2; -else +} else { Date.prototype.getUTCDay = 1; -if (Date.prototype.getUTCDay === x) { - throw new Test262Error('#1: The Date.prototype.getUTCDay has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getUTCDay, + x, + 'The value of Date.prototype.getUTCDay is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T2.js index 5e15c02ba736..8863c901e30c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T2.js @@ -6,13 +6,13 @@ info: The Date.prototype property "getUTCDay" has { DontEnum } attributes esid: sec-date.prototype.getutcdaty description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.getUTCDay, false, 'The value of delete Date.prototype.getUTCDay is not false'); -if (delete Date.prototype.getUTCDay === false) { - throw new Test262Error('#1: The Date.prototype.getUTCDay property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getUTCDay'), + 'The value of !Date.prototype.hasOwnProperty(\'getUTCDay\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getUTCDay')) { - throw new Test262Error('#2: The Date.prototype.getUTCDay property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T3.js index 3ca9ca9a5e07..4b29c9feef79 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getUTCDay" has { DontEnum } attributes esid: sec-date.prototype.getutcdaty description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getUTCDay')) { - throw new Test262Error('#1: The Date.prototype.getUTCDay property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getUTCDay'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getUTCDay\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getUTCDay") { - throw new Test262Error('#2: The Date.prototype.getUTCDay has the attribute DontEnum'); - } + assert.notSameValue(x, "getUTCDay", 'The value of x is not "getUTCDay"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A2_T1.js index 41d920c1f95f..c99eb6aedc61 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getUTCDay" is 0 esid: sec-date.prototype.getutcdaty description: The "length" property of the "getUTCDay" is 0 ---*/ +assert.sameValue( + Date.prototype.getUTCDay.hasOwnProperty("length"), + true, + 'Date.prototype.getUTCDay.hasOwnProperty("length") must return true' +); -if (Date.prototype.getUTCDay.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getUTCDay has a "length" property'); -} - -if (Date.prototype.getUTCDay.length !== 0) { - throw new Test262Error('#2: The "length" property of the getUTCDay is 0'); -} +assert.sameValue( + Date.prototype.getUTCDay.length, + 0, + 'The value of Date.prototype.getUTCDay.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T1.js index 6770f982516e..cdfc659d5bb9 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getUTCDay.length; verifyNotWritable(Date.prototype.getUTCDay, "length", null, 1); -if (Date.prototype.getUTCDay.length !== x) { - throw new Test262Error('#1: The Date.prototype.getUTCDay.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getUTCDay.length, + x, + 'The value of Date.prototype.getUTCDay.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T2.js index 5cc63fe15e46..0ba6464b6163 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutcdaty description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getUTCDay.length, + true, + 'The value of `delete Date.prototype.getUTCDay.length` is expected to be true' +); -if (delete Date.prototype.getUTCDay.length !== true) { - throw new Test262Error('#1: The Date.prototype.getUTCDay.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getUTCDay.hasOwnProperty('length'), + 'The value of !Date.prototype.getUTCDay.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getUTCDay.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getUTCDay.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T3.js index fa7608772bca..42c7b12a6d8b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCDay/S15.9.5.17_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutcdaty description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getUTCDay.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getUTCDay.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getUTCDay.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getUTCDay.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getUTCDay) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getUTCDay.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T1.js index 54e6cd200cca..ef8e59efbd9a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getUTCFullYear; -if (x === 1) +if (x === 1) { Date.prototype.getUTCFullYear = 2; -else +} else { Date.prototype.getUTCFullYear = 1; -if (Date.prototype.getUTCFullYear === x) { - throw new Test262Error('#1: The Date.prototype.getUTCFullYear has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getUTCFullYear, + x, + 'The value of Date.prototype.getUTCFullYear is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T2.js index db99c4843121..49733ea562a9 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "getUTCFullYear" has { DontEnum } attributes esid: sec-date.prototype.getutcfullyear description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getUTCFullYear, + false, + 'The value of delete Date.prototype.getUTCFullYear is not false' +); -if (delete Date.prototype.getUTCFullYear === false) { - throw new Test262Error('#1: The Date.prototype.getUTCFullYear property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getUTCFullYear'), + 'The value of !Date.prototype.hasOwnProperty(\'getUTCFullYear\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getUTCFullYear')) { - throw new Test262Error('#2: The Date.prototype.getUTCFullYear property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T3.js index e2b5f8453afd..7ddec587e5f0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getUTCFullYear" has { DontEnum } attributes esid: sec-date.prototype.getutcfullyear description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getUTCFullYear')) { - throw new Test262Error('#1: The Date.prototype.getUTCFullYear property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getUTCFullYear'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getUTCFullYear\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getUTCFullYear") { - throw new Test262Error('#2: The Date.prototype.getUTCFullYear has the attribute DontEnum'); - } + assert.notSameValue(x, "getUTCFullYear", 'The value of x is not "getUTCFullYear"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A2_T1.js index ba1569d0c264..9779569d9b1a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getUTCFullYear" is 0 esid: sec-date.prototype.getutcfullyear description: The "length" property of the "getUTCFullYear" is 0 ---*/ +assert.sameValue( + Date.prototype.getUTCFullYear.hasOwnProperty("length"), + true, + 'Date.prototype.getUTCFullYear.hasOwnProperty("length") must return true' +); -if (Date.prototype.getUTCFullYear.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getUTCFullYear has a "length" property'); -} - -if (Date.prototype.getUTCFullYear.length !== 0) { - throw new Test262Error('#2: The "length" property of the getUTCFullYear is 0'); -} +assert.sameValue( + Date.prototype.getUTCFullYear.length, + 0, + 'The value of Date.prototype.getUTCFullYear.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T1.js index fb8b829a3001..ae085004cc63 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getUTCFullYear.length; verifyNotWritable(Date.prototype.getUTCFullYear, "length", null, 1); -if (Date.prototype.getUTCFullYear.length !== x) { - throw new Test262Error('#1: The Date.prototype.getUTCFullYear.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getUTCFullYear.length, + x, + 'The value of Date.prototype.getUTCFullYear.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T2.js index 16afec537996..8c21d6d78806 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutcfullyear description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getUTCFullYear.length, + true, + 'The value of `delete Date.prototype.getUTCFullYear.length` is expected to be true' +); -if (delete Date.prototype.getUTCFullYear.length !== true) { - throw new Test262Error('#1: The Date.prototype.getUTCFullYear.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getUTCFullYear.hasOwnProperty('length'), + 'The value of !Date.prototype.getUTCFullYear.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getUTCFullYear.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getUTCFullYear.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T3.js index e66596211334..317b78bd4fc0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCFullYear/S15.9.5.11_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutcfullyear description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getUTCFullYear.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getUTCFullYear.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getUTCFullYear.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getUTCFullYear.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getUTCFullYear) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getUTCFullYear.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T1.js index 174f0eb1a233..c3dc2fec3fe2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getUTCHours; -if (x === 1) +if (x === 1) { Date.prototype.getUTCHours = 2; -else +} else { Date.prototype.getUTCHours = 1; -if (Date.prototype.getUTCHours === x) { - throw new Test262Error('#1: The Date.prototype.getUTCHours has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getUTCHours, + x, + 'The value of Date.prototype.getUTCHours is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T2.js index 08f3741b4e5c..391e4c9ae609 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "getUTCHours" has { DontEnum } attributes esid: sec-date.prototype.getutchours description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getUTCHours, + false, + 'The value of delete Date.prototype.getUTCHours is not false' +); -if (delete Date.prototype.getUTCHours === false) { - throw new Test262Error('#1: The Date.prototype.getUTCHours property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getUTCHours'), + 'The value of !Date.prototype.hasOwnProperty(\'getUTCHours\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getUTCHours')) { - throw new Test262Error('#2: The Date.prototype.getUTCHours property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T3.js index e99c327dc036..881e02a43a4b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getUTCHours" has { DontEnum } attributes esid: sec-date.prototype.getutchours description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getUTCHours')) { - throw new Test262Error('#1: The Date.prototype.getUTCHours property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getUTCHours'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getUTCHours\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getUTCHours") { - throw new Test262Error('#2: The Date.prototype.getUTCHours has the attribute DontEnum'); - } + assert.notSameValue(x, "getUTCHours", 'The value of x is not "getUTCHours"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A2_T1.js index a582b2e3a6f9..8fc7619ec2b0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getUTCHours" is 0 esid: sec-date.prototype.getutchours description: The "length" property of the "getUTCHours" is 0 ---*/ +assert.sameValue( + Date.prototype.getUTCHours.hasOwnProperty("length"), + true, + 'Date.prototype.getUTCHours.hasOwnProperty("length") must return true' +); -if (Date.prototype.getUTCHours.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getUTCHours has a "length" property'); -} - -if (Date.prototype.getUTCHours.length !== 0) { - throw new Test262Error('#2: The "length" property of the getUTCHours is 0'); -} +assert.sameValue( + Date.prototype.getUTCHours.length, + 0, + 'The value of Date.prototype.getUTCHours.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T1.js index 416305ae924b..17c8d64a95ee 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getUTCHours.length; verifyNotWritable(Date.prototype.getUTCHours, "length", null, 1); -if (Date.prototype.getUTCHours.length !== x) { - throw new Test262Error('#1: The Date.prototype.getUTCHours.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getUTCHours.length, + x, + 'The value of Date.prototype.getUTCHours.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T2.js index 072fbbbcf7bd..b7bbcdcfdb3c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutchours description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getUTCHours.length, + true, + 'The value of `delete Date.prototype.getUTCHours.length` is expected to be true' +); -if (delete Date.prototype.getUTCHours.length !== true) { - throw new Test262Error('#1: The Date.prototype.getUTCHours.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getUTCHours.hasOwnProperty('length'), + 'The value of !Date.prototype.getUTCHours.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getUTCHours.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getUTCHours.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T3.js index 0c4c38ec02fb..d56f7edbef11 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCHours/S15.9.5.19_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutchours description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getUTCHours.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getUTCHours.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getUTCHours.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getUTCHours.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getUTCHours) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getUTCHours.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T1.js index 0cfcbf5c4a0c..d9028f85d45f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T1.js @@ -10,12 +10,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getUTCMilliseconds; -if (x === 1) +if (x === 1) { Date.prototype.getUTCMilliseconds = 2; -else +} else { Date.prototype.getUTCMilliseconds = 1; -if (Date.prototype.getUTCMilliseconds === x) { - throw new Test262Error('#1: The Date.prototype.getUTCMilliseconds has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getUTCMilliseconds, + x, + 'The value of Date.prototype.getUTCMilliseconds is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T2.js index 6a30f0354c7c..54830aa061bf 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutcmilliseconds description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getUTCMilliseconds, + false, + 'The value of delete Date.prototype.getUTCMilliseconds is not false' +); -if (delete Date.prototype.getUTCMilliseconds === false) { - throw new Test262Error('#1: The Date.prototype.getUTCMilliseconds property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getUTCMilliseconds'), + 'The value of !Date.prototype.hasOwnProperty(\'getUTCMilliseconds\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getUTCMilliseconds')) { - throw new Test262Error('#2: The Date.prototype.getUTCMilliseconds property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T3.js index 1b1ac5681a43..753702305782 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A1_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutcmilliseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getUTCMilliseconds')) { - throw new Test262Error('#1: The Date.prototype.getUTCMilliseconds property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getUTCMilliseconds'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getUTCMilliseconds\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getUTCMilliseconds") { - throw new Test262Error('#2: The Date.prototype.getUTCMilliseconds has the attribute DontEnum'); - } + assert.notSameValue(x, "getUTCMilliseconds", 'The value of x is not "getUTCMilliseconds"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A2_T1.js index 4c8fae14c217..6aca17be309c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getUTCMilliseconds" is 0 esid: sec-date.prototype.getutcmilliseconds description: The "length" property of the "getUTCMilliseconds" is 0 ---*/ +assert.sameValue( + Date.prototype.getUTCMilliseconds.hasOwnProperty("length"), + true, + 'Date.prototype.getUTCMilliseconds.hasOwnProperty("length") must return true' +); -if (Date.prototype.getUTCMilliseconds.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getUTCMilliseconds has a "length" property'); -} - -if (Date.prototype.getUTCMilliseconds.length !== 0) { - throw new Test262Error('#2: The "length" property of the getUTCMilliseconds is 0'); -} +assert.sameValue( + Date.prototype.getUTCMilliseconds.length, + 0, + 'The value of Date.prototype.getUTCMilliseconds.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T1.js index 7a9837d36449..751e632a3159 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getUTCMilliseconds.length; verifyNotWritable(Date.prototype.getUTCMilliseconds, "length", null, 1); -if (Date.prototype.getUTCMilliseconds.length !== x) { - throw new Test262Error('#1: The Date.prototype.getUTCMilliseconds.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getUTCMilliseconds.length, + x, + 'The value of Date.prototype.getUTCMilliseconds.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T2.js index 6655437c91f4..d04f69662d08 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutcmilliseconds description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getUTCMilliseconds.length, + true, + 'The value of `delete Date.prototype.getUTCMilliseconds.length` is expected to be true' +); -if (delete Date.prototype.getUTCMilliseconds.length !== true) { - throw new Test262Error('#1: The Date.prototype.getUTCMilliseconds.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getUTCMilliseconds.hasOwnProperty('length'), + 'The value of !Date.prototype.getUTCMilliseconds.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getUTCMilliseconds.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getUTCMilliseconds.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T3.js index 8f2bcdb6f0f4..6fb9ff17f22f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMilliseconds/S15.9.5.25_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutcmilliseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getUTCMilliseconds.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getUTCMilliseconds.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getUTCMilliseconds.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getUTCMilliseconds.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getUTCMilliseconds) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getUTCMilliseconds.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T1.js index 43f9636ef782..2f639c3cbbe5 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getUTCMinutes; -if (x === 1) +if (x === 1) { Date.prototype.getUTCMinutes = 2; -else +} else { Date.prototype.getUTCMinutes = 1; -if (Date.prototype.getUTCMinutes === x) { - throw new Test262Error('#1: The Date.prototype.getUTCMinutes has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getUTCMinutes, + x, + 'The value of Date.prototype.getUTCMinutes is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T2.js index 5a733745fc41..c49b894496aa 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "getUTCMinutes" has { DontEnum } attributes esid: sec-date.prototype.getutcminutes description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getUTCMinutes, + false, + 'The value of delete Date.prototype.getUTCMinutes is not false' +); -if (delete Date.prototype.getUTCMinutes === false) { - throw new Test262Error('#1: The Date.prototype.getUTCMinutes property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getUTCMinutes'), + 'The value of !Date.prototype.hasOwnProperty(\'getUTCMinutes\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getUTCMinutes')) { - throw new Test262Error('#2: The Date.prototype.getUTCMinutes property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T3.js index d995a0571de1..3d5acebb83e8 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getUTCMinutes" has { DontEnum } attributes esid: sec-date.prototype.getutcminutes description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getUTCMinutes')) { - throw new Test262Error('#1: The Date.prototype.getUTCMinutes property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getUTCMinutes'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getUTCMinutes\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getUTCMinutes") { - throw new Test262Error('#2: The Date.prototype.getUTCMinutes has the attribute DontEnum'); - } + assert.notSameValue(x, "getUTCMinutes", 'The value of x is not "getUTCMinutes"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A2_T1.js index 946bb6d84a05..0779033d4ca7 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getUTCMinutes" is 0 esid: sec-date.prototype.getutcminutes description: The "length" property of the "getUTCMinutes" is 0 ---*/ +assert.sameValue( + Date.prototype.getUTCMinutes.hasOwnProperty("length"), + true, + 'Date.prototype.getUTCMinutes.hasOwnProperty("length") must return true' +); -if (Date.prototype.getUTCMinutes.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getUTCMinutes has a "length" property'); -} - -if (Date.prototype.getUTCMinutes.length !== 0) { - throw new Test262Error('#2: The "length" property of the getUTCMinutes is 0'); -} +assert.sameValue( + Date.prototype.getUTCMinutes.length, + 0, + 'The value of Date.prototype.getUTCMinutes.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T1.js index dbf1a2bcbfc7..4c43a77de8d2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getUTCMinutes.length; verifyNotWritable(Date.prototype.getUTCMinutes, "length", null, 1); -if (Date.prototype.getUTCMinutes.length !== x) { - throw new Test262Error('#1: The Date.prototype.getUTCMinutes.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getUTCMinutes.length, + x, + 'The value of Date.prototype.getUTCMinutes.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T2.js index ec485789d27a..2c6a0ee7eef8 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutcminutes description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getUTCMinutes.length, + true, + 'The value of `delete Date.prototype.getUTCMinutes.length` is expected to be true' +); -if (delete Date.prototype.getUTCMinutes.length !== true) { - throw new Test262Error('#1: The Date.prototype.getUTCMinutes.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getUTCMinutes.hasOwnProperty('length'), + 'The value of !Date.prototype.getUTCMinutes.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getUTCMinutes.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getUTCMinutes.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T3.js index b5586cd77106..fc9ed2a7fb20 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMinutes/S15.9.5.21_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutcminutes description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getUTCMinutes.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getUTCMinutes.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getUTCMinutes.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getUTCMinutes.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getUTCMinutes) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getUTCMinutes.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T1.js index 01b81bec9b46..925d0587aba4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getUTCMonth; -if (x === 1) +if (x === 1) { Date.prototype.getUTCMonth = 2; -else +} else { Date.prototype.getUTCMonth = 1; -if (Date.prototype.getUTCMonth === x) { - throw new Test262Error('#1: The Date.prototype.getUTCMonth has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getUTCMonth, + x, + 'The value of Date.prototype.getUTCMonth is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T2.js index f4f0d60801c3..f5c1c1417063 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "getUTCMonth" has { DontEnum } attributes esid: sec-date.prototype.getutcmonth description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getUTCMonth, + false, + 'The value of delete Date.prototype.getUTCMonth is not false' +); -if (delete Date.prototype.getUTCMonth === false) { - throw new Test262Error('#1: The Date.prototype.getUTCMonth property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getUTCMonth'), + 'The value of !Date.prototype.hasOwnProperty(\'getUTCMonth\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getUTCMonth')) { - throw new Test262Error('#2: The Date.prototype.getUTCMonth property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T3.js index 7c30142eb133..472b1c1447f2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getUTCMonth" has { DontEnum } attributes esid: sec-date.prototype.getutcmonth description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getUTCMonth')) { - throw new Test262Error('#1: The Date.prototype.getUTCMonth property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getUTCMonth'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getUTCMonth\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getUTCMonth") { - throw new Test262Error('#2: The Date.prototype.getUTCMonth has the attribute DontEnum'); - } + assert.notSameValue(x, "getUTCMonth", 'The value of x is not "getUTCMonth"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A2_T1.js index 7d9c3ab39f61..4fb366a9dc45 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getUTCMonth" is 0 esid: sec-date.prototype.getutcmonth description: The "length" property of the "getUTCMonth" is 0 ---*/ +assert.sameValue( + Date.prototype.getUTCMonth.hasOwnProperty("length"), + true, + 'Date.prototype.getUTCMonth.hasOwnProperty("length") must return true' +); -if (Date.prototype.getUTCMonth.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getUTCMonth has a "length" property'); -} - -if (Date.prototype.getUTCMonth.length !== 0) { - throw new Test262Error('#2: The "length" property of the getUTCMonth is 0'); -} +assert.sameValue( + Date.prototype.getUTCMonth.length, + 0, + 'The value of Date.prototype.getUTCMonth.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T1.js index 5df0ddfd664c..9ddd5d2fa4a0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getUTCMonth.length; verifyNotWritable(Date.prototype.getUTCMonth, "length", null, 1); -if (Date.prototype.getUTCMonth.length !== x) { - throw new Test262Error('#1: The Date.prototype.getUTCMonth.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getUTCMonth.length, + x, + 'The value of Date.prototype.getUTCMonth.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T2.js index 9993c559145a..b712a583b9c4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutcmonth description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getUTCMonth.length, + true, + 'The value of `delete Date.prototype.getUTCMonth.length` is expected to be true' +); -if (delete Date.prototype.getUTCMonth.length !== true) { - throw new Test262Error('#1: The Date.prototype.getUTCMonth.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getUTCMonth.hasOwnProperty('length'), + 'The value of !Date.prototype.getUTCMonth.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getUTCMonth.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getUTCMonth.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T3.js index bb1e0a61b6ac..0d06b876dbeb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCMonth/S15.9.5.13_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutcmonth description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getUTCMonth.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getUTCMonth.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getUTCMonth.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getUTCMonth.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getUTCMonth) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getUTCMonth.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T1.js index 56418f1a6844..85b6e8fc612e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.getUTCSeconds; -if (x === 1) +if (x === 1) { Date.prototype.getUTCSeconds = 2; -else +} else { Date.prototype.getUTCSeconds = 1; -if (Date.prototype.getUTCSeconds === x) { - throw new Test262Error('#1: The Date.prototype.getUTCSeconds has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.getUTCSeconds, + x, + 'The value of Date.prototype.getUTCSeconds is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T2.js index 0f3e76e65c77..fb718d5d2c30 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "getUTCSeconds" has { DontEnum } attributes esid: sec-date.prototype.getutcseconds description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.getUTCSeconds, + false, + 'The value of delete Date.prototype.getUTCSeconds is not false' +); -if (delete Date.prototype.getUTCSeconds === false) { - throw new Test262Error('#1: The Date.prototype.getUTCSeconds property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('getUTCSeconds'), + 'The value of !Date.prototype.hasOwnProperty(\'getUTCSeconds\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('getUTCSeconds')) { - throw new Test262Error('#2: The Date.prototype.getUTCSeconds property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T3.js index 8e24028d612b..98e0d3a30237 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "getUTCSeconds" has { DontEnum } attributes esid: sec-date.prototype.getutcseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('getUTCSeconds')) { - throw new Test262Error('#1: The Date.prototype.getUTCSeconds property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('getUTCSeconds'), + 'The value of !Date.prototype.propertyIsEnumerable(\'getUTCSeconds\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "getUTCSeconds") { - throw new Test262Error('#2: The Date.prototype.getUTCSeconds has the attribute DontEnum'); - } + assert.notSameValue(x, "getUTCSeconds", 'The value of x is not "getUTCSeconds"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A2_T1.js index 2dbd43b4142c..ab2c4c4c935a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "getUTCSeconds" is 0 esid: sec-date.prototype.getutcseconds description: The "length" property of the "getUTCSeconds" is 0 ---*/ +assert.sameValue( + Date.prototype.getUTCSeconds.hasOwnProperty("length"), + true, + 'Date.prototype.getUTCSeconds.hasOwnProperty("length") must return true' +); -if (Date.prototype.getUTCSeconds.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The getUTCSeconds has a "length" property'); -} - -if (Date.prototype.getUTCSeconds.length !== 0) { - throw new Test262Error('#2: The "length" property of the getUTCSeconds is 0'); -} +assert.sameValue( + Date.prototype.getUTCSeconds.length, + 0, + 'The value of Date.prototype.getUTCSeconds.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T1.js index 2ffc345f7408..fdce7234f67e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.getUTCSeconds.length; verifyNotWritable(Date.prototype.getUTCSeconds, "length", null, 1); -if (Date.prototype.getUTCSeconds.length !== x) { - throw new Test262Error('#1: The Date.prototype.getUTCSeconds.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.getUTCSeconds.length, + x, + 'The value of Date.prototype.getUTCSeconds.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T2.js index 0efae11b6248..45a794334f8b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.getutcseconds description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.getUTCSeconds.length, + true, + 'The value of `delete Date.prototype.getUTCSeconds.length` is expected to be true' +); -if (delete Date.prototype.getUTCSeconds.length !== true) { - throw new Test262Error('#1: The Date.prototype.getUTCSeconds.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.getUTCSeconds.hasOwnProperty('length'), + 'The value of !Date.prototype.getUTCSeconds.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.getUTCSeconds.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.getUTCSeconds.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T3.js index 5606e8b12037..fc43b2b26683 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/getUTCSeconds/S15.9.5.23_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.getutcseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.getUTCSeconds.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.getUTCSeconds.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.getUTCSeconds.propertyIsEnumerable('length'), + 'The value of !Date.prototype.getUTCSeconds.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.getUTCSeconds) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.getUTCSeconds.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T1.js index 8b96b7b1a042..801ffd0e1782 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setDate; -if (x === 1) +if (x === 1) { Date.prototype.setDate = 2; -else +} else { Date.prototype.setDate = 1; -if (Date.prototype.setDate === x) { - throw new Test262Error('#1: The Date.prototype.setDate has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setDate, + x, + 'The value of Date.prototype.setDate is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T2.js index da104686e1c4..d0ad33c7de4a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T2.js @@ -6,13 +6,13 @@ info: The Date.prototype property "setDate" has { DontEnum } attributes esid: sec-date.prototype.setdate description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.setDate, false, 'The value of delete Date.prototype.setDate is not false'); -if (delete Date.prototype.setDate === false) { - throw new Test262Error('#1: The Date.prototype.setDate property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setDate'), + 'The value of !Date.prototype.hasOwnProperty(\'setDate\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setDate')) { - throw new Test262Error('#2: The Date.prototype.setDate property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T3.js index 68b58d995a29..f6f9ffd9303a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setDate" has { DontEnum } attributes esid: sec-date.prototype.setdate description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setDate')) { - throw new Test262Error('#1: The Date.prototype.setDate property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setDate'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setDate\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setDate") { - throw new Test262Error('#2: The Date.prototype.setDate has the attribute DontEnum'); - } + assert.notSameValue(x, "setDate", 'The value of x is not "setDate"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A2_T1.js index 8e1c29d99884..a54d6a167d27 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A2_T1.js @@ -6,13 +6,12 @@ info: The "length" property of the "setDate" is 1 esid: sec-date.prototype.setdate description: The "length" property of the "setDate" is 1 ---*/ +assert.sameValue( + Date.prototype.setDate.hasOwnProperty("length"), + true, + 'Date.prototype.setDate.hasOwnProperty("length") must return true' +); -if (Date.prototype.setDate.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setDate has a "length" property'); -} - -if (Date.prototype.setDate.length !== 1) { - throw new Test262Error('#2: The "length" property of the setDate is 1'); -} +assert.sameValue(Date.prototype.setDate.length, 1, 'The value of Date.prototype.setDate.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T1.js index 3ef191df1f21..97e9613bb6d2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setDate.length; verifyNotWritable(Date.prototype.setDate, "length", null, 1); -if (Date.prototype.setDate.length !== x) { - throw new Test262Error('#1: The Date.prototype.setDate.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setDate.length, + x, + 'The value of Date.prototype.setDate.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T2.js index a70639c31016..5b82b4c5d254 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setdate description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setDate.length, + true, + 'The value of `delete Date.prototype.setDate.length` is expected to be true' +); -if (delete Date.prototype.setDate.length !== true) { - throw new Test262Error('#1: The Date.prototype.setDate.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setDate.hasOwnProperty('length'), + 'The value of !Date.prototype.setDate.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setDate.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setDate.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T3.js index 1fd1b3f1bc41..7bc1624b0bc1 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setDate/S15.9.5.36_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setdate description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setDate.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setDate.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setDate.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setDate.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setDate) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setDate.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setDate/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setDate/arg-coercion-order.js new file mode 100644 index 000000000000..094bec44543f --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setDate/arg-coercion-order.js @@ -0,0 +1,32 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setdate +description: Order of coercion of provided argument vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let dt be ? ToNumber(date). + 3. If t is NaN, return NaN. + 4. Set t to LocalTime(t). + 5. Let newDate be MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)). + 6. Let u be TimeClip(UTC(newDate)). + 7. Set the [[DateValue]] internal slot of this Date object to u. + 8. Return u. +---*/ + +var date = new Date(NaN); +var callCount = 0; +var arg = { + valueOf: function() { + callCount += 1; + return 0; + } +}; + +var returnValue = date.setDate(arg); + +assert.sameValue(callCount, 1, 'ToNumber invoked exactly once'); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T1.js index 110f9d2d5829..b958ff7ac00a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setFullYear; -if (x === 1) +if (x === 1) { Date.prototype.setFullYear = 2; -else +} else { Date.prototype.setFullYear = 1; -if (Date.prototype.setFullYear === x) { - throw new Test262Error('#1: The Date.prototype.setFullYear has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setFullYear, + x, + 'The value of Date.prototype.setFullYear is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T2.js index 0c99a942a207..ac18a41d6f07 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setFullYear" has { DontEnum } attributes esid: sec-date.prototype.setfullyear description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setFullYear, + false, + 'The value of delete Date.prototype.setFullYear is not false' +); -if (delete Date.prototype.setFullYear === false) { - throw new Test262Error('#1: The Date.prototype.setFullYear property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setFullYear'), + 'The value of !Date.prototype.hasOwnProperty(\'setFullYear\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setFullYear')) { - throw new Test262Error('#2: The Date.prototype.setFullYear property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T3.js index d1572fe6306c..f342b5755082 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setFullYear" has { DontEnum } attributes esid: sec-date.prototype.setfullyear description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setFullYear')) { - throw new Test262Error('#1: The Date.prototype.setFullYear property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setFullYear'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setFullYear\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setFullYear") { - throw new Test262Error('#2: The Date.prototype.setFullYear has the attribute DontEnum'); - } + assert.notSameValue(x, "setFullYear", 'The value of x is not "setFullYear"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A2_T1.js index a4e5edf3696a..f7f92225f75c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setFullYear" is 3 esid: sec-date.prototype.setfullyear description: The "length" property of the "setFullYear" is 3 ---*/ +assert.sameValue( + Date.prototype.setFullYear.hasOwnProperty("length"), + true, + 'Date.prototype.setFullYear.hasOwnProperty("length") must return true' +); -if (Date.prototype.setFullYear.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setFullYear has a "length" property'); -} - -if (Date.prototype.setFullYear.length !== 3) { - throw new Test262Error('#2: The "length" property of the setFullYear is 3'); -} +assert.sameValue( + Date.prototype.setFullYear.length, + 3, + 'The value of Date.prototype.setFullYear.length is expected to be 3' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T1.js index cf374fb191cd..9f8c4bf99c4d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setFullYear.length; verifyNotWritable(Date.prototype.setFullYear, "length", null, 1); -if (Date.prototype.setFullYear.length !== x) { - throw new Test262Error('#1: The Date.prototype.setFullYear.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setFullYear.length, + x, + 'The value of Date.prototype.setFullYear.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T2.js index 37dda4a88fe4..562b430dcfd1 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setfullyear description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setFullYear.length, + true, + 'The value of `delete Date.prototype.setFullYear.length` is expected to be true' +); -if (delete Date.prototype.setFullYear.length !== true) { - throw new Test262Error('#1: The Date.prototype.setFullYear.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setFullYear.hasOwnProperty('length'), + 'The value of !Date.prototype.setFullYear.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setFullYear.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setFullYear.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T3.js index 8c8133fe7df3..707623ba5171 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setFullYear/S15.9.5.40_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setfullyear description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setFullYear.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setFullYear.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setFullYear.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setFullYear.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setFullYear) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setFullYear.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T1.js index 98372745e215..522a7a554a89 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setHours; -if (x === 1) +if (x === 1) { Date.prototype.setHours = 2; -else +} else { Date.prototype.setHours = 1; -if (Date.prototype.setHours === x) { - throw new Test262Error('#1: The Date.prototype.setHours has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setHours, + x, + 'The value of Date.prototype.setHours is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T2.js index beb88d7587ee..6cf45d93cdb6 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T2.js @@ -6,13 +6,13 @@ info: The Date.prototype property "setHours" has { DontEnum } attributes esid: sec-date.prototype.sethours description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.setHours, false, 'The value of delete Date.prototype.setHours is not false'); -if (delete Date.prototype.setHours === false) { - throw new Test262Error('#1: The Date.prototype.setHours property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setHours'), + 'The value of !Date.prototype.hasOwnProperty(\'setHours\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setHours')) { - throw new Test262Error('#2: The Date.prototype.setHours property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T3.js index 44fdba2927ac..7211067494c8 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setHours" has { DontEnum } attributes esid: sec-date.prototype.sethours description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setHours')) { - throw new Test262Error('#1: The Date.prototype.setHours property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setHours'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setHours\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setHours") { - throw new Test262Error('#2: The Date.prototype.setHours has the attribute DontEnum'); - } + assert.notSameValue(x, "setHours", 'The value of x is not "setHours"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A2_T1.js index 310e051af4c5..ccdabfa8fc27 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A2_T1.js @@ -6,13 +6,12 @@ info: The "length" property of the "setHours" is 4 esid: sec-date.prototype.sethours description: The "length" property of the "setHours" is 4 ---*/ +assert.sameValue( + Date.prototype.setHours.hasOwnProperty("length"), + true, + 'Date.prototype.setHours.hasOwnProperty("length") must return true' +); -if (Date.prototype.setHours.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setHours has a "length" property'); -} - -if (Date.prototype.setHours.length !== 4) { - throw new Test262Error('#2: The "length" property of the setHours is 4'); -} +assert.sameValue(Date.prototype.setHours.length, 4, 'The value of Date.prototype.setHours.length is expected to be 4'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T1.js index bf61d566a937..9d5b7750df5e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setHours.length; verifyNotWritable(Date.prototype.setHours, "length", null, 1); -if (Date.prototype.setHours.length !== x) { - throw new Test262Error('#1: The Date.prototype.setHours.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setHours.length, + x, + 'The value of Date.prototype.setHours.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T2.js index de5435c587af..ac6a60cf7d9c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.sethours description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setHours.length, + true, + 'The value of `delete Date.prototype.setHours.length` is expected to be true' +); -if (delete Date.prototype.setHours.length !== true) { - throw new Test262Error('#1: The Date.prototype.setHours.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setHours.hasOwnProperty('length'), + 'The value of !Date.prototype.setHours.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setHours.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setHours.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T3.js index 919752374815..5b7172510ace 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setHours/S15.9.5.34_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.sethours description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setHours.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setHours.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setHours.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setHours.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setHours) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setHours.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setHours/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setHours/arg-coercion-order.js new file mode 100644 index 000000000000..48bd2590794d --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setHours/arg-coercion-order.js @@ -0,0 +1,59 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.sethours +description: Order of coercion of provided arguments vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let h be ? ToNumber(hour). + 3. If min is present, let m be ? ToNumber(min). + 4. If sec is present, let s be ? ToNumber(sec). + 5. If ms is present, let milli be ? ToNumber(ms). + 6. If t is NaN, return NaN. + 7. Set t to LocalTime(t). + 8. If min is not present, let m be MinFromTime(t). + 9. If sec is not present, let s be SecFromTime(t). + 10. If ms is not present, let milli be msFromTime(t). + 11. Let date be MakeDate(Day(t), MakeTime(h, m, s, milli)). + 12. Let u be TimeClip(UTC(date)). + 13. Set the [[DateValue]] internal slot of this Date object to u. + 14. Return u. +includes: [compareArray.js] +---*/ + +var date = new Date(NaN); +var effects = []; +var argHour = { + valueOf: function() { + effects.push('valueOf hour'); + return 0; + } +}; +var argMin = { + valueOf: function() { + effects.push('valueOf min'); + return 0; + } +}; +var argSec = { + valueOf: function() { + effects.push('valueOf sec'); + return 0; + } +}; +var argMs = { + valueOf: function() { + effects.push('valueOf ms'); + return 0; + } +}; + +var returnValue = date.setHours(argHour, argMin, argSec, argMs); + +var expectedEffects = ['valueOf hour', 'valueOf min', 'valueOf sec', 'valueOf ms']; + +assert.compareArray(effects, expectedEffects); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T1.js index 6fd48cbbc3e6..abd7ac57a323 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setMilliseconds; -if (x === 1) +if (x === 1) { Date.prototype.setMilliseconds = 2; -else +} else { Date.prototype.setMilliseconds = 1; -if (Date.prototype.setMilliseconds === x) { - throw new Test262Error('#1: The Date.prototype.setMilliseconds has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setMilliseconds, + x, + 'The value of Date.prototype.setMilliseconds is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T2.js index ad14bd9f9573..3352f8071e28 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setMilliseconds" has { DontEnum } attributes esid: sec-date.prototype.setmilliseconds description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setMilliseconds, + false, + 'The value of delete Date.prototype.setMilliseconds is not false' +); -if (delete Date.prototype.setMilliseconds === false) { - throw new Test262Error('#1: The Date.prototype.setMilliseconds property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setMilliseconds'), + 'The value of !Date.prototype.hasOwnProperty(\'setMilliseconds\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setMilliseconds')) { - throw new Test262Error('#2: The Date.prototype.setMilliseconds property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T3.js index 33c644d43bd7..e058353e2a44 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setMilliseconds" has { DontEnum } attributes esid: sec-date.prototype.setmilliseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setMilliseconds')) { - throw new Test262Error('#1: The Date.prototype.setMilliseconds property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setMilliseconds'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setMilliseconds\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setMilliseconds") { - throw new Test262Error('#2: The Date.prototype.setMilliseconds has the attribute DontEnum'); - } + assert.notSameValue(x, "setMilliseconds", 'The value of x is not "setMilliseconds"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A2_T1.js index 92e6a675af2e..345a10bbd4ed 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setMilliseconds" is 1 esid: sec-date.prototype.setmilliseconds description: The "length" property of the "setMilliseconds" is 1 ---*/ +assert.sameValue( + Date.prototype.setMilliseconds.hasOwnProperty("length"), + true, + 'Date.prototype.setMilliseconds.hasOwnProperty("length") must return true' +); -if (Date.prototype.setMilliseconds.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setMilliseconds has a "length" property'); -} - -if (Date.prototype.setMilliseconds.length !== 1) { - throw new Test262Error('#2: The "length" property of the setMilliseconds is 1'); -} +assert.sameValue( + Date.prototype.setMilliseconds.length, + 1, + 'The value of Date.prototype.setMilliseconds.length is expected to be 1' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T1.js index d4b006a06055..f8f2f3478b68 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setMilliseconds.length; verifyNotWritable(Date.prototype.setMilliseconds, "length", null, 1); -if (Date.prototype.setMilliseconds.length !== x) { - throw new Test262Error('#1: The Date.prototype.setMilliseconds.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setMilliseconds.length, + x, + 'The value of Date.prototype.setMilliseconds.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T2.js index 8eca045bb875..fc4b43d39dfe 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setmilliseconds description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setMilliseconds.length, + true, + 'The value of `delete Date.prototype.setMilliseconds.length` is expected to be true' +); -if (delete Date.prototype.setMilliseconds.length !== true) { - throw new Test262Error('#1: The Date.prototype.setMilliseconds.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setMilliseconds.hasOwnProperty('length'), + 'The value of !Date.prototype.setMilliseconds.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setMilliseconds.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setMilliseconds.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T3.js index 7f9b5fd9c60b..9e15b794be27 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/S15.9.5.28_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setmilliseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setMilliseconds.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setMilliseconds.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setMilliseconds.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setMilliseconds.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setMilliseconds) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setMilliseconds.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/arg-coercion-order.js new file mode 100644 index 000000000000..38384ec1b188 --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setMilliseconds/arg-coercion-order.js @@ -0,0 +1,32 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setmilliseconds +description: Order of coercion of provided argument vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Set ms to ? ToNumber(ms). + 3. If t is NaN, return NaN. + 4. Set t to LocalTime(t). + 5. Let time be MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms). + 6. Let u be TimeClip(UTC(MakeDate(Day(t), time))). + 7. Set the [[DateValue]] internal slot of this Date object to u. + 8. Return u. +---*/ + +var date = new Date(NaN); +var callCount = 0; +var arg = { + valueOf: function() { + callCount += 1; + return 0; + } +}; + +var returnValue = date.setMilliseconds(arg); + +assert.sameValue(callCount, 1, 'ToNumber invoked exactly once'); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T1.js index 4fd6098d4b0a..495135965b62 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setMinutes; -if (x === 1) +if (x === 1) { Date.prototype.setMinutes = 2; -else +} else { Date.prototype.setMinutes = 1; -if (Date.prototype.setMinutes === x) { - throw new Test262Error('#1: The Date.prototype.setMinutes has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setMinutes, + x, + 'The value of Date.prototype.setMinutes is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T2.js index 52b586bc8e8b..3cc72be7275d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setMinutes" has { DontEnum } attributes esid: sec-date.prototype.setminutes description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setMinutes, + false, + 'The value of delete Date.prototype.setMinutes is not false' +); -if (delete Date.prototype.setMinutes === false) { - throw new Test262Error('#1: The Date.prototype.setMinutes property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setMinutes'), + 'The value of !Date.prototype.hasOwnProperty(\'setMinutes\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setMinutes')) { - throw new Test262Error('#2: The Date.prototype.setMinutes property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T3.js index 04eaa1383148..61eba85e1a29 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setMinutes" has { DontEnum } attributes esid: sec-date.prototype.setminutes description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setMinutes')) { - throw new Test262Error('#1: The Date.prototype.setMinutes property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setMinutes'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setMinutes\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setMinutes") { - throw new Test262Error('#2: The Date.prototype.setMinutes has the attribute DontEnum'); - } + assert.notSameValue(x, "setMinutes", 'The value of x is not "setMinutes"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A2_T1.js index 05249fc5ae50..e95e992ab107 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setMinutes" is 3 esid: sec-date.prototype.setminutes description: The "length" property of the "setMinutes" is 3 ---*/ +assert.sameValue( + Date.prototype.setMinutes.hasOwnProperty("length"), + true, + 'Date.prototype.setMinutes.hasOwnProperty("length") must return true' +); -if (Date.prototype.setMinutes.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setMinutes has a "length" property'); -} - -if (Date.prototype.setMinutes.length !== 3) { - throw new Test262Error('#2: The "length" property of the setMinutes is 3'); -} +assert.sameValue( + Date.prototype.setMinutes.length, + 3, + 'The value of Date.prototype.setMinutes.length is expected to be 3' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T1.js index f0d744289760..2224b138ad64 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setMinutes.length; verifyNotWritable(Date.prototype.setMinutes, "length", null, 1); -if (Date.prototype.setMinutes.length !== x) { - throw new Test262Error('#1: The Date.prototype.setMinutes.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setMinutes.length, + x, + 'The value of Date.prototype.setMinutes.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T2.js index 28ec3a838458..d9a4a750867d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setminutes description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setMinutes.length, + true, + 'The value of `delete Date.prototype.setMinutes.length` is expected to be true' +); -if (delete Date.prototype.setMinutes.length !== true) { - throw new Test262Error('#1: The Date.prototype.setMinutes.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setMinutes.hasOwnProperty('length'), + 'The value of !Date.prototype.setMinutes.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setMinutes.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setMinutes.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T3.js index 8795e166994e..1380f4e35b76 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/S15.9.5.32_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setminutes description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setMinutes.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setMinutes.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setMinutes.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setMinutes.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setMinutes) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setMinutes.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMinutes/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/arg-coercion-order.js new file mode 100644 index 000000000000..50d81c114f89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setMinutes/arg-coercion-order.js @@ -0,0 +1,51 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setminutes +description: Order of coercion of provided argument vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let m be ? ToNumber(min). + 3. If sec is present, let s be ? ToNumber(sec). + 4. If ms is present, let milli be ? ToNumber(ms). + 5. If t is NaN, return NaN. + 6. Set t to LocalTime(t). + 7. If sec is not present, let s be SecFromTime(t). + 8. If ms is not present, let milli be msFromTime(t). + 9. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)). + 10. Let u be TimeClip(UTC(date)). + 11. Set the [[DateValue]] internal slot of this Date object to u. + 12. Return u. +includes: [compareArray.js] +---*/ + +var date = new Date(NaN); +var effects = []; +var argMin = { + valueOf: function() { + effects.push('valueOf min'); + return 0; + } +}; +var argSec = { + valueOf: function() { + effects.push('valueOf sec'); + return 0; + } +}; +var argMs = { + valueOf: function() { + effects.push('valueOf ms'); + return 0; + } +}; + +var returnValue = date.setMinutes(argMin, argSec, argMs); + +var expectedEffects = ['valueOf min', 'valueOf sec', 'valueOf ms']; + +assert.compareArray(effects, expectedEffects); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T1.js index fc1c2fd32e5c..ac3d594ccb04 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setMonth; -if (x === 1) +if (x === 1) { Date.prototype.setMonth = 2; -else +} else { Date.prototype.setMonth = 1; -if (Date.prototype.setMonth === x) { - throw new Test262Error('#1: The Date.prototype.setMonth has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setMonth, + x, + 'The value of Date.prototype.setMonth is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T2.js index 5494772c3164..492b1be5cd04 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T2.js @@ -6,13 +6,13 @@ info: The Date.prototype property "setMonth" has { DontEnum } attributes esid: sec-date.prototype.setmonth description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.setMonth, false, 'The value of delete Date.prototype.setMonth is not false'); -if (delete Date.prototype.setMonth === false) { - throw new Test262Error('#1: The Date.prototype.setMonth property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setMonth'), + 'The value of !Date.prototype.hasOwnProperty(\'setMonth\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setMonth')) { - throw new Test262Error('#2: The Date.prototype.setMonth property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T3.js index f074815223da..22d2585a7c39 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setMonth" has { DontEnum } attributes esid: sec-date.prototype.setmonth description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setMonth')) { - throw new Test262Error('#1: The Date.prototype.setMonth property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setMonth'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setMonth\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setMonth") { - throw new Test262Error('#2: The Date.prototype.setMonth has the attribute DontEnum'); - } + assert.notSameValue(x, "setMonth", 'The value of x is not "setMonth"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A2_T1.js index 57f5fde1ce18..ed5846befa50 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A2_T1.js @@ -6,13 +6,12 @@ info: The "length" property of the "setMonth" is 2 esid: sec-date.prototype.setmonth description: The "length" property of the "setMonth" is 2 ---*/ +assert.sameValue( + Date.prototype.setMonth.hasOwnProperty("length"), + true, + 'Date.prototype.setMonth.hasOwnProperty("length") must return true' +); -if (Date.prototype.setMonth.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setMonth has a "length" property'); -} - -if (Date.prototype.setMonth.length !== 2) { - throw new Test262Error('#2: The "length" property of the setMonth is 2'); -} +assert.sameValue(Date.prototype.setMonth.length, 2, 'The value of Date.prototype.setMonth.length is expected to be 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T1.js index 65ccaa6754fa..f6c45f61ef50 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setMonth.length; verifyNotWritable(Date.prototype.setMonth, "length", null, 1); -if (Date.prototype.setMonth.length !== x) { - throw new Test262Error('#1: The Date.prototype.setMonth.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setMonth.length, + x, + 'The value of Date.prototype.setMonth.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T2.js index 4c25a98ddfb7..9238a8ed74d7 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setmonth description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setMonth.length, + true, + 'The value of `delete Date.prototype.setMonth.length` is expected to be true' +); -if (delete Date.prototype.setMonth.length !== true) { - throw new Test262Error('#1: The Date.prototype.setMonth.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setMonth.hasOwnProperty('length'), + 'The value of !Date.prototype.setMonth.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setMonth.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setMonth.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T3.js index 772c26ae1bec..23f188833162 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setMonth/S15.9.5.38_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setmonth description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setMonth.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setMonth.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setMonth.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setMonth.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setMonth) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setMonth.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setMonth/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setMonth/arg-coercion-order.js new file mode 100644 index 000000000000..a1bc3862afae --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setMonth/arg-coercion-order.js @@ -0,0 +1,43 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setmonth +description: Order of coercion of provided argument vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let m be ? ToNumber(month). + 3. If date is present, let dt be ? ToNumber(date). + 4. If t is NaN, return NaN. + 5. Set t to LocalTime(t). + 6. If date is not present, let dt be DateFromTime(t). + 7. Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)). + 8. Let u be TimeClip(UTC(newDate)). + 9. Set the [[DateValue]] internal slot of this Date object to u. + 10. Return u. +includes: [compareArray.js] +---*/ + +var date = new Date(NaN); +var effects = []; +var argMonth = { + valueOf: function() { + effects.push('valueOf month'); + return 0; + } +}; +var argDate = { + valueOf: function() { + effects.push('valueOf date'); + return 0; + } +}; + +var returnValue = date.setMonth(argMonth, argDate); + +var expectedEffects = ['valueOf month', 'valueOf date']; + +assert.compareArray(effects, expectedEffects); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T1.js index 4f7eed7a431b..80cacf2f6a63 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setSeconds; -if (x === 1) +if (x === 1) { Date.prototype.setSeconds = 2; -else +} else { Date.prototype.setSeconds = 1; -if (Date.prototype.setSeconds === x) { - throw new Test262Error('#1: The Date.prototype.setSeconds has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setSeconds, + x, + 'The value of Date.prototype.setSeconds is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T2.js index 8a8b00e7e9d7..8d6c81ce9a3b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setSeconds" has { DontEnum } attributes esid: sec-date.prototype.setseconds description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setSeconds, + false, + 'The value of delete Date.prototype.setSeconds is not false' +); -if (delete Date.prototype.setSeconds === false) { - throw new Test262Error('#1: The Date.prototype.setSeconds property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setSeconds'), + 'The value of !Date.prototype.hasOwnProperty(\'setSeconds\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setSeconds')) { - throw new Test262Error('#2: The Date.prototype.setSeconds property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T3.js index 92cd07c7ba86..0692617eb2f5 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setSeconds" has { DontEnum } attributes esid: sec-date.prototype.setseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setSeconds')) { - throw new Test262Error('#1: The Date.prototype.setSeconds property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setSeconds'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setSeconds\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setSeconds") { - throw new Test262Error('#2: The Date.prototype.setSeconds has the attribute DontEnum'); - } + assert.notSameValue(x, "setSeconds", 'The value of x is not "setSeconds"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A2_T1.js index 33192076a886..dcac968a56a1 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setSeconds" is 2 esid: sec-date.prototype.setseconds description: The "length" property of the "setSeconds" is 2 ---*/ +assert.sameValue( + Date.prototype.setSeconds.hasOwnProperty("length"), + true, + 'Date.prototype.setSeconds.hasOwnProperty("length") must return true' +); -if (Date.prototype.setSeconds.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setSeconds has a "length" property'); -} - -if (Date.prototype.setSeconds.length !== 2) { - throw new Test262Error('#2: The "length" property of the setSeconds is 2'); -} +assert.sameValue( + Date.prototype.setSeconds.length, + 2, + 'The value of Date.prototype.setSeconds.length is expected to be 2' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T1.js index 5d2ddd78d04f..5a240eca987a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setSeconds.length; verifyNotWritable(Date.prototype.setSeconds, "length", null, 1); -if (Date.prototype.setSeconds.length !== x) { - throw new Test262Error('#1: The Date.prototype.setSeconds.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setSeconds.length, + x, + 'The value of Date.prototype.setSeconds.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T2.js index 8d39f0d4287f..789bca4e48b7 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setseconds description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setSeconds.length, + true, + 'The value of `delete Date.prototype.setSeconds.length` is expected to be true' +); -if (delete Date.prototype.setSeconds.length !== true) { - throw new Test262Error('#1: The Date.prototype.setSeconds.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setSeconds.hasOwnProperty('length'), + 'The value of !Date.prototype.setSeconds.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setSeconds.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setSeconds.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T3.js index d8327454fe69..80e814d9dd83 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/S15.9.5.30_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setSeconds.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setSeconds.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setSeconds.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setSeconds.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setSeconds) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setSeconds.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setSeconds/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/arg-coercion-order.js new file mode 100644 index 000000000000..1cbc4420c4db --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setSeconds/arg-coercion-order.js @@ -0,0 +1,43 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setseconds +description: Order of coercion of provided arguments vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let s be ? ToNumber(sec). + 3. If ms is present, let milli be ? ToNumber(ms). + 4. If t is NaN, return NaN. + 5. Set t to LocalTime(t). + 6. If ms is not present, let milli be msFromTime(t). + 7. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)). + 8. Let u be TimeClip(UTC(date)). + 9. Set the [[DateValue]] internal slot of this Date object to u. + 10. Return u. +includes: [compareArray.js] +---*/ + +var date = new Date(NaN); +var effects = []; +var argSec = { + valueOf: function() { + effects.push('valueOf sec'); + return 0; + } +}; +var argMs = { + valueOf: function() { + effects.push('valueOf ms'); + return 0; + } +}; + +var returnValue = date.setSeconds(argSec, argMs); + +var expectedEffects = ['valueOf sec', 'valueOf ms']; + +assert.compareArray(effects, expectedEffects); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T1.js index 1880729820ee..cdd891deaccc 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setTime; -if (x === 1) +if (x === 1) { Date.prototype.setTime = 2; -else +} else { Date.prototype.setTime = 1; -if (Date.prototype.setTime === x) { - throw new Test262Error('#1: The Date.prototype.setTime has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setTime, + x, + 'The value of Date.prototype.setTime is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T2.js index 6a4127a91bb6..3d425994ab59 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T2.js @@ -6,13 +6,13 @@ info: The Date.prototype property "setTime" has { DontEnum } attributes esid: sec-date.prototype.settime description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue(delete Date.prototype.setTime, false, 'The value of delete Date.prototype.setTime is not false'); -if (delete Date.prototype.setTime === false) { - throw new Test262Error('#1: The Date.prototype.setTime property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setTime'), + 'The value of !Date.prototype.hasOwnProperty(\'setTime\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setTime')) { - throw new Test262Error('#2: The Date.prototype.setTime property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T3.js index 2060d258a2e0..78164e813d41 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setTime" has { DontEnum } attributes esid: sec-date.prototype.settime description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setTime')) { - throw new Test262Error('#1: The Date.prototype.setTime property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setTime'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setTime\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setTime") { - throw new Test262Error('#2: The Date.prototype.setTime has the attribute DontEnum'); - } + assert.notSameValue(x, "setTime", 'The value of x is not "setTime"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A2_T1.js index 558e00e2bd82..a4fa4209a2b2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A2_T1.js @@ -6,13 +6,12 @@ info: The "length" property of the "setTime" is 1 esid: sec-date.prototype.settime description: The "length" property of the "setTime" is 1 ---*/ +assert.sameValue( + Date.prototype.setTime.hasOwnProperty("length"), + true, + 'Date.prototype.setTime.hasOwnProperty("length") must return true' +); -if (Date.prototype.setTime.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setTime has a "length" property'); -} - -if (Date.prototype.setTime.length !== 1) { - throw new Test262Error('#2: The "length" property of the setTime is 1'); -} +assert.sameValue(Date.prototype.setTime.length, 1, 'The value of Date.prototype.setTime.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T1.js index d315efe03e10..4ef36f2f25ee 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setTime.length; verifyNotWritable(Date.prototype.setTime, "length", null, 1); -if (Date.prototype.setTime.length !== x) { - throw new Test262Error('#1: The Date.prototype.setTime.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setTime.length, + x, + 'The value of Date.prototype.setTime.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T2.js index 3b92fe46e565..b66fe9c598b5 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.settime description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setTime.length, + true, + 'The value of `delete Date.prototype.setTime.length` is expected to be true' +); -if (delete Date.prototype.setTime.length !== true) { - throw new Test262Error('#1: The Date.prototype.setTime.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setTime.hasOwnProperty('length'), + 'The value of !Date.prototype.setTime.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setTime.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setTime.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T3.js index 1058b7532e02..9a6bd16d4ccb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setTime/S15.9.5.27_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.settime description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setTime.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setTime.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setTime.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setTime.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setTime) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setTime.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T1.js index 4b1c270f4a77..0ea87161251f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setUTCDate; -if (x === 1) +if (x === 1) { Date.prototype.setUTCDate = 2; -else +} else { Date.prototype.setUTCDate = 1; -if (Date.prototype.setUTCDate === x) { - throw new Test262Error('#1: The Date.prototype.setUTCDate has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setUTCDate, + x, + 'The value of Date.prototype.setUTCDate is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T2.js index 98f4ebcfffbd..84187b61d6be 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setUTCDate" has { DontEnum } attributes esid: sec-date.prototype.setutcdate description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setUTCDate, + false, + 'The value of delete Date.prototype.setUTCDate is not false' +); -if (delete Date.prototype.setUTCDate === false) { - throw new Test262Error('#1: The Date.prototype.setUTCDate property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setUTCDate'), + 'The value of !Date.prototype.hasOwnProperty(\'setUTCDate\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setUTCDate')) { - throw new Test262Error('#2: The Date.prototype.setUTCDate property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T3.js index 27702efcd2f9..e2085634a80b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setUTCDate" has { DontEnum } attributes esid: sec-date.prototype.setutcdate description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setUTCDate')) { - throw new Test262Error('#1: The Date.prototype.setUTCDate property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setUTCDate'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setUTCDate\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setUTCDate") { - throw new Test262Error('#2: The Date.prototype.setUTCDate has the attribute DontEnum'); - } + assert.notSameValue(x, "setUTCDate", 'The value of x is not "setUTCDate"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A2_T1.js index 7c3cda280ccc..0d7c6f5d1119 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setUTCDate" is 1 esid: sec-date.prototype.setutcdate description: The "length" property of the "setUTCDate" is 1 ---*/ +assert.sameValue( + Date.prototype.setUTCDate.hasOwnProperty("length"), + true, + 'Date.prototype.setUTCDate.hasOwnProperty("length") must return true' +); -if (Date.prototype.setUTCDate.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setUTCDate has a "length" property'); -} - -if (Date.prototype.setUTCDate.length !== 1) { - throw new Test262Error('#2: The "length" property of the setUTCDate is 1'); -} +assert.sameValue( + Date.prototype.setUTCDate.length, + 1, + 'The value of Date.prototype.setUTCDate.length is expected to be 1' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T1.js index be10cd49a26b..4ec596966b33 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setUTCDate.length; verifyNotWritable(Date.prototype.setUTCDate, "length", null, 1); -if (Date.prototype.setUTCDate.length !== x) { - throw new Test262Error('#1: The Date.prototype.setUTCDate.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setUTCDate.length, + x, + 'The value of Date.prototype.setUTCDate.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T2.js index e874e477513e..c171c07dc98e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setutcdate description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setUTCDate.length, + true, + 'The value of `delete Date.prototype.setUTCDate.length` is expected to be true' +); -if (delete Date.prototype.setUTCDate.length !== true) { - throw new Test262Error('#1: The Date.prototype.setUTCDate.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setUTCDate.hasOwnProperty('length'), + 'The value of !Date.prototype.setUTCDate.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setUTCDate.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setUTCDate.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T3.js index 9c2c0429e07f..9e4fd50ded35 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/S15.9.5.37_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setutcdate description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setUTCDate.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setUTCDate.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setUTCDate.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setUTCDate.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setUTCDate) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setUTCDate.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/arg-coercion-order.js new file mode 100644 index 000000000000..c00dcdd04c5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCDate/arg-coercion-order.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setutcdate +description: Order of coercion of provided argument vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let dt be ? ToNumber(date). + 3. If t is NaN, return NaN. + 4. Let newDate be MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)). + 5. Let v be TimeClip(newDate). + 6. Set the [[DateValue]] internal slot of this Date object to v. + 7. Return v. +---*/ + +var date = new Date(NaN); +var callCount = 0; +var arg = { + valueOf: function() { + callCount += 1; + return 0; + } +}; + +var returnValue = date.setUTCDate(arg); + +assert.sameValue(callCount, 1, 'ToNumber invoked exactly once'); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T1.js index 741193072008..4bb9f2c24522 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setUTCFullYear; -if (x === 1) +if (x === 1) { Date.prototype.setUTCFullYear = 2; -else +} else { Date.prototype.setUTCFullYear = 1; -if (Date.prototype.setUTCFullYear === x) { - throw new Test262Error('#1: The Date.prototype.setUTCFullYear has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setUTCFullYear, + x, + 'The value of Date.prototype.setUTCFullYear is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T2.js index 28adf7aef869..1161ba431cdc 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setUTCFullYear" has { DontEnum } attributes esid: sec-date.prototype.setutcfullyear description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setUTCFullYear, + false, + 'The value of delete Date.prototype.setUTCFullYear is not false' +); -if (delete Date.prototype.setUTCFullYear === false) { - throw new Test262Error('#1: The Date.prototype.setUTCFullYear property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setUTCFullYear'), + 'The value of !Date.prototype.hasOwnProperty(\'setUTCFullYear\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setUTCFullYear')) { - throw new Test262Error('#2: The Date.prototype.setUTCFullYear property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T3.js index 97a4c4231378..7362027367fb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setUTCFullYear" has { DontEnum } attributes esid: sec-date.prototype.setutcfullyear description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setUTCFullYear')) { - throw new Test262Error('#1: The Date.prototype.setUTCFullYear property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setUTCFullYear'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setUTCFullYear\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setUTCFullYear") { - throw new Test262Error('#2: The Date.prototype.setUTCFullYear has the attribute DontEnum'); - } + assert.notSameValue(x, "setUTCFullYear", 'The value of x is not "setUTCFullYear"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A2_T1.js index c968a24a668d..408605fcb20c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setUTCFullYear" is 3 esid: sec-date.prototype.setutcfullyear description: The "length" property of the "setUTCFullYear" is 3 ---*/ +assert.sameValue( + Date.prototype.setUTCFullYear.hasOwnProperty("length"), + true, + 'Date.prototype.setUTCFullYear.hasOwnProperty("length") must return true' +); -if (Date.prototype.setUTCFullYear.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setUTCFullYear has a "length" property'); -} - -if (Date.prototype.setUTCFullYear.length !== 3) { - throw new Test262Error('#2: The "length" property of the setUTCFullYear is 3'); -} +assert.sameValue( + Date.prototype.setUTCFullYear.length, + 3, + 'The value of Date.prototype.setUTCFullYear.length is expected to be 3' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T1.js index 2a8f31726dff..7015cef362c9 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setUTCFullYear.length; verifyNotWritable(Date.prototype.setUTCFullYear, "length", null, 1); -if (Date.prototype.setUTCFullYear.length !== x) { - throw new Test262Error('#1: The Date.prototype.setUTCFullYear.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setUTCFullYear.length, + x, + 'The value of Date.prototype.setUTCFullYear.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T2.js index 8e4ddfcd2e1d..1076c90b232c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setutcfullyear description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setUTCFullYear.length, + true, + 'The value of `delete Date.prototype.setUTCFullYear.length` is expected to be true' +); -if (delete Date.prototype.setUTCFullYear.length !== true) { - throw new Test262Error('#1: The Date.prototype.setUTCFullYear.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setUTCFullYear.hasOwnProperty('length'), + 'The value of !Date.prototype.setUTCFullYear.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setUTCFullYear.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setUTCFullYear.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T3.js index df329fe99c37..ece7db26db19 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCFullYear/S15.9.5.41_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setutcfullyear description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setUTCFullYear.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setUTCFullYear.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setUTCFullYear.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setUTCFullYear.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setUTCFullYear) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setUTCFullYear.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T1.js index beba87c2c2b3..5bf8bdcc9b9d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setUTCHours; -if (x === 1) +if (x === 1) { Date.prototype.setUTCHours = 2; -else +} else { Date.prototype.setUTCHours = 1; -if (Date.prototype.setUTCHours === x) { - throw new Test262Error('#1: The Date.prototype.setUTCHours has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setUTCHours, + x, + 'The value of Date.prototype.setUTCHours is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T2.js index e5b39c05d6d5..487feb072ae4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setUTCHours" has { DontEnum } attributes esid: sec-date.prototype.setutchours description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setUTCHours, + false, + 'The value of delete Date.prototype.setUTCHours is not false' +); -if (delete Date.prototype.setUTCHours === false) { - throw new Test262Error('#1: The Date.prototype.setUTCHours property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setUTCHours'), + 'The value of !Date.prototype.hasOwnProperty(\'setUTCHours\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setUTCHours')) { - throw new Test262Error('#2: The Date.prototype.setUTCHours property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T3.js index c45190324447..7be2011f6553 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setUTCHours" has { DontEnum } attributes esid: sec-date.prototype.setutchours description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setUTCHours')) { - throw new Test262Error('#1: The Date.prototype.setUTCHours property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setUTCHours'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setUTCHours\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setUTCHours") { - throw new Test262Error('#2: The Date.prototype.setUTCHours has the attribute DontEnum'); - } + assert.notSameValue(x, "setUTCHours", 'The value of x is not "setUTCHours"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A2_T1.js index d43993c5cf6e..ce429ce09eb1 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setUTCHours" is 4 esid: sec-date.prototype.setutchours description: The "length" property of the "setUTCHours" is 4 ---*/ +assert.sameValue( + Date.prototype.setUTCHours.hasOwnProperty("length"), + true, + 'Date.prototype.setUTCHours.hasOwnProperty("length") must return true' +); -if (Date.prototype.setUTCHours.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setUTCHours has a "length" property'); -} - -if (Date.prototype.setUTCHours.length !== 4) { - throw new Test262Error('#2: The "length" property of the setUTCHours is 4'); -} +assert.sameValue( + Date.prototype.setUTCHours.length, + 4, + 'The value of Date.prototype.setUTCHours.length is expected to be 4' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T1.js index a1a361fef12d..da911c82b74d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setUTCHours.length; verifyNotWritable(Date.prototype.setUTCHours, "length", null, 1); -if (Date.prototype.setUTCHours.length !== x) { - throw new Test262Error('#1: The Date.prototype.setUTCHours.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setUTCHours.length, + x, + 'The value of Date.prototype.setUTCHours.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T2.js index 75d074cad00c..cad8d4c37aa4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setutchours description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setUTCHours.length, + true, + 'The value of `delete Date.prototype.setUTCHours.length` is expected to be true' +); -if (delete Date.prototype.setUTCHours.length !== true) { - throw new Test262Error('#1: The Date.prototype.setUTCHours.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setUTCHours.hasOwnProperty('length'), + 'The value of !Date.prototype.setUTCHours.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setUTCHours.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setUTCHours.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T3.js index ec0396e0ffb2..d196adad9d50 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/S15.9.5.35_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setutchours description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setUTCHours.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setUTCHours.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setUTCHours.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setUTCHours.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setUTCHours) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setUTCHours.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/arg-coercion-order.js new file mode 100644 index 000000000000..bbb850e7cf49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCHours/arg-coercion-order.js @@ -0,0 +1,58 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setutchours +description: Order of coercion of provided arguments vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let h be ? ToNumber(hour). + 3. If min is present, let m be ? ToNumber(min). + 4. If sec is present, let s be ? ToNumber(sec). + 5. If ms is present, let milli be ? ToNumber(ms). + 6. If t is NaN, return NaN. + 7. If min is not present, let m be MinFromTime(t). + 8. If sec is not present, let s be SecFromTime(t). + 9. If ms is not present, let milli be msFromTime(t). + 10. Let date be MakeDate(Day(t), MakeTime(h, m, s, milli)). + 11. Let v be TimeClip(date). + 12. Set the [[DateValue]] internal slot of this Date object to v. + 13. Return v. +includes: [compareArray.js] +---*/ + +var date = new Date(NaN); +var effects = []; +var argHour = { + valueOf: function() { + effects.push('valueOf hour'); + return 0; + } +}; +var argMin = { + valueOf: function() { + effects.push('valueOf min'); + return 0; + } +}; +var argSec = { + valueOf: function() { + effects.push('valueOf sec'); + return 0; + } +}; +var argMs = { + valueOf: function() { + effects.push('valueOf ms'); + return 0; + } +}; + +var returnValue = date.setUTCHours(argHour, argMin, argSec, argMs); + +var expectedEffects = ['valueOf hour', 'valueOf min', 'valueOf sec', 'valueOf ms']; + +assert.compareArray(effects, expectedEffects); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T1.js index 839c293cf086..a3770024c835 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T1.js @@ -10,12 +10,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setUTCMilliseconds; -if (x === 1) +if (x === 1) { Date.prototype.setUTCMilliseconds = 2; -else +} else { Date.prototype.setUTCMilliseconds = 1; -if (Date.prototype.setUTCMilliseconds === x) { - throw new Test262Error('#1: The Date.prototype.setUTCMilliseconds has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setUTCMilliseconds, + x, + 'The value of Date.prototype.setUTCMilliseconds is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T2.js index 31b1299d24cd..a539610d4a87 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setutcmilliseconds description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setUTCMilliseconds, + false, + 'The value of delete Date.prototype.setUTCMilliseconds is not false' +); -if (delete Date.prototype.setUTCMilliseconds === false) { - throw new Test262Error('#1: The Date.prototype.setUTCMilliseconds property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setUTCMilliseconds'), + 'The value of !Date.prototype.hasOwnProperty(\'setUTCMilliseconds\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setUTCMilliseconds')) { - throw new Test262Error('#2: The Date.prototype.setUTCMilliseconds property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T3.js index c61dd5b04ebc..a7508f1b5841 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A1_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setutcmilliseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setUTCMilliseconds')) { - throw new Test262Error('#1: The Date.prototype.setUTCMilliseconds property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setUTCMilliseconds'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setUTCMilliseconds\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setUTCMilliseconds") { - throw new Test262Error('#2: The Date.prototype.setUTCMilliseconds has the attribute DontEnum'); - } + assert.notSameValue(x, "setUTCMilliseconds", 'The value of x is not "setUTCMilliseconds"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A2_T1.js index 7aeae38cb64d..dbaabc809eed 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setUTCMilliseconds" is 1 esid: sec-date.prototype.setutcmilliseconds description: The "length" property of the "setUTCMilliseconds" is 1 ---*/ +assert.sameValue( + Date.prototype.setUTCMilliseconds.hasOwnProperty("length"), + true, + 'Date.prototype.setUTCMilliseconds.hasOwnProperty("length") must return true' +); -if (Date.prototype.setUTCMilliseconds.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setUTCMilliseconds has a "length" property'); -} - -if (Date.prototype.setUTCMilliseconds.length !== 1) { - throw new Test262Error('#2: The "length" property of the setUTCMilliseconds is 1'); -} +assert.sameValue( + Date.prototype.setUTCMilliseconds.length, + 1, + 'The value of Date.prototype.setUTCMilliseconds.length is expected to be 1' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T1.js index c738c585482b..6345c92b26a4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setUTCMilliseconds.length; verifyNotWritable(Date.prototype.setUTCMilliseconds, "length", null, 1); -if (Date.prototype.setUTCMilliseconds.length !== x) { - throw new Test262Error('#1: The Date.prototype.setUTCMilliseconds.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setUTCMilliseconds.length, + x, + 'The value of Date.prototype.setUTCMilliseconds.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T2.js index d562a436e1b8..7954d93fcd61 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setutcmilliseconds description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setUTCMilliseconds.length, + true, + 'The value of `delete Date.prototype.setUTCMilliseconds.length` is expected to be true' +); -if (delete Date.prototype.setUTCMilliseconds.length !== true) { - throw new Test262Error('#1: The Date.prototype.setUTCMilliseconds.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setUTCMilliseconds.hasOwnProperty('length'), + 'The value of !Date.prototype.setUTCMilliseconds.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setUTCMilliseconds.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setUTCMilliseconds.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T3.js index 097b014b3e81..40071144d73f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/S15.9.5.29_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setutcmilliseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setUTCMilliseconds.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setUTCMilliseconds.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setUTCMilliseconds.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setUTCMilliseconds.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setUTCMilliseconds) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setUTCMilliseconds.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/arg-coercion-order.js new file mode 100644 index 000000000000..02f2c3fd8a91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMilliseconds/arg-coercion-order.js @@ -0,0 +1,32 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setutcmilliseconds +description: Order of coercion of provided argument vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let dt be ? ToNumber(date). + 3. If t is NaN, return NaN. + 4. Set t to LocalTime(t). + 5. Let newDate be MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)). + 6. Let u be TimeClip(UTC(newDate)). + 7. Set the [[DateValue]] internal slot of this Date object to u. + 8. Return u. +---*/ + +var date = new Date(NaN); +var callCount = 0; +var arg = { + valueOf: function() { + callCount += 1; + return 0; + } +}; + +var returnValue = date.setUTCMilliseconds(arg); + +assert.sameValue(callCount, 1, 'ToNumber invoked exactly once'); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T1.js index 64e8aa57c0c7..d2aa63596bdb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setUTCMinutes; -if (x === 1) +if (x === 1) { Date.prototype.setUTCMinutes = 2; -else +} else { Date.prototype.setUTCMinutes = 1; -if (Date.prototype.setUTCMinutes === x) { - throw new Test262Error('#1: The Date.prototype.setUTCMinutes has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setUTCMinutes, + x, + 'The value of Date.prototype.setUTCMinutes is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T2.js index 91bfa874a1e5..14f6fa9b8f63 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setUTCMinutes" has { DontEnum } attributes esid: sec-date.prototype.setutcminutes description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setUTCMinutes, + false, + 'The value of delete Date.prototype.setUTCMinutes is not false' +); -if (delete Date.prototype.setUTCMinutes === false) { - throw new Test262Error('#1: The Date.prototype.setUTCMinutes property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setUTCMinutes'), + 'The value of !Date.prototype.hasOwnProperty(\'setUTCMinutes\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setUTCMinutes')) { - throw new Test262Error('#2: The Date.prototype.setUTCMinutes property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T3.js index bfe7c8cbb1d6..0a3afc4f3f63 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setUTCMinutes" has { DontEnum } attributes esid: sec-date.prototype.setutcminutes description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setUTCMinutes')) { - throw new Test262Error('#1: The Date.prototype.setUTCMinutes property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setUTCMinutes'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setUTCMinutes\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setUTCMinutes") { - throw new Test262Error('#2: The Date.prototype.setUTCMinutes has the attribute DontEnum'); - } + assert.notSameValue(x, "setUTCMinutes", 'The value of x is not "setUTCMinutes"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A2_T1.js index 3cc41b37c145..62c01ca4b7dc 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setUTCMinutes" is 3 esid: sec-date.prototype.setutcminutes description: The "length" property of the "setUTCMinutes" is 3 ---*/ +assert.sameValue( + Date.prototype.setUTCMinutes.hasOwnProperty("length"), + true, + 'Date.prototype.setUTCMinutes.hasOwnProperty("length") must return true' +); -if (Date.prototype.setUTCMinutes.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setUTCMinutes has a "length" property'); -} - -if (Date.prototype.setUTCMinutes.length !== 3) { - throw new Test262Error('#2: The "length" property of the setUTCMinutes is 3'); -} +assert.sameValue( + Date.prototype.setUTCMinutes.length, + 3, + 'The value of Date.prototype.setUTCMinutes.length is expected to be 3' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T1.js index 8a3281aad215..ca46350d6b05 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setUTCMinutes.length; verifyNotWritable(Date.prototype.setUTCMinutes, "length", null, 1); -if (Date.prototype.setUTCMinutes.length !== x) { - throw new Test262Error('#1: The Date.prototype.setUTCMinutes.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setUTCMinutes.length, + x, + 'The value of Date.prototype.setUTCMinutes.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T2.js index 364254329e61..de0271b5b570 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setutcminutes description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setUTCMinutes.length, + true, + 'The value of `delete Date.prototype.setUTCMinutes.length` is expected to be true' +); -if (delete Date.prototype.setUTCMinutes.length !== true) { - throw new Test262Error('#1: The Date.prototype.setUTCMinutes.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setUTCMinutes.hasOwnProperty('length'), + 'The value of !Date.prototype.setUTCMinutes.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setUTCMinutes.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setUTCMinutes.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T3.js index 3a7df7655f38..57301fe91fb0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/S15.9.5.33_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setutcminutes description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setUTCMinutes.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setUTCMinutes.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setUTCMinutes.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setUTCMinutes.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setUTCMinutes) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setUTCMinutes.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/arg-coercion-order.js new file mode 100644 index 000000000000..83b0a0346d93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMinutes/arg-coercion-order.js @@ -0,0 +1,50 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setutcminutes +description: Order of coercion of provided argument vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let m be ? ToNumber(min). + 3. If sec is present, let s be ? ToNumber(sec). + 4. If ms is present, let milli be ? ToNumber(ms). + 5. If t is NaN, return NaN. + 6. If sec is not present, let s be SecFromTime(t). + 7. If ms is not present, let milli be msFromTime(t). + 8. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)). + 9. Let v be TimeClip(date). + 10. Set the [[DateValue]] internal slot of this Date object to v. + 11. Return v. +includes: [compareArray.js] +---*/ + +var date = new Date(NaN); +var effects = []; +var argMin = { + valueOf: function() { + effects.push('valueOf min'); + return 0; + } +}; +var argSec = { + valueOf: function() { + effects.push('valueOf sec'); + return 0; + } +}; +var argMs = { + valueOf: function() { + effects.push('valueOf ms'); + return 0; + } +}; + +var returnValue = date.setUTCMinutes(argMin, argSec, argMs); + +var expectedEffects = ['valueOf min', 'valueOf sec', 'valueOf ms']; + +assert.compareArray(effects, expectedEffects); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T1.js index c0f7c449ef33..3a47d37da586 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setUTCMonth; -if (x === 1) +if (x === 1) { Date.prototype.setUTCMonth = 2; -else +} else { Date.prototype.setUTCMonth = 1; -if (Date.prototype.setUTCMonth === x) { - throw new Test262Error('#1: The Date.prototype.setUTCMonth has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setUTCMonth, + x, + 'The value of Date.prototype.setUTCMonth is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T2.js index d2e1dd5ec6c9..e250febbfef3 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setUTCMonth" has { DontEnum } attributes esid: sec-date.prototype.setutcmonth description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setUTCMonth, + false, + 'The value of delete Date.prototype.setUTCMonth is not false' +); -if (delete Date.prototype.setUTCMonth === false) { - throw new Test262Error('#1: The Date.prototype.setUTCMonth property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setUTCMonth'), + 'The value of !Date.prototype.hasOwnProperty(\'setUTCMonth\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setUTCMonth')) { - throw new Test262Error('#2: The Date.prototype.setUTCMonth property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T3.js index 13923a85ff59..bf3154fab42d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setUTCMonth" has { DontEnum } attributes esid: sec-date.prototype.setutcmonth description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setUTCMonth')) { - throw new Test262Error('#1: The Date.prototype.setUTCMonth property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setUTCMonth'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setUTCMonth\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setUTCMonth") { - throw new Test262Error('#2: The Date.prototype.setUTCMonth has the attribute DontEnum'); - } + assert.notSameValue(x, "setUTCMonth", 'The value of x is not "setUTCMonth"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A2_T1.js index 859c2b38cd7d..e917ba9810da 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setUTCMonth" is 2 esid: sec-date.prototype.setutcmonth description: The "length" property of the "setUTCMonth" is 2 ---*/ +assert.sameValue( + Date.prototype.setUTCMonth.hasOwnProperty("length"), + true, + 'Date.prototype.setUTCMonth.hasOwnProperty("length") must return true' +); -if (Date.prototype.setUTCMonth.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setUTCMonth has a "length" property'); -} - -if (Date.prototype.setUTCMonth.length !== 2) { - throw new Test262Error('#2: The "length" property of the setUTCMonth is 2'); -} +assert.sameValue( + Date.prototype.setUTCMonth.length, + 2, + 'The value of Date.prototype.setUTCMonth.length is expected to be 2' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T1.js index d40b74a451cc..cf63985f9522 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setUTCMonth.length; verifyNotWritable(Date.prototype.setUTCMonth, "length", null, 1); -if (Date.prototype.setUTCMonth.length !== x) { - throw new Test262Error('#1: The Date.prototype.setUTCMonth.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setUTCMonth.length, + x, + 'The value of Date.prototype.setUTCMonth.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T2.js index e9b47b64a870..923cba2989d7 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setutcmonth description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setUTCMonth.length, + true, + 'The value of `delete Date.prototype.setUTCMonth.length` is expected to be true' +); -if (delete Date.prototype.setUTCMonth.length !== true) { - throw new Test262Error('#1: The Date.prototype.setUTCMonth.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setUTCMonth.hasOwnProperty('length'), + 'The value of !Date.prototype.setUTCMonth.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setUTCMonth.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setUTCMonth.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T3.js index 830242f7968b..03d107db9bba 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/S15.9.5.39_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setutcmonth description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setUTCMonth.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setUTCMonth.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setUTCMonth.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setUTCMonth.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setUTCMonth) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setUTCMonth.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/arg-coercion-order.js new file mode 100644 index 000000000000..c94d09f56d4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCMonth/arg-coercion-order.js @@ -0,0 +1,42 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setutcmonth +description: Order of coercion of provided argument vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let m be ? ToNumber(month). + 3. If date is present, let dt be ? ToNumber(date). + 4. If t is NaN, return NaN. + 5. If date is not present, let dt be DateFromTime(t). + 6. Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)). + 7. Let v be TimeClip(newDate). + 8. Set the [[DateValue]] internal slot of this Date object to v. + 9. Return v. +includes: [compareArray.js] +---*/ + +var date = new Date(NaN); +var effects = []; +var argMonth = { + valueOf: function() { + effects.push('valueOf month'); + return 0; + } +}; +var argDate = { + valueOf: function() { + effects.push('valueOf date'); + return 0; + } +}; + +var returnValue = date.setUTCMonth(argMonth, argDate); + +var expectedEffects = ['valueOf month', 'valueOf date']; + +assert.compareArray(effects, expectedEffects); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T1.js index 5bb2445b6c13..1d75241ef895 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.setUTCSeconds; -if (x === 1) +if (x === 1) { Date.prototype.setUTCSeconds = 2; -else +} else { Date.prototype.setUTCSeconds = 1; -if (Date.prototype.setUTCSeconds === x) { - throw new Test262Error('#1: The Date.prototype.setUTCSeconds has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.setUTCSeconds, + x, + 'The value of Date.prototype.setUTCSeconds is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T2.js index f44a1288ae23..4a0cfaa0f633 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "setUTCSeconds" has { DontEnum } attributes esid: sec-date.prototype.setutcseconds description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.setUTCSeconds, + false, + 'The value of delete Date.prototype.setUTCSeconds is not false' +); -if (delete Date.prototype.setUTCSeconds === false) { - throw new Test262Error('#1: The Date.prototype.setUTCSeconds property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('setUTCSeconds'), + 'The value of !Date.prototype.hasOwnProperty(\'setUTCSeconds\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('setUTCSeconds')) { - throw new Test262Error('#2: The Date.prototype.setUTCSeconds property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T3.js index 3cdb78038c2f..efb81dd571cd 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "setUTCSeconds" has { DontEnum } attributes esid: sec-date.prototype.setutcseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('setUTCSeconds')) { - throw new Test262Error('#1: The Date.prototype.setUTCSeconds property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('setUTCSeconds'), + 'The value of !Date.prototype.propertyIsEnumerable(\'setUTCSeconds\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "setUTCSeconds") { - throw new Test262Error('#2: The Date.prototype.setUTCSeconds has the attribute DontEnum'); - } + assert.notSameValue(x, "setUTCSeconds", 'The value of x is not "setUTCSeconds"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A2_T1.js index 3f61003fd14a..314194b4c4b6 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "setUTCSeconds" is 2 esid: sec-date.prototype.setutcseconds description: The "length" property of the "setUTCSeconds" is 2 ---*/ +assert.sameValue( + Date.prototype.setUTCSeconds.hasOwnProperty("length"), + true, + 'Date.prototype.setUTCSeconds.hasOwnProperty("length") must return true' +); -if (Date.prototype.setUTCSeconds.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The setUTCSeconds has a "length" property'); -} - -if (Date.prototype.setUTCSeconds.length !== 2) { - throw new Test262Error('#2: The "length" property of the setUTCSeconds is 2'); -} +assert.sameValue( + Date.prototype.setUTCSeconds.length, + 2, + 'The value of Date.prototype.setUTCSeconds.length is expected to be 2' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T1.js index 6f08f503045e..422b8d2f54d4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.setUTCSeconds.length; verifyNotWritable(Date.prototype.setUTCSeconds, "length", null, 1); -if (Date.prototype.setUTCSeconds.length !== x) { - throw new Test262Error('#1: The Date.prototype.setUTCSeconds.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.setUTCSeconds.length, + x, + 'The value of Date.prototype.setUTCSeconds.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T2.js index bef1dfc84d0b..195b8488930b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.setutcseconds description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.setUTCSeconds.length, + true, + 'The value of `delete Date.prototype.setUTCSeconds.length` is expected to be true' +); -if (delete Date.prototype.setUTCSeconds.length !== true) { - throw new Test262Error('#1: The Date.prototype.setUTCSeconds.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.setUTCSeconds.hasOwnProperty('length'), + 'The value of !Date.prototype.setUTCSeconds.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.setUTCSeconds.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.setUTCSeconds.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T3.js index ea209b314250..aec6f68e8d30 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/S15.9.5.31_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.setutcseconds description: Checking DontEnum attribute ---*/ - -if (Date.prototype.setUTCSeconds.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.setUTCSeconds.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.setUTCSeconds.propertyIsEnumerable('length'), + 'The value of !Date.prototype.setUTCSeconds.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.setUTCSeconds) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.setUTCSeconds.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/arg-coercion-order.js b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/arg-coercion-order.js new file mode 100644 index 000000000000..a453b5a2c215 --- /dev/null +++ b/js/src/tests/test262/built-ins/Date/prototype/setUTCSeconds/arg-coercion-order.js @@ -0,0 +1,42 @@ +// Copyright (C) 2021 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-date.prototype.setutcseconds +description: Order of coercion of provided arguments vs NaN check +info: | + 1. Let t be ? thisTimeValue(this value). + 2. Let s be ? ToNumber(sec). + 3. If ms is present, let milli be ? ToNumber(ms). + 4. If t is NaN, return NaN. + 5. If ms is not present, let milli be msFromTime(t). + 6. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)). + 7. Let v be TimeClip(date). + 8. Set the [[DateValue]] internal slot of this Date object to v. + 9. Return v. +includes: [compareArray.js] +---*/ + +var date = new Date(NaN); +var effects = []; +var argSec = { + valueOf: function() { + effects.push('valueOf sec'); + return 0; + } +}; +var argMs = { + valueOf: function() { + effects.push('valueOf ms'); + return 0; + } +}; + +var returnValue = date.setUTCSeconds(argSec, argMs); + +var expectedEffects = ['valueOf sec', 'valueOf ms']; + +assert.compareArray(effects, expectedEffects); +assert.sameValue(returnValue, NaN, 'argument is ignored when `this` is an invalid date'); +assert.sameValue(date.getTime(), NaN, 'argument is ignored when `this` is an invalid date'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T1.js index 0859fb22166f..8c3b6275c198 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.toDateString; -if (x === 1) +if (x === 1) { Date.prototype.toDateString = 2; -else +} else { Date.prototype.toDateString = 1; -if (Date.prototype.toDateString === x) { - throw new Test262Error('#1: The Date.prototype.toDateString has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.toDateString, + x, + 'The value of Date.prototype.toDateString is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T2.js index 7a04024140ef..b577a2dbc56e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T2.js @@ -6,13 +6,17 @@ info: The Date.prototype property "toDateString" has { DontEnum } attributes esid: sec-date.prototype.todatestring description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.toDateString, + false, + 'The value of delete Date.prototype.toDateString is not false' +); -if (delete Date.prototype.toDateString === false) { - throw new Test262Error('#1: The Date.prototype.toDateString property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('toDateString'), + 'The value of !Date.prototype.hasOwnProperty(\'toDateString\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('toDateString')) { - throw new Test262Error('#2: The Date.prototype.toDateString property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T3.js index a625e506936e..19fead51e383 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "toDateString" has { DontEnum } attributes esid: sec-date.prototype.todatestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('toDateString')) { - throw new Test262Error('#1: The Date.prototype.toDateString property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('toDateString'), + 'The value of !Date.prototype.propertyIsEnumerable(\'toDateString\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "toDateString") { - throw new Test262Error('#2: The Date.prototype.toDateString has the attribute DontEnum'); - } + assert.notSameValue(x, "toDateString", 'The value of x is not "toDateString"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A2_T1.js index 8124a0e85861..ec4467849962 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "toDateString" is 0 esid: sec-date.prototype.todatestring description: The "length" property of the "toDateString" is 0 ---*/ +assert.sameValue( + Date.prototype.toDateString.hasOwnProperty("length"), + true, + 'Date.prototype.toDateString.hasOwnProperty("length") must return true' +); -if (Date.prototype.toDateString.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The toDateString has a "length" property'); -} - -if (Date.prototype.toDateString.length !== 0) { - throw new Test262Error('#2: The "length" property of the toDateString is 0'); -} +assert.sameValue( + Date.prototype.toDateString.length, + 0, + 'The value of Date.prototype.toDateString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T1.js index 516b4c4f9d9b..ea918616ee47 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.toDateString.length; verifyNotWritable(Date.prototype.toDateString, "length", null, 1); -if (Date.prototype.toDateString.length !== x) { - throw new Test262Error('#1: The Date.prototype.toDateString.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.toDateString.length, + x, + 'The value of Date.prototype.toDateString.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T2.js index 00727fbfdd81..d56ed18a2002 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.todatestring description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.toDateString.length, + true, + 'The value of `delete Date.prototype.toDateString.length` is expected to be true' +); -if (delete Date.prototype.toDateString.length !== true) { - throw new Test262Error('#1: The Date.prototype.toDateString.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.toDateString.hasOwnProperty('length'), + 'The value of !Date.prototype.toDateString.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.toDateString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.toDateString.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T3.js index 3a00839f139b..fd89a02806a3 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toDateString/S15.9.5.3_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.todatestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.toDateString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.toDateString.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.toDateString.propertyIsEnumerable('length'), + 'The value of !Date.prototype.toDateString.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.toDateString) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.toDateString.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T1.js index 8772a3ee061f..4ecf0d30290e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T1.js @@ -10,12 +10,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.toLocaleDateString; -if (x === 1) +if (x === 1) { Date.prototype.toLocaleDateString = 2; -else +} else { Date.prototype.toLocaleDateString = 1; -if (Date.prototype.toLocaleDateString === x) { - throw new Test262Error('#1: The Date.prototype.toLocaleDateString has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.toLocaleDateString, + x, + 'The value of Date.prototype.toLocaleDateString is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T2.js index daa2b47ede18..99ff7abca096 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.tolocaledatestring description: Checking absence of DontDelete attribute ---*/ +assert.notSameValue( + delete Date.prototype.toLocaleDateString, + false, + 'The value of delete Date.prototype.toLocaleDateString is not false' +); -if (delete Date.prototype.toLocaleDateString === false) { - throw new Test262Error('#1: The Date.prototype.toLocaleDateString property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('toLocaleDateString'), + 'The value of !Date.prototype.hasOwnProperty(\'toLocaleDateString\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('toLocaleDateString')) { - throw new Test262Error('#2: The Date.prototype.toLocaleDateString property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T3.js index 477916fbee72..20a586e47f4f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A1_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.tolocaledatestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('toLocaleDateString')) { - throw new Test262Error('#1: The Date.prototype.toLocaleDateString property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('toLocaleDateString'), + 'The value of !Date.prototype.propertyIsEnumerable(\'toLocaleDateString\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "toLocaleDateString") { - throw new Test262Error('#2: The Date.prototype.toLocaleDateString has the attribute DontEnum'); - } + assert.notSameValue(x, "toLocaleDateString", 'The value of x is not "toLocaleDateString"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A2_T1.js index 7827b3e46d6c..283d863bf406 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A2_T1.js @@ -6,13 +6,16 @@ info: The "length" property of the "toLocaleDateString" is 0 esid: sec-date.prototype.tolocaledatestring description: The "length" property of the "toLocaleDateString" is 0 ---*/ +assert.sameValue( + Date.prototype.toLocaleDateString.hasOwnProperty("length"), + true, + 'Date.prototype.toLocaleDateString.hasOwnProperty("length") must return true' +); -if (Date.prototype.toLocaleDateString.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The toLocaleDateString has a "length" property'); -} - -if (Date.prototype.toLocaleDateString.length !== 0) { - throw new Test262Error('#2: The "length" property of the toLocaleDateString is 0'); -} +assert.sameValue( + Date.prototype.toLocaleDateString.length, + 0, + 'The value of Date.prototype.toLocaleDateString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T1.js index 2588bbdea8b6..3df27ab67320 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.toLocaleDateString.length; verifyNotWritable(Date.prototype.toLocaleDateString, "length", null, 1); -if (Date.prototype.toLocaleDateString.length !== x) { - throw new Test262Error('#1: The Date.prototype.toLocaleDateString.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.toLocaleDateString.length, + x, + 'The value of Date.prototype.toLocaleDateString.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T2.js index d4c4fa11f617..5339b513a262 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.tolocaledatestring description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.toLocaleDateString.length, + true, + 'The value of `delete Date.prototype.toLocaleDateString.length` is expected to be true' +); -if (delete Date.prototype.toLocaleDateString.length !== true) { - throw new Test262Error('#1: The Date.prototype.toLocaleDateString.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.toLocaleDateString.hasOwnProperty('length'), + 'The value of !Date.prototype.toLocaleDateString.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.toLocaleDateString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.toLocaleDateString.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T3.js index c778fbc08676..23f2fe919df7 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleDateString/S15.9.5.6_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.tolocaledatestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.toLocaleDateString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.toLocaleDateString.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.toLocaleDateString.propertyIsEnumerable('length'), + 'The value of !Date.prototype.toLocaleDateString.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.toLocaleDateString) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.toLocaleDateString.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T1.js index 96667eeffd5c..462d53f26b59 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.toLocaleString; -if (x === 1) +if (x === 1) { Date.prototype.toLocaleString = 2; -else +} else { Date.prototype.toLocaleString = 1; -if (Date.prototype.toLocaleString === x) { - throw new Test262Error('#1: The Date.prototype.toLocaleString has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.toLocaleString, + x, + 'The value of Date.prototype.toLocaleString is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T2.js index e03e6c6d4e64..7048a1c8c413 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T2.js @@ -7,12 +7,17 @@ esid: sec-date.prototype.tolocalestring description: Checking absence of DontDelete attribute ---*/ -if (delete Date.prototype.toLocaleString === false) { - throw new Test262Error('#1: The Date.prototype.toLocaleString property has not the attributes DontDelete'); -} +assert.notSameValue( + delete Date.prototype.toLocaleString, + false, + 'The value of delete Date.prototype.toLocaleString is not false' +); -if (Date.prototype.hasOwnProperty('toLocaleString')) { - throw new Test262Error('#2: The Date.prototype.toLocaleString property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('toLocaleString'), + 'The value of !Date.prototype.hasOwnProperty(\'toLocaleString\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T3.js index 4aec64709ae4..8cd0d560cc9c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "toLocaleString" has { DontEnum } attributes esid: sec-date.prototype.tolocalestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('toLocaleString')) { - throw new Test262Error('#1: The Date.prototype.toLocaleString property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('toLocaleString'), + 'The value of !Date.prototype.propertyIsEnumerable(\'toLocaleString\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "toLocaleString") { - throw new Test262Error('#2: The Date.prototype.toLocaleString has the attribute DontEnum'); - } + assert.notSameValue(x, "toLocaleString", 'The value of x is not "toLocaleString"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A2_T1.js index 1c64668c109a..a99ec980520c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A2_T1.js @@ -7,12 +7,16 @@ esid: sec-date.prototype.tolocalestring description: The "length" property of the "toLocaleString" is 0 ---*/ -if (Date.prototype.toLocaleString.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The toLocaleString has a "length" property'); -} +assert.sameValue( + Date.prototype.toLocaleString.hasOwnProperty("length"), + true, + 'Date.prototype.toLocaleString.hasOwnProperty("length") must return true' +); -if (Date.prototype.toLocaleString.length !== 0) { - throw new Test262Error('#2: The "length" property of the toLocaleString is 0'); -} +assert.sameValue( + Date.prototype.toLocaleString.length, + 0, + 'The value of Date.prototype.toLocaleString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T1.js index a7a53c379d8e..4537937e8b35 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.toLocaleString.length; verifyNotWritable(Date.prototype.toLocaleString, "length", null, 1); -if (Date.prototype.toLocaleString.length !== x) { - throw new Test262Error('#1: The Date.prototype.toLocaleString.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.toLocaleString.length, + x, + 'The value of Date.prototype.toLocaleString.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T2.js index b3c2e34b7a53..29166bae0698 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T2.js @@ -9,12 +9,17 @@ esid: sec-date.prototype.tolocalestring description: Checking DontDelete attribute ---*/ -if (delete Date.prototype.toLocaleString.length !== true) { - throw new Test262Error('#1: The Date.prototype.toLocaleString.length property does not have the attributes DontDelete'); -} +assert.sameValue( + delete Date.prototype.toLocaleString.length, + true, + 'The value of `delete Date.prototype.toLocaleString.length` is expected to be true' +); -if (Date.prototype.toLocaleString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.toLocaleString.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.toLocaleString.hasOwnProperty('length'), + 'The value of !Date.prototype.toLocaleString.hasOwnProperty(\'length\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T3.js index 15a987c757fb..af48b9388e3b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleString/S15.9.5.5_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.tolocalestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.toLocaleString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.toLocaleString.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.toLocaleString.propertyIsEnumerable('length'), + 'The value of !Date.prototype.toLocaleString.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.toLocaleString) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.toLocaleString.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T1.js index 97ca147fa016..21dd5d44113e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T1.js @@ -10,12 +10,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.toLocaleTimeString; -if (x === 1) +if (x === 1) { Date.prototype.toLocaleTimeString = 2; -else +} else { Date.prototype.toLocaleTimeString = 1; -if (Date.prototype.toLocaleTimeString === x) { - throw new Test262Error('#1: The Date.prototype.toLocaleTimeString has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.toLocaleTimeString, + x, + 'The value of Date.prototype.toLocaleTimeString is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T2.js index 1d8be9249ef1..3069df6de63e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T2.js @@ -9,12 +9,17 @@ esid: sec-date.prototype.tolocaletimestring description: Checking absence of DontDelete attribute ---*/ -if (delete Date.prototype.toLocaleTimeString === false) { - throw new Test262Error('#1: The Date.prototype.toLocaleTimeString property has not the attributes DontDelete'); -} +assert.notSameValue( + delete Date.prototype.toLocaleTimeString, + false, + 'The value of delete Date.prototype.toLocaleTimeString is not false' +); -if (Date.prototype.hasOwnProperty('toLocaleTimeString')) { - throw new Test262Error('#2: The Date.prototype.toLocaleTimeString property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('toLocaleTimeString'), + 'The value of !Date.prototype.hasOwnProperty(\'toLocaleTimeString\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T3.js index 0e0f49633a4d..ece77abd00ad 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A1_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.tolocaletimestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('toLocaleTimeString')) { - throw new Test262Error('#1: The Date.prototype.toLocaleTimeString property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('toLocaleTimeString'), + 'The value of !Date.prototype.propertyIsEnumerable(\'toLocaleTimeString\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "toLocaleTimeString") { - throw new Test262Error('#2: The Date.prototype.toLocaleTimeString has the attribute DontEnum'); - } + assert.notSameValue(x, "toLocaleTimeString", 'The value of x is not "toLocaleTimeString"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A2_T1.js index 30e314fa9fb0..9db46eb03438 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A2_T1.js @@ -7,12 +7,16 @@ esid: sec-date.prototype.tolocaletimestring description: The "length" property of the "toLocaleTimeString" is 0 ---*/ -if (Date.prototype.toLocaleTimeString.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The toLocaleTimeString has a "length" property'); -} +assert.sameValue( + Date.prototype.toLocaleTimeString.hasOwnProperty("length"), + true, + 'Date.prototype.toLocaleTimeString.hasOwnProperty("length") must return true' +); -if (Date.prototype.toLocaleTimeString.length !== 0) { - throw new Test262Error('#2: The "length" property of the toLocaleTimeString is 0'); -} +assert.sameValue( + Date.prototype.toLocaleTimeString.length, + 0, + 'The value of Date.prototype.toLocaleTimeString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T1.js index c34cd87029a4..d0f4fbabc34c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.toLocaleTimeString.length; verifyNotWritable(Date.prototype.toLocaleTimeString, "length", null, 1); -if (Date.prototype.toLocaleTimeString.length !== x) { - throw new Test262Error('#1: The Date.prototype.toLocaleTimeString.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.toLocaleTimeString.length, + x, + 'The value of Date.prototype.toLocaleTimeString.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T2.js index 67bd497aaa25..5137a41104e6 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T2.js @@ -9,12 +9,17 @@ esid: sec-date.prototype.tolocaletimestring description: Checking DontDelete attribute ---*/ -if (delete Date.prototype.toLocaleTimeString.length !== true) { - throw new Test262Error('#1: The Date.prototype.toLocaleTimeString.length property does not have the attributes DontDelete'); -} +assert.sameValue( + delete Date.prototype.toLocaleTimeString.length, + true, + 'The value of `delete Date.prototype.toLocaleTimeString.length` is expected to be true' +); -if (Date.prototype.toLocaleTimeString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.toLocaleTimeString.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.toLocaleTimeString.hasOwnProperty('length'), + 'The value of !Date.prototype.toLocaleTimeString.hasOwnProperty(\'length\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T3.js index e70ed5f07372..8e03eff9be81 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toLocaleTimeString/S15.9.5.7_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.tolocaletimestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.toLocaleTimeString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.toLocaleTimeString.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.toLocaleTimeString.propertyIsEnumerable('length'), + 'The value of !Date.prototype.toLocaleTimeString.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.toLocaleTimeString) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.toLocaleTimeString.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T1.js index 97fba980b185..6612e3a747a4 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.toString; -if (x === 1) +if (x === 1) { Date.prototype.toString = 2; -else +} else { Date.prototype.toString = 1; -if (Date.prototype.toString === x) { - throw new Test262Error('#1: The Date.prototype.toString has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.toString, + x, + 'The value of Date.prototype.toString is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T2.js index a4a537258f07..0395c2e11145 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T2.js @@ -7,12 +7,12 @@ esid: sec-date.prototype.tostring description: Checking absence of DontDelete attribute ---*/ -if (delete Date.prototype.toString === false) { - throw new Test262Error('#1: The Date.prototype.toString property has not the attributes DontDelete'); -} +assert.notSameValue(delete Date.prototype.toString, false, 'The value of delete Date.prototype.toString is not false'); +assert( + !Date.prototype.hasOwnProperty('toString'), + 'The value of !Date.prototype.hasOwnProperty(\'toString\') is expected to be true' +); -if (Date.prototype.hasOwnProperty('toString')) { - throw new Test262Error('#2: The Date.prototype.toString property has not the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T3.js index 23e7f989828c..494bbdb2ace0 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "toString" has { DontEnum } attributes esid: sec-date.prototype.tostring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('toString')) { - throw new Test262Error('#1: The Date.prototype.toString property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('toString'), + 'The value of !Date.prototype.propertyIsEnumerable(\'toString\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "toString") { - throw new Test262Error('#2: The Date.prototype.toString has the attribute DontEnum'); - } + assert.notSameValue(x, "toString", 'The value of x is not "toString"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A2_T1.js index d9fa18ae0f40..61390398931c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A2_T1.js @@ -7,12 +7,12 @@ esid: sec-date.prototype.tostring description: The "length" property of the "toString" is 0 ---*/ -if (Date.prototype.toString.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The toString has a "length" property'); -} +assert.sameValue( + Date.prototype.toString.hasOwnProperty("length"), + true, + 'Date.prototype.toString.hasOwnProperty("length") must return true' +); -if (Date.prototype.toString.length !== 0) { - throw new Test262Error('#2: The "length" property of the toString is 0'); -} +assert.sameValue(Date.prototype.toString.length, 0, 'The value of Date.prototype.toString.length is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T1.js index 2999bf145421..f8505716f7e3 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.toString.length; verifyNotWritable(Date.prototype.toString, "length", null, 1); -if (Date.prototype.toString.length !== x) { - throw new Test262Error('#1: The Date.prototype.toString.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.toString.length, + x, + 'The value of Date.prototype.toString.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T2.js index c6a3a9878de0..d265d9f4c3bd 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T2.js @@ -9,12 +9,17 @@ esid: sec-date.prototype.tostring description: Checking DontDelete attribute ---*/ -if (delete Date.prototype.toString.length !== true) { - throw new Test262Error('#1: The Date.prototype.toString.length property does not have the attributes DontDelete'); -} +assert.sameValue( + delete Date.prototype.toString.length, + true, + 'The value of `delete Date.prototype.toString.length` is expected to be true' +); -if (Date.prototype.toString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.toString.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.toString.hasOwnProperty('length'), + 'The value of !Date.prototype.toString.hasOwnProperty(\'length\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T3.js index 7362f4571990..d4b54c6f790e 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toString/S15.9.5.2_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.tostring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.toString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.toString.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.toString.propertyIsEnumerable('length'), + 'The value of !Date.prototype.toString.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.toString) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.toString.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T1.js index 0cceb1e4b045..4b2913c51fd6 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.toTimeString; -if (x === 1) +if (x === 1) { Date.prototype.toTimeString = 2; -else +} else { Date.prototype.toTimeString = 1; -if (Date.prototype.toTimeString === x) { - throw new Test262Error('#1: The Date.prototype.toTimeString has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.toTimeString, + x, + 'The value of Date.prototype.toTimeString is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T2.js index d876c328affd..8a9830dd56f3 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T2.js @@ -7,12 +7,17 @@ esid: sec-date.prototype.totimestring description: Checking absence of DontDelete attribute ---*/ -if (delete Date.prototype.toTimeString === false) { - throw new Test262Error('#1: The Date.prototype.toTimeString property has not the attributes DontDelete'); -} +assert.notSameValue( + delete Date.prototype.toTimeString, + false, + 'The value of delete Date.prototype.toTimeString is not false' +); -if (Date.prototype.hasOwnProperty('toTimeString')) { - throw new Test262Error('#2: The Date.prototype.toTimeString property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('toTimeString'), + 'The value of !Date.prototype.hasOwnProperty(\'toTimeString\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T3.js index 84780d809f32..c6a0aa0e024d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "toTimeString" has { DontEnum } attributes esid: sec-date.prototype.totimestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('toTimeString')) { - throw new Test262Error('#1: The Date.prototype.toTimeString property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('toTimeString'), + 'The value of !Date.prototype.propertyIsEnumerable(\'toTimeString\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "toTimeString") { - throw new Test262Error('#2: The Date.prototype.toTimeString has the attribute DontEnum'); - } + assert.notSameValue(x, "toTimeString", 'The value of x is not "toTimeString"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A2_T1.js index e7299f7a0c8c..2d8c9676f35d 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A2_T1.js @@ -1,18 +1,22 @@ // Copyright 2009 the Sputnik authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. - /*--- info: The "length" property of the "toTimeString" is 0 esid: sec-date.prototype.totimestring description: The "length" property of the "toTimeString" is 0 ---*/ -if (Date.prototype.toTimeString.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The toTimeString has a "length" property'); -} +assert.sameValue( + Date.prototype.toTimeString.hasOwnProperty("length"), + true, + 'Date.prototype.toTimeString.hasOwnProperty("length") must return true' +); -if (Date.prototype.toTimeString.length !== 0) { - throw new Test262Error('#2: The "length" property of the toTimeString is 0'); -} + +assert.sameValue( + Date.prototype.toTimeString.length, + 0, + 'The value of Date.prototype.toTimeString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T1.js index bdbac2de2376..8337e86cbf5a 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.toTimeString.length; verifyNotWritable(Date.prototype.toTimeString, "length", null, 1); -if (Date.prototype.toTimeString.length !== x) { - throw new Test262Error('#1: The Date.prototype.toTimeString.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.toTimeString.length, + x, + 'The value of Date.prototype.toTimeString.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T2.js index 048d8dd98ef2..27c8d06ee0eb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T2.js @@ -8,13 +8,17 @@ info: | esid: sec-date.prototype.totimestring description: Checking DontDelete attribute ---*/ +assert.sameValue( + delete Date.prototype.toTimeString.length, + true, + 'The value of `delete Date.prototype.toTimeString.length` is expected to be true' +); -if (delete Date.prototype.toTimeString.length !== true) { - throw new Test262Error('#1: The Date.prototype.toTimeString.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.toTimeString.hasOwnProperty('length'), + 'The value of !Date.prototype.toTimeString.hasOwnProperty(\'length\') is expected to be true' +); -if (Date.prototype.toTimeString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.toTimeString.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T3.js index 36bf6529886c..ef6033fcc89f 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toTimeString/S15.9.5.4_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.totimestring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.toTimeString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.toTimeString.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.toTimeString.propertyIsEnumerable('length'), + 'The value of !Date.prototype.toTimeString.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.toTimeString) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.toTimeString.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T1.js index 75675ec09eee..8112c69a0024 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.toUTCString; -if (x === 1) +if (x === 1) { Date.prototype.toUTCString = 2; -else +} else { Date.prototype.toUTCString = 1; -if (Date.prototype.toUTCString === x) { - throw new Test262Error('#1: The Date.prototype.toUTCString has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.toUTCString, + x, + 'The value of Date.prototype.toUTCString is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T2.js index 2c8b66144dd9..381863eb75d8 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T2.js @@ -7,12 +7,17 @@ esid: sec-date.prototype.toutcstring description: Checking absence of DontDelete attribute ---*/ -if (delete Date.prototype.toUTCString === false) { - throw new Test262Error('#1: The Date.prototype.toUTCString property has not the attributes DontDelete'); -} +assert.notSameValue( + delete Date.prototype.toUTCString, + false, + 'The value of delete Date.prototype.toUTCString is not false' +); -if (Date.prototype.hasOwnProperty('toUTCString')) { - throw new Test262Error('#2: The Date.prototype.toUTCString property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('toUTCString'), + 'The value of !Date.prototype.hasOwnProperty(\'toUTCString\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T3.js index bea0b5dd43c2..9f6547954cec 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "toUTCString" has { DontEnum } attributes esid: sec-date.prototype.toutcstring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('toUTCString')) { - throw new Test262Error('#1: The Date.prototype.toUTCString property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('toUTCString'), + 'The value of !Date.prototype.propertyIsEnumerable(\'toUTCString\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "toUTCString") { - throw new Test262Error('#2: The Date.prototype.toUTCString has the attribute DontEnum'); - } + assert.notSameValue(x, "toUTCString", 'The value of x is not "toUTCString"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A2_T1.js index c4bb9d2212b8..b7e15d69aefd 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A2_T1.js @@ -7,12 +7,16 @@ esid: sec-date.prototype.toutcstring description: The "length" property of the "toUTCString" is 0 ---*/ -if (Date.prototype.toUTCString.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The toUTCString has a "length" property'); -} +assert.sameValue( + Date.prototype.toUTCString.hasOwnProperty("length"), + true, + 'Date.prototype.toUTCString.hasOwnProperty("length") must return true' +); -if (Date.prototype.toUTCString.length !== 0) { - throw new Test262Error('#2: The "length" property of the toUTCString is 0'); -} +assert.sameValue( + Date.prototype.toUTCString.length, + 0, + 'The value of Date.prototype.toUTCString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T1.js index c3b1963e7d9b..37634bdfe645 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.toUTCString.length; verifyNotWritable(Date.prototype.toUTCString, "length", null, 1); -if (Date.prototype.toUTCString.length !== x) { - throw new Test262Error('#1: The Date.prototype.toUTCString.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.toUTCString.length, + x, + 'The value of Date.prototype.toUTCString.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T2.js index 4fe99d344a7a..23528c870d91 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T2.js @@ -9,12 +9,17 @@ esid: sec-date.prototype.toutcstring description: Checking DontDelete attribute ---*/ -if (delete Date.prototype.toUTCString.length !== true) { - throw new Test262Error('#1: The Date.prototype.toUTCString.length property does not have the attributes DontDelete'); -} +assert.sameValue( + delete Date.prototype.toUTCString.length, + true, + 'The value of `delete Date.prototype.toUTCString.length` is expected to be true' +); -if (Date.prototype.toUTCString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.toUTCString.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.toUTCString.hasOwnProperty('length'), + 'The value of !Date.prototype.toUTCString.hasOwnProperty(\'length\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T3.js index afec331f198c..b15da4c99445 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/toUTCString/S15.9.5.42_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.toutcstring description: Checking DontEnum attribute ---*/ - -if (Date.prototype.toUTCString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.toUTCString.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.toUTCString.propertyIsEnumerable('length'), + 'The value of !Date.prototype.toUTCString.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.toUTCString) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.toUTCString.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T1.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T1.js index 9bc839d233fa..704878882aae 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T1.js @@ -8,12 +8,18 @@ description: Checking absence of ReadOnly attribute ---*/ var x = Date.prototype.valueOf; -if (x === 1) +if (x === 1) { Date.prototype.valueOf = 2; -else +} else { Date.prototype.valueOf = 1; -if (Date.prototype.valueOf === x) { - throw new Test262Error('#1: The Date.prototype.valueOf has not the attribute ReadOnly'); } +assert.notSameValue( + Date.prototype.valueOf, + x, + 'The value of Date.prototype.valueOf is expected to not equal the value of `x`' +); + +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T2.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T2.js index c2324c3ba2f6..f19351c81b17 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T2.js @@ -7,12 +7,13 @@ esid: sec-date.prototype.valueof description: Checking absence of DontDelete attribute ---*/ -if (delete Date.prototype.valueOf === false) { - throw new Test262Error('#1: The Date.prototype.valueOf property has not the attributes DontDelete'); -} +assert.notSameValue(delete Date.prototype.valueOf, false, 'The value of delete Date.prototype.valueOf is not false'); -if (Date.prototype.hasOwnProperty('valueOf')) { - throw new Test262Error('#2: The Date.prototype.valueOf property has not the attributes DontDelete'); -} +assert( + !Date.prototype.hasOwnProperty('valueOf'), + 'The value of !Date.prototype.hasOwnProperty(\'valueOf\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T3.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T3.js index 5192ce535fa9..e9c3021e819b 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A1_T3.js @@ -6,15 +6,15 @@ info: The Date.prototype property "valueOf" has { DontEnum } attributes esid: sec-date.prototype.valueof description: Checking DontEnum attribute ---*/ - -if (Date.prototype.propertyIsEnumerable('valueOf')) { - throw new Test262Error('#1: The Date.prototype.valueOf property has the attribute DontEnum'); -} +assert( + !Date.prototype.propertyIsEnumerable('valueOf'), + 'The value of !Date.prototype.propertyIsEnumerable(\'valueOf\') is expected to be true' +); for (var x in Date.prototype) { - if (x === "valueOf") { - throw new Test262Error('#2: The Date.prototype.valueOf has the attribute DontEnum'); - } + assert.notSameValue(x, "valueOf", 'The value of x is not "valueOf"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A2_T1.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A2_T1.js index 4ad337408549..1653792cf066 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A2_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A2_T1.js @@ -7,12 +7,12 @@ esid: sec-date.prototype.valueof description: The "length" property of the "valueOf" is 0 ---*/ -if (Date.prototype.valueOf.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The valueOf has a "length" property'); -} +assert.sameValue( + Date.prototype.valueOf.hasOwnProperty("length"), + true, + 'Date.prototype.valueOf.hasOwnProperty("length") must return true' +); -if (Date.prototype.valueOf.length !== 0) { - throw new Test262Error('#2: The "length" property of the valueOf is 0'); -} +assert.sameValue(Date.prototype.valueOf.length, 0, 'The value of Date.prototype.valueOf.length is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T1.js index 1ef7d37746d3..24e84469c98c 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T1.js @@ -12,8 +12,13 @@ includes: [propertyHelper.js] var x = Date.prototype.valueOf.length; verifyNotWritable(Date.prototype.valueOf, "length", null, 1); -if (Date.prototype.valueOf.length !== x) { - throw new Test262Error('#1: The Date.prototype.valueOf.length has the attribute ReadOnly'); -} + +assert.sameValue( + Date.prototype.valueOf.length, + x, + 'The value of Date.prototype.valueOf.length is expected to equal the value of x' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T2.js index 0bfbe53e459d..9cfe3eab5445 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T2.js @@ -9,12 +9,17 @@ esid: sec-date.prototype.valueof description: Checking DontDelete attribute ---*/ -if (delete Date.prototype.valueOf.length !== true) { - throw new Test262Error('#1: The Date.prototype.valueOf.length property does not have the attributes DontDelete'); -} +assert.sameValue( + delete Date.prototype.valueOf.length, + true, + 'The value of `delete Date.prototype.valueOf.length` is expected to be true' +); -if (Date.prototype.valueOf.hasOwnProperty('length')) { - throw new Test262Error('#2: The Date.prototype.valueOf.length property does not have the attributes DontDelete'); -} +assert( + !Date.prototype.valueOf.hasOwnProperty('length'), + 'The value of !Date.prototype.valueOf.hasOwnProperty(\'length\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T3.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T3.js index bfd508dfd701..5d3dcf9c67fb 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T3.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S15.9.5.8_A3_T3.js @@ -8,15 +8,15 @@ info: | esid: sec-date.prototype.valueof description: Checking DontEnum attribute ---*/ - -if (Date.prototype.valueOf.propertyIsEnumerable('length')) { - throw new Test262Error('#1: The Date.prototype.valueOf.length property has the attribute DontEnum'); -} +assert( + !Date.prototype.valueOf.propertyIsEnumerable('length'), + 'The value of !Date.prototype.valueOf.propertyIsEnumerable(\'length\') is expected to be true' +); for (var x in Date.prototype.valueOf) { - if (x === "length") { - throw new Test262Error('#2: The Date.prototype.valueOf.length has the attribute DontEnum'); - } + assert.notSameValue(x, "length", 'The value of x is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S9.4_A3_T1.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S9.4_A3_T1.js index 049bfe2f6809..65de790c8ea2 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S9.4_A3_T1.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S9.4_A3_T1.js @@ -12,74 +12,50 @@ description: For testing constructor Date(Number) is used // CHECK#1 var d1 = new Date(6.54321); -if (d1.valueOf() !== 6) { - throw new Test262Error('#1: var d1 = new Date(6.54321); d1.valueOf() === 6;'); -} +assert.sameValue(d1.valueOf(), 6, 'd1.valueOf() must return 6'); // CHECK#2 var d2 = new Date(-6.54321); -if (d2.valueOf() !== -6) { - throw new Test262Error('#2: var d2 = new Date(-6.54321); d2.valueOf() === -6;'); -} +assert.sameValue(d2.valueOf(), -6, 'd2.valueOf() must return -6'); // CHECK#3 var d3 = new Date(6.54321e2); -if (d3.valueOf() !== 654) { - throw new Test262Error('#3: var d3 = new Date(6.54321e2); d3.valueOf() === 654;'); -} +assert.sameValue(d3.valueOf(), 654, 'd3.valueOf() must return 654'); // CHECK#4 var d4 = new Date(-6.54321e2); -if (d4.valueOf() !== -654) { - throw new Test262Error('#4: var d4 = new Date(-6.54321e2); d4.valueOf() === -654;'); -} +assert.sameValue(d4.valueOf(), -654, 'd4.valueOf() must return -654'); // CHECK#5 var d5 = new Date(0.654321e1); -if (d5.valueOf() !== 6) { - throw new Test262Error('#5: var d5 = new Date(0.654321e1); d5.valueOf() === 6;'); -} +assert.sameValue(d5.valueOf(), 6, 'd5.valueOf() must return 6'); // CHECK#6 var d6 = new Date(-0.654321e1); -if (d6.valueOf() !== -6) { - throw new Test262Error('#6: var d6 = new Date(-0.654321e1); d6.valueOf() === -6;'); -} +assert.sameValue(d6.valueOf(), -6, 'd6.valueOf() must return -6'); // CHECK#7 var d7 = new Date(true); -if (d7.valueOf() !== 1) { - throw new Test262Error('#7: var d7 = new Date(true); d7.valueOf() === 1;'); -} +assert.sameValue(d7.valueOf(), 1, 'd7.valueOf() must return 1'); // CHECK#8 var d8 = new Date(false); -if (d8.valueOf() !== 0) { - throw new Test262Error('#8: var d8 = new Date(false); d8.valueOf() === 0;'); -} +assert.sameValue(d8.valueOf(), 0, 'd8.valueOf() must return 0'); // CHECK#9 var d9 = new Date(1.23e15); -if (d9.valueOf() !== 1.23e15) { - throw new Test262Error('#9: var d9 = new Date(1.23e15); d9.valueOf() === 1.23e15;'); -} +assert.sameValue(d9.valueOf(), 1.23e15, 'd9.valueOf() must return 1.23e15'); // CHECK#10 var d10 = new Date(-1.23e15); -if (d10.valueOf() !== -1.23e15) { - throw new Test262Error('#10: var d10 = new Date(-1.23e15); d10.valueOf() === -1.23e15;'); -} +assert.sameValue(d10.valueOf(), -1.23e15, 'd10.valueOf() must return -1.23e15'); // CHECK#11 var d11 = new Date(1.23e-15); -if (d11.valueOf() !== 0) { - throw new Test262Error('#11: var d11 = new Date(1.23e-15); d11.valueOf() === 0;'); -} +assert.sameValue(d11.valueOf(), 0, 'd11.valueOf() must return 0'); // CHECK#12 var d12 = new Date(-1.23e-15); -if (d12.valueOf() !== -0) { - throw new Test262Error('#12: var d12 = new Date(-1.23e-15); d12.valueOf() === -0;'); -} +assert.sameValue(d12.valueOf(), 0, 'd12.valueOf() must return 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S9.4_A3_T2.js b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S9.4_A3_T2.js index 4654a3dece21..e1747d60d6f9 100644 --- a/js/src/tests/test262/built-ins/Date/prototype/valueOf/S9.4_A3_T2.js +++ b/js/src/tests/test262/built-ins/Date/prototype/valueOf/S9.4_A3_T2.js @@ -14,26 +14,22 @@ description: > // CHECK#1 var d1 = new Date(Number.NaN); -assert.sameValue(d1.valueOf(), NaN, "NaN"); +assert.sameValue(d1.valueOf(), NaN, 'd1.valueOf() returns NaN'); // CHECK#2 var d2 = new Date(Infinity); -assert.sameValue(d2.valueOf(), NaN, "Infinity"); +assert.sameValue(d2.valueOf(), NaN, 'd2.valueOf() returns NaN'); // CHECK#3 var d3 = new Date(-Infinity); -assert.sameValue(d3.valueOf(), NaN, "-Infinity"); +assert.sameValue(d3.valueOf(), NaN, 'd3.valueOf() returns NaN'); // CHECK#4 var d4 = new Date(0); -if (d4.valueOf() !== 0) { - throw new Test262Error('#4: var d4 = new Date(0); d4.valueOf() === 0;'); -} +assert.sameValue(d4.valueOf(), 0, 'd4.valueOf() must return 0'); // CHECK#5 var d5 = new Date(-0); -if (d5.valueOf() !== -0) { - throw new Test262Error('#5: var d5 = new Date(-0); d5.valueOf() === -0;'); -} +assert.sameValue(d5.valueOf(), 0, 'd5.valueOf() must return 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A1_T1.js b/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A1_T1.js index ddc8bbb4b446..b7f3835e93a0 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A1_T1.js @@ -13,11 +13,11 @@ var proto = Error.prototype; //CHECK#1 verifyNotConfigurable(Error, "prototype"); try { - if ((delete Error.prototype) !== false) { - throw new Test262Error('#1: Error.prototype has the attribute DontDelete'); - } + assert.sameValue(delete Error.prototype, false); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } assert(e instanceof TypeError); } // @@ -31,4 +31,6 @@ if (Error.prototype !== proto) { // ////////////////////////////////////////////////////////////////////////////// +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A2_T1.js b/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A2_T1.js index 645a8fdacf3e..ae59d43325e3 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A2_T1.js @@ -6,21 +6,13 @@ info: Error.prototype property has the attributes {DontEnum} es5id: 15.11.3.1_A2_T1 description: Checking if enumerating the Error.prototype property fails ---*/ +assert(Error.hasOwnProperty('prototype'), 'Error.hasOwnProperty(\'prototype\') must return true'); -////////////////////////////////////////////////////////////////////////////// -//CHECK#0 -if (!(Error.hasOwnProperty('prototype'))) { - throw new Test262Error('#0: Error.hasOwnProperty(\'prototype\') return true. Actual: ' + Error.hasOwnProperty('prototype')); -} -// -////////////////////////////////////////////////////////////////////////////// +assert( + !Error.propertyIsEnumerable('prototype'), + 'The value of !Error.propertyIsEnumerable(\'prototype\') is expected to be true' +); - -////////////////////////////////////////////////////////////////////////////// -// CHECK#1 -if (Error.propertyIsEnumerable('prototype')) { - throw new Test262Error('#1: Error.propertyIsEnumerable(\'prototype\') return false. Actual: ' + Error.propertyIsEnumerable('prototype')); -} // ////////////////////////////////////////////////////////////////////////////// @@ -30,13 +22,13 @@ if (Error.propertyIsEnumerable('prototype')) { var cout = 0; for (var p in Error) { - if (p === "prototype") cout++; + if (p === "prototype") { + cout++; + } } -if (cout !== 0) { - throw new Test262Error('#2: cout === 0. Actual: ' + cout); -} -// -////////////////////////////////////////////////////////////////////////////// +assert.sameValue(cout, 0, 'The value of cout is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A3_T1.js b/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A3_T1.js index 46d2ec17ac3a..c73918fb5a25 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A3_T1.js @@ -7,14 +7,7 @@ es5id: 15.11.3.1_A3_T1 description: Checking if varying the Error.prototype property fails includes: [propertyHelper.js] ---*/ - -////////////////////////////////////////////////////////////////////////////// -//CHECK#1 -if (!(Error.hasOwnProperty('prototype'))) { - throw new Test262Error('#1: Error.hasOwnProperty(\'prototype\') return true. Actual: ' + Error.hasOwnProperty('prototype')); -} -// -////////////////////////////////////////////////////////////////////////////// +assert(Error.hasOwnProperty('prototype')); var __obj = Error.prototype; @@ -22,23 +15,9 @@ verifyNotWritable(Error, "prototype", null, function() { return "shifted"; }); -////////////////////////////////////////////////////////////////////////////// -//CHECK#2 -if (Error.prototype !== __obj) { - throw new Test262Error('#2: __obj = Error.prototype; Error.prototype = function(){return "shifted";}; Error.prototype === __obj. Actual: ' + Error.prototype); -} -// -////////////////////////////////////////////////////////////////////////////// +assert.sameValue(Error.prototype, __obj); + +// TODO: Convert to verifyProperty() format. -////////////////////////////////////////////////////////////////////////////// -//CHECK#3 -try { - Error.prototype(); - throw new Test262Error('#3: "Error.prototype()" lead to throwing exception'); -} catch (e) { - if (e instanceof Test262Error) throw e; -} -// -////////////////////////////////////////////////////////////////////////////// reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A4_T1.js b/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A4_T1.js index ecf984484c72..b98f286a1b45 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A4_T1.js +++ b/js/src/tests/test262/built-ins/Error/prototype/S15.11.3.1_A4_T1.js @@ -6,13 +6,6 @@ info: The Error has property prototype es5id: 15.11.3.1_A4_T1 description: Checking Error.hasOwnProperty('prototype') ---*/ - -////////////////////////////////////////////////////////////////////////////// -//CHECK#1 -if (!(Error.hasOwnProperty('prototype'))) { - throw new Test262Error('#1: Error.hasOwnProperty(\'prototype\') return true. Actual: ' + Error.hasOwnProperty('prototype')); -} -// -////////////////////////////////////////////////////////////////////////////// +assert(Error.hasOwnProperty('prototype'), 'Error.hasOwnProperty(\'prototype\') must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A1.js b/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A1.js index 975e698dbbe5..1c701cc39d1a 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A1.js +++ b/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A1.js @@ -8,13 +8,9 @@ info: | es5id: 15.11.4_A1 description: Get Error.prototype and compare with Object.prototype ---*/ - -////////////////////////////////////////////////////////////////////////////// -// CHECK#1 -if (!Object.prototype.isPrototypeOf(Error.prototype)) { - throw new Test262Error('#1: Object.prototype.isPrototypeOf(Error.prototype) return true. Actual: ' + Object.prototype.isPrototypeOf(Error.prototype)); -} -// -////////////////////////////////////////////////////////////////////////////// +assert( + Object.prototype.isPrototypeOf(Error.prototype), + 'Object.prototype.isPrototypeOf(Error.prototype) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A2.js b/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A2.js index a71101255900..cdd0359b483b 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A2.js +++ b/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A2.js @@ -14,12 +14,6 @@ description: > Error.prototype.toString = Object.prototype.toString; var __tostr = Error.prototype.toString(); -////////////////////////////////////////////////////////////////////////////// -//CHECK#1 -if (__tostr !== "[object Object]") { - throw new Test262Error('#1: Error.prototype.toString=Object.prototype.toString; __tostr = Error.prototype.toString(); __tostr === "[object Object]". Actual: ' + __tostr); -} -// -////////////////////////////////////////////////////////////////////////////// +assert.sameValue(__tostr, "[object Object]", 'The value of __tostr is expected to be "[object Object]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A3.js b/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A3.js index 58c5272d07dc..782c9354839a 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A3.js +++ b/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A3.js @@ -7,15 +7,9 @@ es5id: 15.11.4_A3 description: Checking if call of Error prototype as a function fails ---*/ -////////////////////////////////////////////////////////////////////////////// -//CHECK#1 -try { +assert.throws(TypeError, () => { Error.prototype(); - throw new Test262Error('#1: "Error.prototype()" lead to throwing exception'); -} catch (e) { - if (e instanceof Test262Error) throw e; -} -// -////////////////////////////////////////////////////////////////////////////// + throw new Test262Error(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A4.js b/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A4.js index b87c69728ecb..1bdd74a439df 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A4.js +++ b/js/src/tests/test262/built-ins/Error/prototype/S15.11.4_A4.js @@ -7,15 +7,9 @@ es5id: 15.11.4_A4 description: Checking if creating "new Error.prototype" fails ---*/ -////////////////////////////////////////////////////////////////////////////// -//CHECK#1 -try { - var __instance = new Error.prototype; - throw new Test262Error('#1: "var __instance = new Error.prototype" lead to throwing exception'); -} catch (e) { - if (e instanceof Test262Error) throw e; -} -// -////////////////////////////////////////////////////////////////////////////// +assert.throws(TypeError, () => { + new Error.prototype(); + throw new Test262Error(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/constructor/S15.11.4.1_A1_T2.js b/js/src/tests/test262/built-ins/Error/prototype/constructor/S15.11.4.1_A1_T2.js index 693870d28ec0..5615ded4afe3 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/constructor/S15.11.4.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Error/prototype/constructor/S15.11.4.1_A1_T2.js @@ -15,46 +15,16 @@ var constr = Error.prototype.constructor; var err = new constr; -////////////////////////////////////////////////////////////////////////////// -// CHECK#0 -if (err === undefined) { - throw new Test262Error('#0: constr = Error.prototype.constructor; err = new constr; err === undefined'); -} -// -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -// CHECK#1 -if (err.constructor !== Error) { - throw new Test262Error('#1: constr = Error.prototype.constructor; err = new constr; err.constructor === Error. Actual: ' + err.constructor); -} -// -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -// CHECK#2 -if (!(Error.prototype.isPrototypeOf(err))) { - throw new Test262Error('#2: constr = Error.prototype.constructor; err = new constr; Error.prototype.isPrototypeOf(err) return true. Actual: ' + Error.prototype.isPrototypeOf(err)); -} +assert.notSameValue(err, undefined, 'The value of err is expected to not equal ``undefined``'); +assert.sameValue(err.constructor, Error, 'The value of err.constructor is expected to equal the value of Error'); +assert(Error.prototype.isPrototypeOf(err), 'Error.prototype.isPrototypeOf(err) must return true'); // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // CHECK#3 Error.prototype.toString = Object.prototype.toString; -var to_string_result = '[object ' + 'Error' + ']'; -if (err.toString() !== to_string_result) { - throw new Test262Error('#3: constr = Error.prototype.constructor; err = new constr; Error.prototype.toString=Object.prototype.toString; err.toString() === \'[object Error]\'. Actual: ' + err.toString()); -} -// -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -// CHECK#4 -if (err.valueOf().toString() !== to_string_result) { - throw new Test262Error('#4: constr = Error.prototype.constructor; err = new constr; Error.prototype.toString=Object.prototype.toString; err.valueOf().toString() === \'[object Error]\'. Actual: ' + err.valueOf().toString()); -} -// -////////////////////////////////////////////////////////////////////////////// +assert.sameValue(err.toString(), '[object Error]', 'err.toString() must return "[object Error]"'); +assert.sameValue(err.valueOf().toString(), '[object Error]', 'err.valueOf().toString() must return "[object Error]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Error/prototype/toString/S15.11.4.4_A2.js b/js/src/tests/test262/built-ins/Error/prototype/toString/S15.11.4.4_A2.js index 6c99b6324475..0e8aaff45656 100644 --- a/js/src/tests/test262/built-ins/Error/prototype/toString/S15.11.4.4_A2.js +++ b/js/src/tests/test262/built-ins/Error/prototype/toString/S15.11.4.4_A2.js @@ -4,22 +4,9 @@ /*--- info: The Error.prototype.toString returns an implementation defined string es5id: 15.11.4.4_A2 -description: Checking if call of Error.prototype.toSting() fails +description: Checking if call of Error.prototype.toString() fails ---*/ -////////////////////////////////////////////////////////////////////////////// -// CHECK#1 -var err1 = new Error("Error"); -try { - var toStr = err1.toString(); -} -catch (e) { - throw new Test262Error('#1: var err1=new Error("Error"); var toStr=err1.toString(); lead to throwing exception. Exception is ' + e); -} -if (toStr === undefined) { - throw new Test262Error('#2: var err1=new Error("Error"); var toStr=err1.toString(); toStr!==undefined. Actual: ' + toStr); -} -// -////////////////////////////////////////////////////////////////////////////// +assert.notSameValue(new Error("Error").toString(), undefined, 'The value of toStr is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/gc-has-one-chance-to-call-cleanupCallback.js b/js/src/tests/test262/built-ins/FinalizationRegistry/gc-has-one-chance-to-call-cleanupCallback.js index e9e5dc14f78a..1d373e0eb82c 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/gc-has-one-chance-to-call-cleanupCallback.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/gc-has-one-chance-to-call-cleanupCallback.js @@ -26,7 +26,7 @@ info: | 2. For each FinalizationRegistry finalizationRegistry such that finalizationRegistry.[[Cells]] contains cell, such that cell.[[Target]] is obj, a. Set cell.[[Target]] to empty. b. Optionally, perform ! HostCleanupFinalizationRegistry(finalizationRegistry). -features: [cleanupSome, FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, async-functions, host-gc-required] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, async-functions, host-gc-required] flags: [async, non-deterministic] includes: [async-gc.js, compareArray.js] ---*/ diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/callback-not-callable-throws.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/callback-not-callable-throws.js index 1951092abc30..2e8450b19e64 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/callback-not-callable-throws.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/callback-not-callable-throws.js @@ -13,7 +13,7 @@ info: | 3. If finalizationRegistry does not have a [[Cells]] internal slot, throw a TypeError exception. 4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception. ... -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry] ---*/ assert.sameValue(typeof FinalizationRegistry.prototype.cleanupSome, 'function'); diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-reference.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-reference.js index ee89a432d9c3..d8c23a7d1e02 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-reference.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-reference.js @@ -14,7 +14,7 @@ info: | 4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception. 5. Perform ? CleanupFinalizationRegistry(finalizationRegistry, callback). 6. Return undefined. -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry, host-gc-required] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, host-gc-required] includes: [async-gc.js] flags: [async, non-deterministic] ---*/ diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-unregister.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-unregister.js index 9c26adbb180c..6669be38b219 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-unregister.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-unregister.js @@ -23,7 +23,7 @@ info: | i. Remove cell from finalizationRegistry.[[Cells]]. ii. Set removed to true. 3. Return removed. -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry, host-gc-required] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, host-gc-required] includes: [async-gc.js] flags: [async, non-deterministic] ---*/ diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/custom-this.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/custom-this.js index 2521204f5bcd..1b99dc1917f6 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/custom-this.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/custom-this.js @@ -14,7 +14,7 @@ info: | 4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception. 5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback). 6. Return undefined. -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry] ---*/ var fn = function() {}; diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/holdings-multiple-values.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/holdings-multiple-values.js index cc0561b500ae..4c8d99b11aa4 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/holdings-multiple-values.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/holdings-multiple-values.js @@ -24,7 +24,7 @@ info: | ... -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry, Symbol, host-gc-required] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, Symbol, host-gc-required] includes: [async-gc.js] flags: [async, non-deterministic] ---*/ diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/length.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/length.js index 3bf563aabfb9..797ecd569496 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/length.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/length.js @@ -22,7 +22,7 @@ info: | function object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry] ---*/ verifyProperty(FinalizationRegistry.prototype.cleanupSome, 'length', { diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/name.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/name.js index 26b4d18af023..e71415a2c2d0 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/name.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/name.js @@ -21,7 +21,7 @@ info: | object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry] ---*/ verifyProperty(FinalizationRegistry.prototype.cleanupSome, 'name', { diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/prop-desc.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/prop-desc.js index dd1dbe3e5069..f942e2c1a497 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/prop-desc.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/prop-desc.js @@ -13,7 +13,7 @@ info: | has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. includes: [propertyHelper.js] -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry] ---*/ assert.sameValue(typeof FinalizationRegistry.prototype.cleanupSome, 'function'); diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/reentrancy.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/reentrancy.js index a9c4c9f135cc..ebecca0725d9 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/reentrancy.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/reentrancy.js @@ -9,7 +9,7 @@ description: > info: | FinalizationRegistry.prototype.cleanupSome ( [ callback ] ) -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry, host-gc-required] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, host-gc-required] includes: [async-gc.js] flags: [async, non-deterministic] ---*/ diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined-with-gc.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined-with-gc.js index 098930f6dded..ef1f04b0e714 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined-with-gc.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined-with-gc.js @@ -14,7 +14,7 @@ info: | 4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception. 5. Perform ? CleanupFinalizationRegistry(finalizationRegistry, callback). 6. Return undefined. -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry, arrow-function, async-functions, async-iteration, class, host-gc-required] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, arrow-function, async-functions, async-iteration, class, host-gc-required] includes: [async-gc.js] flags: [async, non-deterministic] ---*/ diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined.js index 3c37b2bd3cae..6a5ff5a6e5f3 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined.js @@ -14,7 +14,7 @@ info: | 4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception. 5. Perform ? CleanupFinalizationRegistry(finalizationRegistry, callback). 6. Return undefined. -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry, arrow-function, async-functions, async-iteration, class] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, arrow-function, async-functions, async-iteration, class] ---*/ var fn = function() {}; diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/this-does-not-have-internal-cells-throws.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/this-does-not-have-internal-cells-throws.js index 88b3221978dd..267e6d3163f4 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/this-does-not-have-internal-cells-throws.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/this-does-not-have-internal-cells-throws.js @@ -13,7 +13,7 @@ info: | 3. If finalizationRegistry does not have a [[Cells]] internal slot, throw a TypeError exception. 4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception. ... -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, WeakSet, WeakMap, FinalizationRegistry, WeakRef] +features: [FinalizationRegistry.prototype.cleanupSome, WeakSet, WeakMap, FinalizationRegistry, WeakRef] ---*/ assert.sameValue(typeof FinalizationRegistry.prototype.cleanupSome, 'function'); diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/this-not-object-throws.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/this-not-object-throws.js index c89a551ef885..0be906620179 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/this-not-object-throws.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/cleanupSome/this-not-object-throws.js @@ -13,7 +13,7 @@ info: | 3. If finalizationRegistry does not have a [[Cells]] internal slot, throw a TypeError exception. 4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception. ... -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry] ---*/ assert.sameValue(typeof FinalizationRegistry.prototype.cleanupSome, 'function'); diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-cell.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-cell.js index bd0abf397b52..ade30e146bbf 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-cell.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-cell.js @@ -30,7 +30,7 @@ info: | i. Remove cell from finalizationRegistry.[[Cells]]. ii. Set removed to true. 3. Return removed. -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, FinalizationRegistry, host-gc-required] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, host-gc-required] includes: [async-gc.js] flags: [async, non-deterministic] ---*/ diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/shell.js b/js/src/tests/test262/built-ins/FinalizationRegistry/shell.js index e32dd4dbd7c4..d23c2fd8110b 100644 --- a/js/src/tests/test262/built-ins/FinalizationRegistry/shell.js +++ b/js/src/tests/test262/built-ins/FinalizationRegistry/shell.js @@ -5,7 +5,7 @@ /*--- description: > Collection of functions used to capture references cleanup from garbage collectors -features: [cleanupSome, FinalizationRegistry, Symbol, async-functions] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, Symbol, async-functions] flags: [non-deterministic] defines: [asyncGC, asyncGCDeref, resolveAsyncGC] ---*/ diff --git a/js/src/tests/test262/built-ins/Function/S10.1.1_A1_T3.js b/js/src/tests/test262/built-ins/Function/S10.1.1_A1_T3.js index b7141cbd2f48..9effff977eda 100644 --- a/js/src/tests/test262/built-ins/Function/S10.1.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Function/S10.1.1_A1_T3.js @@ -11,11 +11,14 @@ description: > object as a constructor ---*/ -//CHECK#1 var x = new function f1() { return 1; }; -if (typeof(x.constructor) !== "function") - throw new Test262Error('#1: typeof(x.constructor)!=="function"'); + +assert.sameValue( + typeof(x.constructor), + "function", + 'The value of `typeof(x.constructor)` is expected to be "function"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.1_A1_T1.js b/js/src/tests/test262/built-ins/Function/S15.3.1_A1_T1.js index 928af1a64592..13a751b43b57 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.1_A1_T1.js @@ -11,32 +11,14 @@ description: Create simple functions and check returned values var f = Function("return arguments[0];"); -//CHECK#1 -if (!(f instanceof Function)) { - throw new Test262Error('#1: f instanceof Function'); -} - -//CHECK#2 -if (f(1) !== 1) { - throw new Test262Error('#2: f(1) !== 1'); -} +assert(f instanceof Function, 'The result of evaluating (f instanceof Function) is expected to be true'); +assert.sameValue(f(1), 1, 'f(1) must return 1'); var g = new Function("return arguments[0];"); -//CHECK#3 -if (!(g instanceof Function)) { - throw new Test262Error('#3: g instanceof Function'); -} - -//CHECK#4 -if (g("A") !== "A") { - throw new Test262Error('#4: g("A") !== "A"'); -} - -//CHECK#5 -if (g("A") !== f("A")) { - throw new Test262Error('#5: g("A") !== f("A")'); -} +assert(g instanceof Function, 'The result of evaluating (g instanceof Function) is expected to be true'); +assert.sameValue(g("A"), "A", 'g("A") must return "A"'); +assert.sameValue(g("A"), f("A"), 'g("A") must return the same value returned by f("A")'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T1.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T1.js index cd7af9cdc4d8..4acc08d7cb24 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T1.js @@ -20,14 +20,11 @@ var body = { } } -//CHECK#1 try { var f = new Function(body); throw new Test262Error('#1: When the Function constructor is called with one argument then body be that argument the following step are taken: call ToString(body)'); } catch (e) { - if (e !== 7) { - throw new Test262Error('#1.1: When the Function constructor is called with one argument then body be that argument the following step are taken: call ToString(body)'); - } + assert.sameValue(e, 7, 'The value of e is expected to be 7'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T10.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T10.js index 5a671cb022ae..96b516287afa 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T10.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T10.js @@ -14,21 +14,13 @@ es5id: 15.3.2.1_A1_T10 description: Value of the function constructor argument is "null" ---*/ -//CHECK#1 try { var f = new Function(null); } catch (e) { throw new Test262Error('#1: test fails with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T11.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T11.js index 8246e5d90654..bbbef017b884 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T11.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T11.js @@ -14,21 +14,13 @@ es5id: 15.3.2.1_A1_T11 description: Value of the function constructor argument is "undefined" ---*/ -//CHECK#1 try { var f = new Function(undefined); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T12.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T12.js index eeb201a5021c..812fac55b8c0 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T12.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T12.js @@ -14,21 +14,13 @@ es5id: 15.3.2.1_A1_T12 description: Value of the function constructor argument is "void 0" ---*/ -//CHECK#1 try { var f = new Function(void 0); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T13.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T13.js index fe8eb7481d1b..2d5138b163fd 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T13.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T13.js @@ -14,14 +14,14 @@ es5id: 15.3.2.1_A1_T13 description: Value of the function constructor argument is "{}" ---*/ -//CHECK#1 try { var f = new Function({}); throw new Test262Error('#1: test failed with error ' + e); } catch (e) { - if (!(e instanceof SyntaxError)) { - throw new Test262Error('#1.1: If body is not parsable as FunctionBody then throw a SyntaxError exception'); - } + assert( + e instanceof SyntaxError, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T2.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T2.js index c996dbe58e1f..fa59de885789 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T2.js @@ -22,21 +22,13 @@ var body = { } }; -//CHECK#1 try { var f = new Function(body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== 1) { - throw new Test262Error('#3: hen the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), 1, 'f() must return 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T3.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T3.js index 915f5da42016..3855e8f181fa 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T3.js @@ -14,21 +14,13 @@ es5id: 15.3.2.1_A1_T3 description: Value of the function constructor argument is 1 ---*/ -//CHECK#1 try { var f = new Function(1); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T4.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T4.js index 1ee0831efe1f..a70dfdffbee8 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T4.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T4.js @@ -16,22 +16,14 @@ description: > specified with "undefined" ---*/ -//CHECK#1 try { var f = new Function(x); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); var x; diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T5.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T5.js index b6cb067a33b5..3e628677277f 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T5.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T5.js @@ -18,21 +18,13 @@ description: > var body = Object("return \'A\'"); -//CHECK#1 try { var f = new Function(body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== "\u0041") { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), "\u0041", 'f() must return "u0041"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T6.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T6.js index 32499569218d..febdfa36fdae 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T6.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T6.js @@ -16,21 +16,13 @@ description: > true;" ---*/ -//CHECK#1 try { var f = new Function("return true;"); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (!(f())) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert(f(), 'f() must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T7.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T7.js index a432bbb01b2c..8f842acd3fac 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T7.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T7.js @@ -16,21 +16,13 @@ description: Value of the function constructor argument is "Object(1)" var body = new Object(1); -//CHECK#1 try { var f = new Function(body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T8.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T8.js index 5542a75dc46f..5caea00ab74d 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T8.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T8.js @@ -16,14 +16,14 @@ description: Value of the function constructor argument is "var 1=1;" var body = "var 1=1;"; -//CHECK#1 try { var f = new Function(body); throw new Test262Error('#1: If body is not parsable as FunctionBody then throw a SyntaxError exception'); } catch (e) { - if (!(e instanceof SyntaxError)) { - throw new Test262Error('#1.1: If body is not parsable as FunctionBody then throw a SyntaxError exception'); - } + assert( + e instanceof SyntaxError, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T9.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T9.js index 154fcf003736..44e47c4ff326 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T9.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A1_T9.js @@ -18,14 +18,7 @@ description: > var f = new Function("return arguments[0];"); -//CHECK#1 -if (!(f instanceof Function)) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument and the following steps are taken...'); -} - -//CHECK#2 -if (f("A") !== "A") { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and the following steps are taken...'); -} +assert(f instanceof Function, 'The result of evaluating (f instanceof Function) is expected to be true'); +assert.sameValue(f("A"), "A", 'f("A") must return "A"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T1.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T1.js index 0879ec5782e1..de53a3228f36 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T1.js @@ -11,21 +11,13 @@ description: > "arg3", "return arg1+arg2+arg3;" ---*/ -//CHECK#1 try { var f = Function("arg1", "arg2", "arg3", "return arg1+arg2+arg3;"); } catch (e) { throw new Test262Error('#1: test failed'); } -//CHECK#2 -if (!(f instanceof Function)) { - throw new Test262Error('#2: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} - -//CHECK#3 -if (f(1, 2, 3) !== 6) { - throw new Test262Error('#3: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} +assert(f instanceof Function, 'The result of evaluating (f instanceof Function) is expected to be true'); +assert.sameValue(f(1, 2, 3), 6, 'f(1, 2, 3) must return 6'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T2.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T2.js index 89ffc53b7148..90d4df122e6f 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T2.js @@ -11,21 +11,13 @@ description: > "arg3", "return arg1+arg2+arg3;" ---*/ -//CHECK#1 try { var f = Function("arg1, arg2", "arg3", "return arg1+arg2+arg3;"); } catch (e) { throw new Test262Error('#1: test failed'); } -//CHECK#2 -if (!(f instanceof Function)) { - throw new Test262Error('#2: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} - -//CHECK#3 -if (f("AB", "BA", 1) !== "ABBA1") { - throw new Test262Error('#3: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} +assert(f instanceof Function, 'The result of evaluating (f instanceof Function) is expected to be true'); +assert.sameValue(f("AB", "BA", 1), "ABBA1", 'f(AB, BA, 1) must return "ABBA1"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T3.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T3.js index 678d4fa4532c..d087c6d0d388 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T3.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T3.js @@ -11,21 +11,13 @@ description: > arg3", "return arg1+arg2+arg3;" ---*/ -//CHECK#1 try { var f = Function("arg1, arg2, arg3", "return arg1+arg2+arg3;"); } catch (e) { throw new Test262Error('#1: test failed'); } -//CHECK#2 -if (!(f instanceof Function)) { - throw new Test262Error('#2: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} - -//CHECK#3 -if (f(1, 1, "ABBA") !== "2ABBA") { - throw new Test262Error('#3: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} +assert(f instanceof Function, 'The result of evaluating (f instanceof Function) is expected to be true'); +assert.sameValue(f(1, 1, "ABBA"), "2ABBA", 'f(1, 1, ABBA) must return "2ABBA"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T4.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T4.js index 1279ca0e6d4b..130295400016 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T4.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T4.js @@ -19,21 +19,13 @@ var p = { } }; -//CHECK#1 try { var f = Function(p, p, p, "return arg1+arg2+arg3;"); } catch (e) { throw new Test262Error('#1: test failed'); } -//CHECK#2 -if (!(f instanceof Function)) { - throw new Test262Error('#2: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} - -//CHECK#3 -if (f(4, "2", "QUESTION") !== "42QUESTION") { - throw new Test262Error('#3: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} +assert(f instanceof Function, 'The result of evaluating (f instanceof Function) is expected to be true'); +assert.sameValue(f(4, "2", "QUESTION"), "42QUESTION", 'f(4, 2, QUESTION) must return "42QUESTION"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T5.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T5.js index 34919909e16b..a3633e65348c 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T5.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T5.js @@ -19,21 +19,13 @@ var p = { } }; -//CHECK#1 try { var f = Function(p + "," + p, p, "return arg1+arg2+arg3;"); } catch (e) { throw new Test262Error('#1: test failed'); } -//CHECK#2 -if (!(f instanceof Function)) { - throw new Test262Error('#2: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} - -//CHECK#3 -if (f("", 1, 2) !== "12") { - throw new Test262Error('#3: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} +assert(f instanceof Function, 'The result of evaluating (f instanceof Function) is expected to be true'); +assert.sameValue(f("", 1, 2), "12", 'f(, 1, 2) must return "12"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T6.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T6.js index 746ff96cac3f..ec54005d70f5 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T6.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A2_T6.js @@ -19,21 +19,13 @@ var p = { } }; -//CHECK#1 try { var f = Function(p + "," + p + "," + p, "return arg1+arg2+arg3;"); } catch (e) { throw new Test262Error('#1: test failed'); } -//CHECK#2 -if (!(f instanceof Function)) { - throw new Test262Error('#2: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} - -//CHECK#3 -if (f("", 1, p) !== "1arg4") { - throw new Test262Error('#3: It is permissible but not necessary to have one argument for each formal parameter to be specified'); -} +assert(f instanceof Function, 'The result of evaluating (f instanceof Function) is expected to be true'); +assert.sameValue(f("", 1, p), "1arg4", 'f(, 1, {toString: function() {return "arg" + (++i)}}) must return "1arg4"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T1.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T1.js index 530007cbc3bf..9db71a9e8c29 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T1.js @@ -30,14 +30,11 @@ var body = { } }; -//CHECK#1 try { var f = new Function(p, body); throw new Test262Error('#1: test failed'); } catch (e) { - if (e !== 1) { - throw new Test262Error('#1.1: i) Let Result(i) be the first argument; ii) Let P be ToString(Result(i))'); - } + assert.sameValue(e, 1, 'The value of e is expected to be 1'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T10.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T10.js index 79a1bfe4be74..57b0e07aefbe 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T10.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T10.js @@ -25,14 +25,14 @@ var p = { } }; -//CHECK#1 try { var f = new Function(p, body); throw new Test262Error('#1: If P is not parsable as a FormalParameterList_opt then throw a SyntaxError exception'); } catch (e) { - if (!(e instanceof SyntaxError)) { - throw new Test262Error('#1.1: If P is not parsable as a FormalParameterList_opt then throw a SyntaxError exception'); - } + assert( + e instanceof SyntaxError, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T11.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T11.js index f99e20816f21..a95e64e09def 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T11.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T11.js @@ -20,21 +20,13 @@ description: > var p = "a,b,c"; -//CHECK#1 try { var f = new Function(p, void 0); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with arguments p, body creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with arguments p, body the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T12.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T12.js index 56ec418e936b..20bae194ee78 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T12.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T12.js @@ -20,21 +20,13 @@ description: > var p = "a,b,c"; -//CHECK#1 try { var f = new Function(p, undefined); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with arguments p, body creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with arguments p, body the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T13.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T13.js index 9c4366147bce..935b46e1a904 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T13.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T13.js @@ -18,21 +18,13 @@ description: Values of the function constructor arguments are "a,b,c" and "null" var p = "a,b,c"; -//CHECK#1 try { var f = new Function(p, null); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with arguments p, body creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with arguments p, body the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T14.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T14.js index 6b1edf9bd9bd..4a8210fbc53a 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T14.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T14.js @@ -20,22 +20,14 @@ description: > var p = "a,b,c"; -//CHECK#1 try { var f = new Function(p, body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with arguments p, body creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with arguments p, body the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); var body; diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T15.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T15.js index 39d00bac6913..ef7d13699212 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T15.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T15.js @@ -18,21 +18,13 @@ description: > strings ---*/ -//CHECK#1 try { var f = new Function("", ""); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with arguments p, body creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== undefined) { - throw new Test262Error('#3: When the Function constructor is called with arguments p, body the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), undefined, 'f() returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T2.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T2.js index ac024e069e9a..ac77392383fb 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T2.js @@ -25,21 +25,13 @@ var p = { }; var body = "return a;"; -//CHECK#1 try { var f = new Function(p, body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with arguments p, body creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f(42) !== 42) { - throw new Test262Error('#3: When the Function constructor is called with arguments p, body creates a new Function object as specified in 13.2'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(42), 42, 'f(42) must return 42'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T3.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T3.js index 6d5e667be796..022feeda7158 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T3.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T3.js @@ -31,19 +31,13 @@ var body = { } }; -//CHECK#1 try { var f = new Function(p, body); throw new Test262Error('#1: test failed'); } catch (e) { - if (e !== "body") { - throw new Test262Error('#1.1: i) Let Result(i) be the first argument; ii) Let P be ToString(Result(i))'); - } + assert.sameValue(e, "body", 'The value of e is expected to be "body"'); } -//CHECK#2 -if (p !== 1) { - throw new Test262Error('#2: i) Let Result(i) be the first argument; ii) Let P be ToString(Result(i))'); -} +assert.sameValue(p, 1, 'The value of p is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T4.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T4.js index eb52876a7bbd..935747f1c372 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T4.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T4.js @@ -20,22 +20,14 @@ description: > var body = "return 1.1;"; -//CHECK#1 try { var f = new Function(p, body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== 1.1) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), 1.1, 'f() must return 1.1'); var p; diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T5.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T5.js index b28ac17eaee6..6025d613be65 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T5.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T5.js @@ -20,21 +20,13 @@ description: > var body = "return \"A\";"; -//CHECK#1 try { var f = new Function(void 0, body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== '\u0041') { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), '\u0041', 'f() must return "u0041"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T6.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T6.js index 7065ba77ff0b..d4a4a2e67c45 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T6.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T6.js @@ -20,14 +20,14 @@ description: > var body = "return true;"; -//CHECK#1 try { var f = new Function(null, body); throw new Test262Error('#1: If P is not parsable as a FormalParameterList_opt then throw a SyntaxError exception'); } catch (e) { - if (!(e instanceof SyntaxError)) { - throw new Test262Error('#1.1: If P is not parsable as a FormalParameterList_opt then throw a SyntaxError exception'); - } + assert( + e instanceof SyntaxError, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T7.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T7.js index 8a9dbf2ba912..b31929b23ae9 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T7.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T7.js @@ -22,21 +22,13 @@ var body = "return a;"; var p = Object("a"); -//CHECK#1 try { var f = new Function(p, body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f(1) !== 1) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(1), 1, 'f(1) must return 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T8.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T8.js index afbe925291fa..15280f6b000b 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T8.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T8.js @@ -20,21 +20,13 @@ description: > var body = "return this;"; -//CHECK#1 try { var f = new Function(undefined, body); } catch (e) { throw new Test262Error('#1: test failed with error ' + e); } -//CHECK#2 -if (f.constructor !== Function) { - throw new Test262Error('#2: When the Function constructor is called with one argument then body be that argument and creates a new Function object as specified in 13.2'); -} - -//CHECK#3 -if (f() !== this) { - throw new Test262Error('#3: When the Function constructor is called with one argument then body be that argument the following steps are taken...'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.sameValue(f(), this, 'f() must return this'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T9.js b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T9.js index 776f92aa5cd6..512aaa826df1 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T9.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2.1_A3_T9.js @@ -21,14 +21,14 @@ description: > var body = "return this;"; var p = "1,1"; -//CHECK#1 try { var f = new Function(p, body); throw new Test262Error('#1: If P is not parsable as a FormalParameterList_opt then throw a SyntaxError exception'); } catch (e) { - if (!(e instanceof SyntaxError)) { - throw new Test262Error('#1.1: If P is not parsable as a FormalParameterList_opt then throw a SyntaxError exception'); - } + assert( + e instanceof SyntaxError, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.2_A1.js b/js/src/tests/test262/built-ins/Function/S15.3.2_A1.js index fbc438eb020a..74138065b8bb 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.2_A1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.2_A1.js @@ -13,14 +13,7 @@ description: > var f = new Function; -//CHECK#1 -if (f.constructor !== Function) { - throw new Test262Error('#1: When Function is called as part of a new expression, it is a constructor: it initialises the newly created object'); -} - -//CHECK#2 -if (f === undefined) { - throw new Test262Error('#2: When Function is called as part of a new expression, it is a constructor: it initialises the newly created object'); -} +assert.sameValue(f.constructor, Function, 'The value of f.constructor is expected to equal the value of Function'); +assert.notSameValue(f, undefined, 'The value of f is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.3_A1.js b/js/src/tests/test262/built-ins/Function/S15.3.3_A1.js index 6cc29d218c7b..81462d9c7305 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.3_A1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.3_A1.js @@ -6,9 +6,6 @@ info: The Function constructor has the property "prototype" es5id: 15.3.3_A1 description: Checking existence of the property "prototype" ---*/ - -if (!Function.hasOwnProperty("prototype")) { - throw new Test262Error('#1: The Function constructor has the property "prototype"'); -} +assert(Function.hasOwnProperty("prototype"), 'Function.hasOwnProperty("prototype") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.3_A2_T1.js b/js/src/tests/test262/built-ins/Function/S15.3.3_A2_T1.js index 40f5d7b2f502..af19e7d60bc6 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.3_A2_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.3_A2_T1.js @@ -8,10 +8,9 @@ info: | es5id: 15.3.3_A2_T1 description: Checking prototype of Function ---*/ - -// CHECK# -if (!(Function.prototype.isPrototypeOf(Function))) { - throw new Test262Error('#1: the value of the internal [[Prototype]] property of the Function constructor is the Function prototype object.'); -} +assert( + Function.prototype.isPrototypeOf(Function), + 'Function.prototype.isPrototypeOf(Function) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.3_A2_T2.js b/js/src/tests/test262/built-ins/Function/S15.3.3_A2_T2.js index 3cc9b6cb6b76..e15dfca7f809 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.3_A2_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.3_A2_T2.js @@ -11,9 +11,6 @@ description: Add new property to Function.prototype and check it Function.prototype.indicator = 1; -//CHECK# -if (Function.indicator != 1) { - throw new Test262Error('#1: the value of the internal [[Prototype]] property of the Function constructor is the Function prototype object.'); -} +assert.sameValue(Function.indicator, 1, 'The value of Function.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.3_A3.js b/js/src/tests/test262/built-ins/Function/S15.3.3_A3.js index 254678ddd84e..56e68be75db3 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.3_A3.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.3_A3.js @@ -6,15 +6,7 @@ info: Function constructor has length property whose value is 1 es5id: 15.3.3_A3 description: Checking Function.length property ---*/ - -//CHECK#1 -if (!Function.hasOwnProperty("length")) { - throw new Test262Error('#1: Function constructor has length property'); -} - -//CHECK#2 -if (Function.length !== 1) { - throw new Test262Error('#2: Function constructor length property value is 1'); -} +assert(Function.hasOwnProperty("length"), 'Function.hasOwnProperty("length") must return true'); +assert.sameValue(Function.length, 1, 'The value of Function.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.5_A1_T1.js b/js/src/tests/test262/built-ins/Function/S15.3.5_A1_T1.js index ed403d99d693..65e07a28de6a 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.5_A1_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.5_A1_T1.js @@ -9,8 +9,10 @@ description: For testing use variable f = new Function var f = new Function; -if (Object.prototype.toString.call(f) !== "[object Function]") { - throw new Test262Error('#1: The value of the [[Class]] property is "Function"'); -} +assert.sameValue( + Object.prototype.toString.call(f), + "[object Function]", + 'Object.prototype.toString.call(new Function) must return "[object Function]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.5_A1_T2.js b/js/src/tests/test262/built-ins/Function/S15.3.5_A1_T2.js index ee1cc8187178..915dc25e18fb 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.5_A1_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.5_A1_T2.js @@ -9,8 +9,10 @@ description: For testing use variable f = Function() var f = Function(); -if (Object.prototype.toString.call(f) !== "[object Function]") { - throw new Test262Error('#1: The value of the [[Class]] property is "Function"'); -} +assert.sameValue( + Object.prototype.toString.call(f), + "[object Function]", + 'Object.prototype.toString.call(Function()) must return "[object Function]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.5_A2_T1.js b/js/src/tests/test262/built-ins/Function/S15.3.5_A2_T1.js index 218419390204..0d13575f7f9c 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.5_A2_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.5_A2_T1.js @@ -6,20 +6,13 @@ info: Every function instance has a [[Call]] property es5id: 15.3.5_A2_T1 description: For testing call Function("var x =1; this.y=2;return \"OK\";")() ---*/ +assert.sameValue( + Function("var x =1; this.y=2;return \"OK\";")(), + "OK", + 'Function("var x =1; this.y=2;return "OK";")() must return "OK"' +); -//CHECK#1 -if (Function("var x =1; this.y=2;return \"OK\";")() !== "OK") { - throw new Test262Error('#1: Every function instance has a [[Call]] property'); -} - -//CHECK#2 -if (typeof x !== "undefined") { - throw new Test262Error('#2: Every function instance has a [[Call]] property'); -} - -//CHECK#3 -if (y !== 2) { - throw new Test262Error('#3: Every function instance has a [[Call]] property'); -} +assert.sameValue(typeof x, "undefined", 'The value of `typeof x` is expected to be "undefined"'); +assert.sameValue(y, 2, 'The value of y is expected to be 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.5_A2_T2.js b/js/src/tests/test262/built-ins/Function/S15.3.5_A2_T2.js index 457d60e89317..cd3611b698d4 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.5_A2_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.5_A2_T2.js @@ -8,20 +8,13 @@ description: > For testing call (new Function("arg1,arg2","var x =arg1; this.y=arg2;return arg1+arg2;"))("1",2) ---*/ +assert.sameValue( + (new Function("arg1,arg2", "var x =arg1; this.y=arg2;return arg1+arg2;"))("1", 2), + "12", + 'new Function("arg1,arg2", "var x =arg1; this.y=arg2;return arg1+arg2;")(1, 2) must return "12"' +); -//CHECK#1 -if ((new Function("arg1,arg2", "var x =arg1; this.y=arg2;return arg1+arg2;"))("1", 2) !== "12") { - throw new Test262Error('#1: Every function instance has a [[Call]] property'); -} - -//CHECK#2 -if (typeof x !== "undefined") { - throw new Test262Error('#2: Every function instance has a [[Call]] property'); -} - -//CHECK#3 -if (y !== 2) { - throw new Test262Error('#3: Every function instance has a [[Call]] property'); -} +assert.sameValue(typeof x, "undefined", 'The value of `typeof x` is expected to be "undefined"'); +assert.sameValue(y, 2, 'The value of y is expected to be 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.5_A3_T1.js b/js/src/tests/test262/built-ins/Function/S15.3.5_A3_T1.js index 46daa0819480..6ffc3cf72cf1 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.5_A3_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.5_A3_T1.js @@ -10,19 +10,8 @@ description: As constructor use Function("var x =1; this.y=2;return \"OK\";") var FACTORY = Function("var x =1; this.y=2;return \"OK\";"); var obj = new FACTORY; -//CHECK#1 -if (typeof obj !== "object") { - throw new Test262Error('#1: every function instance has a [[Construct]] property'); -} - -//CHECK#2 -if (obj.constructor !== FACTORY) { - throw new Test262Error('#2: every function instance has a [[Construct]] property'); -} - -//CHECK#3 -if (obj.y !== 2) { - throw new Test262Error('#3: every function instance has a [[Construct]] property'); -} +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert.sameValue(obj.constructor, FACTORY, 'The value of obj.constructor is expected to equal the value of FACTORY'); +assert.sameValue(obj.y, 2, 'The value of obj.y is expected to be 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3.5_A3_T2.js b/js/src/tests/test262/built-ins/Function/S15.3.5_A3_T2.js index 89990aef1654..c7a26bc9bf87 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3.5_A3_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3.5_A3_T2.js @@ -12,19 +12,8 @@ description: > var FACTORY = new Function("arg1,arg2", "var x =1; this.y=arg1+arg2;return \"OK\";"); var obj = new FACTORY("1", 2); -//CHECK#1 -if (typeof obj !== "object") { - throw new Test262Error('#1: every function instance has a [[Construct]] property'); -} - -//CHECK#2 -if (obj.constructor !== FACTORY) { - throw new Test262Error('#2: every function instance has a [[Construct]] property'); -} - -//CHECK#3 -if (obj.y !== "12") { - throw new Test262Error('#3: every function instance has a [[Construct]] property'); -} +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert.sameValue(obj.constructor, FACTORY, 'The value of obj.constructor is expected to equal the value of FACTORY'); +assert.sameValue(obj.y, "12", 'The value of obj.y is expected to be "12"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A1.js b/js/src/tests/test262/built-ins/Function/S15.3_A1.js index f62c90af744d..5eb50f3d10c7 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A1.js @@ -11,8 +11,6 @@ var obj = Function; var thisobj = this.Function; -if (obj !== thisobj) { - throw new Test262Error('Function is the property of global'); -} +assert.sameValue(obj, thisobj, 'The value of obj is expected to equal the value of thisobj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A2_T1.js b/js/src/tests/test262/built-ins/Function/S15.3_A2_T1.js index ceadc1229012..61b4135e1b37 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A2_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A2_T1.js @@ -10,13 +10,13 @@ es5id: 15.3_A2_T1 description: Checking if executing "Function.call(this, "var x / = 1;")" fails ---*/ -//CHECK# try { Function.call(this, "var x / = 1;"); } catch (e) { - if (!(e instanceof SyntaxError)) { - throw new Test262Error('#1: function body must be valid'); - } + assert( + e instanceof SyntaxError, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A2_T2.js b/js/src/tests/test262/built-ins/Function/S15.3_A2_T2.js index 66a582ee70e0..1c65e11b90a8 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A2_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A2_T2.js @@ -10,13 +10,13 @@ es5id: 15.3_A2_T2 description: Checking if executing "Function.call(this, "var #x = 1;")" fails ---*/ -//CHECK# try { Function.call(this, "var #x = 1;"); } catch (e) { - if (!(e instanceof SyntaxError)) { - throw new Test262Error('#1: function body must be valid'); - } + assert( + e instanceof SyntaxError, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A3_T1.js b/js/src/tests/test262/built-ins/Function/S15.3_A3_T1.js index 3dc476cb7118..b3335ea9bc72 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A3_T1.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A3_T1.js @@ -9,7 +9,6 @@ es5id: 15.3_A3_T1 description: First argument is object ---*/ -//CHECK#1 - does not throw var f = Function.call(mars, "return name;"); var mars = { name: "mars", @@ -21,12 +20,8 @@ var f = Function.call(mars, "this.godname=\"ares\"; return this.color;"); var about_mars = f(); -//CHECK#2 -if (about_mars !== undefined) { - throw new Test262Error('#2: When applied to the Function object itself, thisArg should be ignored'); -} +assert.sameValue(about_mars, undefined); -//CHECK#3 if (this.godname !== "ares" && mars.godname === undefined) { throw new Test262Error('#3: When applied to the Function object itself, thisArg should be ignored'); } diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A3_T2.js b/js/src/tests/test262/built-ins/Function/S15.3_A3_T2.js index 9879804736e2..6c1cf334209f 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A3_T2.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A3_T2.js @@ -14,16 +14,10 @@ var planet = "mars"; var f = Function.call("blablastring", "return this.color;"); -//CHECK#1 -if (f() !== "red") { - throw new Test262Error('#1: '); -} +assert.sameValue(f(), "red", 'f() must return "red"'); var g = Function.call(null, "return this.planet;"); -//CHECK#2 -if (g() !== "mars") { - throw new Test262Error('#2: '); -} +assert.sameValue(g(), "mars", 'g() must return "mars"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A3_T3.js b/js/src/tests/test262/built-ins/Function/S15.3_A3_T3.js index f8a470c4aef5..b795780d5973 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A3_T3.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A3_T3.js @@ -12,32 +12,24 @@ description: First argument is this, and this don`t have needed variable var f = Function.call(this, "return planet;"); var g = Function.call(this, "return color;"); -//CHECK#1 -if (f() !== undefined) { - throw new Test262Error('#1: '); -} +assert.sameValue(f(), undefined, 'f() returns undefined'); var planet = "mars"; -//CHECK#2 -if (f() !== "mars") { - throw new Test262Error('#2: '); -} +assert.sameValue(f(), "mars", 'f() must return "mars"'); -//CHECK#3 try { g(); throw new Test262Error('#3: '); } catch (e) { - if (!(e instanceof ReferenceError)) - throw new Test262Error('#3.1: '); + assert( + e instanceof ReferenceError, + 'The result of evaluating (e instanceof ReferenceError) is expected to be true' + ); } this.color = "red"; -//CHECK#4 -if (g() !== "red") { - throw new Test262Error('#4: '); -} +assert.sameValue(g(), "red", 'g() must return "red"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A3_T4.js b/js/src/tests/test262/built-ins/Function/S15.3_A3_T4.js index 2e0733724f89..0f53c43c301f 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A3_T4.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A3_T4.js @@ -11,16 +11,10 @@ description: First argument is this, and this have needed variable var f = Function.call(this, "return planet;"); -//CHECK#1 -if (f() !== undefined) { - throw new Test262Error('#1: '); -} +assert.sameValue(f(), undefined, 'f() returns undefined'); var planet = "mars"; -//CHECK#2 -if (f() !== "mars") { - throw new Test262Error('#2: '); -} +assert.sameValue(f(), "mars", 'f() must return "mars"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A3_T5.js b/js/src/tests/test262/built-ins/Function/S15.3_A3_T5.js index 6295b83bc885..041166d5b2cc 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A3_T5.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A3_T5.js @@ -14,28 +14,15 @@ description: > var f = Function.call(this, "return this.planet;"); var g = Function.call(this, "return this.color;"); -//CHECK#1 -if (f() !== undefined) { - throw new Test262Error('#2: '); -} +assert.sameValue(f(), undefined, 'f() returns undefined'); var planet = "mars"; -//CHECK#2 -if (f() !== "mars") { - throw new Test262Error('#2: '); -} - -//CHECK#3 -if (g() !== undefined) { - throw new Test262Error('#3: '); -} +assert.sameValue(f(), "mars", 'f() must return "mars"'); +assert.sameValue(g(), undefined, 'g() returns undefined'); this.color = "red"; -//CHECK#4 -if (g() !== "red") { - throw new Test262Error('#4: '); -} +assert.sameValue(g(), "red", 'g() must return "red"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/S15.3_A3_T6.js b/js/src/tests/test262/built-ins/Function/S15.3_A3_T6.js index 3c24942b74b9..e5e0589ea14c 100644 --- a/js/src/tests/test262/built-ins/Function/S15.3_A3_T6.js +++ b/js/src/tests/test262/built-ins/Function/S15.3_A3_T6.js @@ -13,16 +13,10 @@ description: > var f = Function.call(this, "return this.planet;"); -//CHECK#1 -if (f() !== undefined) { - throw new Test262Error('#1: '); -} +assert.sameValue(f(), undefined, 'f() returns undefined'); var planet = "mars"; -//CHECK#2 -if (f() !== "mars") { - throw new Test262Error('#2: '); -} +assert.sameValue(f(), "mars", 'f() must return "mars"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/StrictFunction_reservedwords_with.js b/js/src/tests/test262/built-ins/Function/StrictFunction_reservedwords_with.js index d6b6ffb779ab..46a21ed5f1b8 100644 --- a/js/src/tests/test262/built-ins/Function/StrictFunction_reservedwords_with.js +++ b/js/src/tests/test262/built-ins/Function/StrictFunction_reservedwords_with.js @@ -17,7 +17,7 @@ info: | ---*/ assert.throws(SyntaxError, function() { - new Function("'use strict'; with ({}) {}"); -}); + new Function("'use strict'; with ({}) {}"); +}, '`new Function("\'use strict\'; with ({}) {}")` throws a SyntaxError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/StrictFunction_restricted-properties-strict.js b/js/src/tests/test262/built-ins/Function/StrictFunction_restricted-properties-strict.js index 963a68a8d684..54b35534894d 100644 --- a/js/src/tests/test262/built-ins/Function/StrictFunction_restricted-properties-strict.js +++ b/js/src/tests/test262/built-ins/Function/StrictFunction_restricted-properties-strict.js @@ -16,39 +16,39 @@ function func() {} assert.throws(TypeError, function() { return func.caller; -}); +}, 'return func.caller throws a TypeError exception'); assert.throws(TypeError, function() { func.caller = {}; -}); +}, 'func.caller = {} throws a TypeError exception'); assert.throws(TypeError, function() { return func.arguments; -}); +}, 'return func.arguments throws a TypeError exception'); assert.throws(TypeError, function() { func.arguments = {}; -}); +}, 'func.arguments = {} throws a TypeError exception'); var newfunc = new Function('"use strict"'); -assert.sameValue(newfunc.hasOwnProperty('caller'), false, 'strict Functions created using Function constructor do not have own property "caller"'); -assert.sameValue(newfunc.hasOwnProperty('arguments'), false, 'strict Functions created using Function constructor do not have own property "arguments"'); +assert.sameValue(newfunc.hasOwnProperty('caller'), false, 'newfunc.hasOwnProperty(\'caller\') must return false'); +assert.sameValue(newfunc.hasOwnProperty('arguments'), false, 'newfunc.hasOwnProperty(\'arguments\') must return false'); assert.throws(TypeError, function() { return newfunc.caller; -}); +}, 'return newfunc.caller throws a TypeError exception'); assert.throws(TypeError, function() { newfunc.caller = {}; -}); +}, 'newfunc.caller = {} throws a TypeError exception'); assert.throws(TypeError, function() { return newfunc.arguments; -}); +}, 'return newfunc.arguments throws a TypeError exception'); assert.throws(TypeError, function() { newfunc.arguments = {}; -}); +}, 'newfunc.arguments = {} throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/internals/Call/class-ctor-realm.js b/js/src/tests/test262/built-ins/Function/internals/Call/class-ctor-realm.js index 2d43e4791762..7deb05571d2d 100644 --- a/js/src/tests/test262/built-ins/Function/internals/Call/class-ctor-realm.js +++ b/js/src/tests/test262/built-ins/Function/internals/Call/class-ctor-realm.js @@ -10,7 +10,7 @@ features: [cross-realm, class] const realm = $262.createRealm(); const C = realm.global.eval('(class {})'); -const TE = realm.global.eval('TypeError'); +const TE = realm.global.TypeError; assert.throws(TE, function() { C(); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T1.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T1.js index 9ad0452780c8..25a578ed6c33 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T1.js @@ -11,14 +11,7 @@ description: Checking length property of Function("arg1,arg2,arg3", null) var f = new Function("arg1,arg2,arg3", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} - -//CHECK#2 -if (f.length !== 3) { - throw new Test262Error('#2: The value of the length property is usually an integer that indicates the "typical" number of arguments expected by the function'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); +assert.sameValue(f.length, 3, 'The value of f.length is expected to be 3'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T2.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T2.js index d3f3bb8bb5b1..2f92fd4b70bd 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T2.js @@ -13,14 +13,7 @@ description: > var f = Function("arg1,arg2,arg3", "arg4,arg5", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} - -//CHECK#2 -if (f.length !== 5) { - throw new Test262Error('#2: The value of the length property is usually an integer that indicates the "typical" number of arguments expected by the function'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); +assert.sameValue(f.length, 5, 'The value of f.length is expected to be 5'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T3.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T3.js index 3271a99d31bb..75bb201363b8 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A1_T3.js @@ -13,14 +13,7 @@ description: > var f = new Function("arg1,arg2,arg3", "arg1,arg2", "arg3", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} - -//CHECK#2 -if (f.length !== 6) { - throw new Test262Error('#2: The value of the length property is usually an integer that indicates the "typical" number of arguments expected by the function'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); +assert.sameValue(f.length, 6, 'The value of f.length is expected to be 6'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T1.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T1.js index 4b8ca0f84e34..9950b42daef5 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T1.js @@ -11,24 +11,11 @@ description: > var f = new Function("arg1,arg2,arg3", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); +assert(delete f.length, 'The value of delete f.length is expected to be true'); +assert(!f.hasOwnProperty('length'), 'The value of !f.hasOwnProperty(\'length\') is expected to be true'); +assert.notSameValue(f.length, 3, 'The value of f.length is not 3'); -//CHECK#2 -if (!delete f.length) { - throw new Test262Error('#2: the function.length property does not have the attributes DontDelete.'); -} - -//CHECK#3 -if (f.hasOwnProperty('length')) { - throw new Test262Error('#3: the function.length property does not have the attributes DontDelete.'); -} - -//CHECK#4 -if (f.length === 3) { - throw new Test262Error('#4: the length property does not have the attributes { DontDelete }'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T2.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T2.js index 3b9b9566e346..0eeb054a2d62 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T2.js @@ -11,21 +11,13 @@ description: > var f = Function("arg1,arg2,arg3", "arg4,arg5", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); delete f.length; -//CHECK#2 -if (f.hasOwnProperty('length')) { - throw new Test262Error('#2: the function.length property does not have the attributes DontDelete.'); -} +assert(!f.hasOwnProperty('length'), 'The value of !f.hasOwnProperty(\'length\') is expected to be true'); +assert.notSameValue(f.length, 5, 'The value of f.length is not 5'); -//CHECK#3 -if (f.length === 5) { - throw new Test262Error('#3: the length property does not have the attributes { DontDelete }'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T3.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T3.js index 6b02b5cdb8ca..2bb421ab95f5 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T3.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A2_T3.js @@ -11,21 +11,13 @@ description: > var f = new Function("arg1,arg2,arg3", "arg1,arg2", "arg3", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); delete f.length; -//CHECK#2 -if (f.hasOwnProperty('length')) { - throw new Test262Error('#2: the function.length property does not have the attributes DontDelete.'); -} +assert(!f.hasOwnProperty('length'), 'The value of !f.hasOwnProperty(\'length\') is expected to be true'); +assert.notSameValue(f.length, 6, 'The value of f.length is not 6'); -//CHECK#3 -if (f.length === 6) { - throw new Test262Error('#3: the length property does not have the attributes { DontDelete }'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T1.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T1.js index e512269fddba..0730211a2263 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T1.js @@ -12,31 +12,27 @@ includes: [propertyHelper.js] var f = new Function("arg1,arg2,arg3", "arg4,arg5", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length')); var flength = f.length; verifyNotWritable(f, "length", null, function() {}); -//CHECK#2 -if (f.length !== flength) { - throw new Test262Error('#2: the function.length property has the attributes ReadOnly'); -} +assert.sameValue(f.length, flength); -//CHECK#3 try { f.length(); throw new Test262Error('#3: the function.length property has the attributes ReadOnly'); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } } -//CHECK#4 if (f.length !== 5) { throw new Test262Error('#4: the length property has the attributes { ReadOnly }'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T2.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T2.js index 6640da57c313..e98b6827bc30 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T2.js @@ -12,31 +12,27 @@ includes: [propertyHelper.js] var f = Function("arg1,arg2,arg3", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length')); var flength = f.length; verifyNotWritable(f, "length", null, function() {}); -//CHECK#2 -if (f.length !== flength) { - throw new Test262Error('#2: the function.length property has the attributes ReadOnly'); -} +assert.sameValue(f.length, flength); -//CHECK#3 try { f.length(); throw new Test262Error('#3: the function.length property has the attributes ReadOnly'); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } } -//CHECK#4 if (f.length !== 3) { throw new Test262Error('#4: the length property has the attributes { ReadOnly }'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T3.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T3.js index bcb4dda53795..99ccfd2c3118 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T3.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A3_T3.js @@ -12,31 +12,27 @@ includes: [propertyHelper.js] var f = new Function("arg1,arg2,arg3", "arg1,arg2", "arg3", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length')); var flength = f.length; verifyNotWritable(f, "length", null, function() {}); -//CHECK#2 -if (f.length !== flength) { - throw new Test262Error('#2: the function.length property has the attributes ReadOnly'); -} +assert.sameValue(f.length, flength); -//CHECK#3 try { f.length(); throw new Test262Error('#3: the function.length property has the attributes ReadOnly'); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } } -//CHECK#4 if (f.length !== 6) { throw new Test262Error('#4: the length property has the attributes { ReadOnly }'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T1.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T1.js index b7c365559773..bc4d7d1a49ed 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T1.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T1.js @@ -11,19 +11,15 @@ description: > var f = new Function("arg1,arg2,arg3", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); for (var key in f) { if (key == "length") { var lengthenumed = true; } } -//CHECK#2 -if (lengthenumed) { - throw new Test262Error('#2: the length property has the attributes { DontEnum }'); -} +assert(!lengthenumed, 'The value of !lengthenumed is expected to be true'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T2.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T2.js index d1fc6ac7264d..25ae5037e85a 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T2.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T2.js @@ -11,10 +11,7 @@ description: > var f = Function("arg1,arg2,arg3", "arg5,arg4", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); for (var key in f) { if (key == "length") { @@ -22,9 +19,8 @@ for (var key in f) { } } -//CHECK#2 -if (lengthenumed) { - throw new Test262Error('#2: the length property has the attributes { DontEnum }'); -} +assert(!lengthenumed, 'The value of !lengthenumed is expected to be true'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T3.js b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T3.js index 018ef1510fc4..a0f6255fc7bc 100644 --- a/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T3.js +++ b/js/src/tests/test262/built-ins/Function/length/S15.3.5.1_A4_T3.js @@ -11,10 +11,7 @@ description: > var f = new Function("arg1,arg2,arg3", "arg1,arg2", "arg3", null); -//CHECK#1 -if (!(f.hasOwnProperty('length'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('length'), 'f.hasOwnProperty(\'length\') must return true'); for (var key in f) { if (key == "length") { @@ -22,9 +19,8 @@ for (var key in f) { } } -//CHECK#2 -if (lengthenumed) { - throw new Test262Error('#2: the length property has the attributes { DontEnum }'); -} +assert(!lengthenumed, 'The value of !lengthenumed is expected to be true'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A1.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A1.js index 16967b3debc5..a48cb62845d1 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A1.js @@ -14,18 +14,14 @@ verifyNotWritable(Function, "prototype", null, function() { return "shifted"; }); -//CHECK#1 -if (Function.prototype !== obj) { - throw new Test262Error('#1: the Function.prototype property has the attributes ReadOnly.'); -} +assert.sameValue(Function.prototype, obj, 'The value of Function.prototype is expected to equal the value of obj'); -//CHECK#2 try { - if (Function.prototype() !== undefined) { - throw new Test262Error('#2: the Function.prototype property has the attributes ReadOnly'); - } + assert.sameValue(Function.prototype(), undefined, 'Function.prototype() returns undefined'); } catch (e) { throw new Test262Error('#2.1: the Function.prototype property has the attributes ReadOnly: ' + e); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A2.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A2.js index 391d22f154de..5c865b6c54ca 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A2.js @@ -6,21 +6,22 @@ info: The Function.prototype property has the attribute DontEnum es5id: 15.3.3.1_A2 description: Checking if enumerating the Function.prototype property fails ---*/ - -// CHECK#1 -if (Function.propertyIsEnumerable('prototype')) { - throw new Test262Error('#1: the Function.prototype property has the attributes DontEnum'); -} +assert( + !Function.propertyIsEnumerable('prototype'), + 'The value of !Function.propertyIsEnumerable(\'prototype\') is expected to be true' +); // CHECK#2 var count = 0; for (var p in Function) { - if (p === "prototype") count++; + if (p === "prototype") { + count++; + } } -if (count !== 0) { - throw new Test262Error('#2: the Function.prototype property has the attributes DontEnum'); -} +assert.sameValue(count, 0, 'The value of count is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A3.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A3.js index 82f24d0ae78e..1bf129b24e10 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A3.js @@ -10,19 +10,19 @@ includes: [propertyHelper.js] verifyNotConfigurable(Function, "prototype"); -//CHECK#1 try { - if ((delete Function.prototype) !== false) { - throw new Test262Error('#1: Function.prototype has the attribute DontDelete'); - } + assert.sameValue(delete Function.prototype, false); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } assert(e instanceof TypeError); } -//CHECK#2 if (!(Function.hasOwnProperty('prototype'))) { throw new Test262Error('#2: the Function.prototype property has the attributes DontDelete.'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A4.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A4.js index 58648319ebb4..a5b8cb8e4f10 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.3.1_A4.js @@ -18,9 +18,11 @@ function foo() {} Object.defineProperty(foo, 'prototype', { value: {} }); -if (foo.prototype !== - Object.getOwnPropertyDescriptor(foo, 'prototype').value) { - throw new Test262Error("A function.prototype's descriptor lies"); -} + +assert.sameValue( + foo.prototype, + Object.getOwnPropertyDescriptor(foo, 'prototype').value, + 'The value of foo.prototype is expected to equal the value of Object.getOwnPropertyDescriptor(foo, \'prototype\').value' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A1.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A1.js index 7d15a43b5ce5..b8243f7f3471 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A1.js @@ -8,10 +8,10 @@ info: | es5id: 15.3.4_A1 description: Object.prototype.toString returns [object+[[Class]]+] ---*/ - -if (Object.prototype.toString.call(Function.prototype) !== "[object Function]") { - throw new Test262Error('#2: The Function prototype object is itself a Function ' + - 'object (its [[Class]] is "Function") (15.3.4)'); -} +assert.sameValue( + Object.prototype.toString.call(Function.prototype), + "[object Function]", + 'Object.prototype.toString.call(Function.prototype) must return "[object Function]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T1.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T1.js index 87f003f0f678..940857145e68 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T1.js @@ -9,11 +9,8 @@ es5id: 15.3.4_A2_T1 description: Call Function.prototype() ---*/ -//CHECK#1 try { - if (Function.prototype() !== undefined) { - throw new Test262Error('#1: The Function prototype object is itself a Function object that, when invoked, accepts any arguments and returns undefined'); - } + assert.sameValue(Function.prototype(), undefined, 'Function.prototype() returns undefined'); } catch (e) { throw new Test262Error('#1.1: The Function prototype object is itself a Function object that, when invoked, accepts any arguments and returns undefined: ' + e); } diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T2.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T2.js index 69284d292b84..7d0f2dbb29ae 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T2.js @@ -9,11 +9,8 @@ es5id: 15.3.4_A2_T2 description: Call Function.prototype(null,void 0) ---*/ -//CHECK#1 try { - if (Function.prototype(null, void 0) !== undefined) { - throw new Test262Error('#1: The Function prototype object is itself a Function object that, when invoked, accepts any arguments and returns undefined'); - } + assert.sameValue(Function.prototype(null, void 0), undefined, 'Function.prototype(null, void 0) returns undefined'); } catch (e) { throw new Test262Error('#1.1: The Function prototype object is itself a Function object that, when invoked, accepts any arguments and returns undefined: ' + e); } diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T3.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T3.js index 5542a2e5d05e..f3139932fa20 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A2_T3.js @@ -9,14 +9,7 @@ es5id: 15.3.4_A2_T3 description: Call Function.prototype(x), where x is undefined variable ---*/ -//CHECK#1 -try { - if (Function.prototype(x) !== undefined) { - var x; - throw new Test262Error('#1: The Function prototype object is itself a Function object that, when invoked, accepts any arguments and returns undefined'); - } -} catch (e) { - throw new Test262Error('#1.1: The Function prototype object is itself a Function object that, when invoked, accepts any arguments and returns undefined: ' + e); -} +var x; +assert.sameValue(Function.prototype(x), undefined, 'Function.prototype(x) returns undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A3_T1.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A3_T1.js index 7e1d4829351b..356d5743f7b1 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A3_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A3_T1.js @@ -8,11 +8,10 @@ info: | es5id: 15.3.4_A3_T1 description: Checking prototype of Function.prototype ---*/ - -if (Object.getPrototypeOf(Function.prototype) !== Object.prototype) { - throw new Test262Error('#1: The value of the internal [[Prototype]] property of ' + - 'the Function prototype object is the Object prototype ' + - 'object (15.3.4)'); -} +assert.sameValue( + Object.getPrototypeOf(Function.prototype), + Object.prototype, + 'Object.getPrototypeOf(Function.prototype) returns Object.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A3_T2.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A3_T2.js index 9060ded7c256..b0b0561e3133 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A3_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A3_T2.js @@ -13,9 +13,6 @@ description: > Object.prototype.indicator = 1; -//CHECK#1 -if (Function.prototype.indicator !== 1) { - throw new Test262Error('#1: The value of the internal [[Prototype]] property of the Function prototype object is the Object prototype object (15.3.2.1)'); -} +assert.sameValue(Function.prototype.indicator, 1, 'The value of Function.prototype.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A4.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A4.js index 49d158cd5751..f9acf656c022 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A4.js @@ -9,20 +9,22 @@ info: | es5id: 15.3.4_A4 description: Checking valueOf property at Function.prototype ---*/ +assert.sameValue( + Function.prototype.hasOwnProperty("valueOf"), + false, + 'Function.prototype.hasOwnProperty("valueOf") must return false' +); -//CHECK#1 -if (Function.prototype.hasOwnProperty("valueOf") !== false) { - throw new Test262Error('#1: The Function prototype object does not have a valueOf property of its own'); -} +assert.notSameValue( + typeof Function.prototype.valueOf, + "undefined", + 'The value of typeof Function.prototype.valueOf is not "undefined"' +); -//CHECK#2 -if (typeof Function.prototype.valueOf === "undefined") { - throw new Test262Error('#2: however, it inherits the valueOf property from the Object prototype Object'); -} - -//CHECK#3 -if (Function.prototype.valueOf !== Object.prototype.valueOf) { - throw new Test262Error('#3: however, it inherits the valueOf property from the Object prototype Object'); -} +assert.sameValue( + Function.prototype.valueOf, + Object.prototype.valueOf, + 'The value of Function.prototype.valueOf is expected to equal the value of Object.prototype.valueOf' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A5.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A5.js index 4095d2ebaa47..810420ff434f 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.4_A5.js @@ -11,6 +11,6 @@ description: Checking if creating "new Function.prototype object" fails assert.throws(TypeError, function() { new Function.prototype; -}); +}, '`new Function.prototype` throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.5.2_A1_T1.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.5.2_A1_T1.js index 417d051f8c05..9497828bbf43 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.5.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.5.2_A1_T1.js @@ -12,28 +12,25 @@ includes: [propertyHelper.js] var f = new Function("", null); -//CHECK#1 -if (!(f.hasOwnProperty('prototype'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('prototype')); var fproto = f.prototype; verifyNotConfigurable(f, "prototype"); -//CHECK#2 try { - if ((delete f.prototype) !== false) { - throw new Test262Error('#2: the prototype property has the attributes { DontDelete }'); - } + assert.sameValue(delete f.prototype, false); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } assert(e instanceof TypeError); } -//CHECK#3 if (f.prototype !== fproto) { throw new Test262Error('#3: the prototype property has the attributes { DontDelete }'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/S15.3.5.2_A1_T2.js b/js/src/tests/test262/built-ins/Function/prototype/S15.3.5.2_A1_T2.js index 205a6857f6c5..1f6605344678 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/S15.3.5.2_A1_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/S15.3.5.2_A1_T2.js @@ -12,28 +12,25 @@ includes: [propertyHelper.js] var f = Function(void 0, ""); -//CHECK#1 -if (!(f.hasOwnProperty('prototype'))) { - throw new Test262Error('#1: the function has length property.'); -} +assert(f.hasOwnProperty('prototype')); var fproto = f.prototype; verifyNotConfigurable(f, "prototype"); -//CHECK#2 try { - if ((delete f.prototype) !== false) { - throw new Test262Error('#2: the prototype property has the attributes { DontDelete }'); - } + assert.sameValue(delete f.prototype, false); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } assert(e instanceof TypeError); } -//CHECK#3 if (f.prototype !== fproto) { throw new Test262Error('#3: the prototype property has the attributes { DontDelete }'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A12.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A12.js index a22f76612cf2..d57a3bd809d0 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A12.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A12.js @@ -8,10 +8,10 @@ description: > Checking if obtaining the prototype property of Function.prototype.apply fails ---*/ - -//CHECK#1 -if (Function.prototype.apply.prototype !== undefined) { - throw new Test262Error('#1: Function.prototype.apply has not prototype property' + Function.prototype.apply.prototype); -} +assert.sameValue( + Function.prototype.apply.prototype, + undefined, + 'The value of Function.prototype.apply.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A1_T1.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A1_T1.js index 0b9a3c5ea45e..dee75c43ec5d 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A1_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A1_T1.js @@ -14,25 +14,19 @@ description: > var proto = Function(); -function FACTORY() {}; +function FACTORY() {} FACTORY.prototype = proto; var obj = new FACTORY; -//CHECK#1 -if (typeof obj.apply !== "function") { - throw new Test262Error('#1: apply method accessed'); -} +assert.sameValue(typeof obj.apply, "function", 'The value of `typeof obj.apply` is expected to be "function"'); -//CHECK#2 try { obj.apply(); throw new Test262Error('#2: If the object does not have a [[Call]] property, a TypeError exception is thrown'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2.1: If the object does not have a [[Call]] property, a TypeError exception is thrown'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A1_T2.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A1_T2.js index 906bc19eb2af..3bf968716d46 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A1_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A1_T2.js @@ -12,25 +12,19 @@ description: > property. Prototype of the object is Function.prototype ---*/ -function FACTORY() {}; +function FACTORY() {} FACTORY.prototype = Function.prototype; var obj = new FACTORY; -//CHECK#1 -if (typeof obj.apply !== "function") { - throw new Test262Error('#1: apply method accessed'); -} +assert.sameValue(typeof obj.apply, "function", 'The value of `typeof obj.apply` is expected to be "function"'); -//CHECK#2 try { obj.apply(); throw new Test262Error('#2: If the object does not have a [[Call]] property, a TypeError exception is thrown'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2.1: If the object does not have a [[Call]] property, a TypeError exception is thrown'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T1.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T1.js index 8094910003a7..024b06f90c13 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T1.js @@ -11,9 +11,6 @@ description: Not any arguments at apply function Function("this.field=\"strawberry\"").apply(); -//CHECK#1 -if (this["field"] !== "strawberry") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["field"], "strawberry", 'The value of this["field"] is expected to be "strawberry"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T10.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T10.js index 61bcd06045bb..2b572d62ec1b 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T10.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T10.js @@ -12,9 +12,6 @@ flags: [noStrict] eval(" (function(){this.feat=1}).apply()"); -//CHECK#1 -if (this["feat"] !== 1) { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], 1, 'The value of this["feat"] is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T2.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T2.js index 8310c7bb3dec..91c17f39cfa6 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T2.js @@ -11,9 +11,6 @@ description: Argument at apply function is null Function("this.field=\"green\"").apply(null); -//CHECK#1 -if (this["field"] !== "green") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["field"], "green", 'The value of this["field"] is expected to be "green"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T3.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T3.js index 76cf33d08621..a104a919b72b 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T3.js @@ -11,9 +11,6 @@ description: Argument at apply function is void 0 Function("this.field=\"battle\"").apply(void 0); -//CHECK#1 -if (this["field"] !== "battle") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["field"], "battle", 'The value of this["field"] is expected to be "battle"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T4.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T4.js index 77a3da08ef44..ae0aaa451913 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T4.js @@ -11,9 +11,6 @@ description: Argument at apply function is undefined Function("this.field=\"oil\"").apply(undefined); -//CHECK#1 -if (this["field"] !== "oil") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["field"], "oil", 'The value of this["field"] is expected to be "oil"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T5.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T5.js index 65201c481dbb..7e898f1b287f 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T5.js @@ -13,18 +13,11 @@ description: > function FACTORY() { Function("this.feat=\"in da haus\"").apply(); -}; +} var obj = new FACTORY; -//CHECK#1 -if (this["feat"] !== "in da haus") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} - -//CHECK#2 -if (typeof obj.feat !== "undefined") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], "in da haus", 'The value of this["feat"] is expected to be "in da haus"'); +assert.sameValue(typeof obj.feat, "undefined", 'The value of `typeof obj.feat` is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T6.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T6.js index 6edf5f0fc87f..3da4007a0923 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T6.js @@ -16,18 +16,11 @@ function FACTORY() { (function() { this.feat = "kamon beyba" }).apply(null); -}; +} var obj = new FACTORY; -//CHECK#1 -if (this["feat"] !== "kamon beyba") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} - -//CHECK#2 -if (typeof obj.feat !== "undefined") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], "kamon beyba", 'The value of this["feat"] is expected to be "kamon beyba"'); +assert.sameValue(typeof obj.feat, "undefined", 'The value of `typeof obj.feat` is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T7.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T7.js index c5c3f7d6d70c..db00cfd8adb8 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T7.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T7.js @@ -16,9 +16,6 @@ description: > })(); -//CHECK#1 -if (this["feat"] !== "in da haus") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], "in da haus", 'The value of this["feat"] is expected to be "in da haus"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T8.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T8.js index eda83fd040ac..40fcf50b5797 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T8.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T8.js @@ -18,9 +18,6 @@ flags: [noStrict] }).apply(undefined); })(); -//CHECK#1 -if (this["feat"] !== "kamon beyba") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], "kamon beyba", 'The value of this["feat"] is expected to be "kamon beyba"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T9.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T9.js index 7c29baed0d5d..87ea76102662 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T9.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A3_T9.js @@ -11,9 +11,6 @@ description: Checking by using eval, argument at apply function is void 0 eval(" Function(\"this.feat=1\").apply(void 0) "); -//CHECK#1 -if (this["feat"] !== 1) { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], 1, 'The value of this["feat"] is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T1.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T1.js index 3f6545be5469..ae2c48c6dc6d 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T1.js @@ -13,14 +13,7 @@ var obj = 1; var retobj = Function("this.touched= true; return this;").apply(obj); -//CHECK#1 -if (typeof obj.touched !== "undefined") { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} - -//CHECK#2 -if (!(retobj["touched"])) { - throw new Test262Error('#2: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert.sameValue(typeof obj.touched, "undefined", 'The value of `typeof obj.touched` is expected to be "undefined"'); +assert(retobj["touched"], 'The value of retobj["touched"] is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T2.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T2.js index 65e002511159..051f441a1d4b 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T2.js @@ -13,14 +13,7 @@ var obj = true; var retobj = new Function("this.touched= true; return this;").apply(obj); -//CHECK#1 -if (typeof obj.touched !== "undefined") { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} - -//CHECK#2 -if (!(retobj["touched"])) { - throw new Test262Error('#2: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert.sameValue(typeof obj.touched, "undefined", 'The value of `typeof obj.touched` is expected to be "undefined"'); +assert(retobj["touched"], 'The value of retobj["touched"] is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T3.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T3.js index b0b3ffcd1ddd..42848413ef85 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T3.js @@ -17,14 +17,7 @@ var retobj = (function() { return this; }).apply(obj); -//CHECK#1 -if (typeof obj.touched !== "undefined") { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} - -//CHECK#2 -if (!(retobj["touched"])) { - throw new Test262Error('#2: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert.sameValue(typeof obj.touched, "undefined", 'The value of `typeof obj.touched` is expected to be "undefined"'); +assert(retobj["touched"], 'The value of retobj["touched"] is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T4.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T4.js index 5edee1d45261..4a572f5e0346 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T4.js @@ -17,15 +17,8 @@ f = function() { retobj = f.apply(obj); -//CHECK#1 -if (typeof obj !== "undefined") { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} - -//CHECK#2 -if (!(retobj["touched"])) { - throw new Test262Error('#2: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert.sameValue(typeof obj, "undefined", 'The value of `typeof obj` is expected to be "undefined"'); +assert(retobj["touched"], 'The value of retobj["touched"] is expected to be true'); var obj; diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T5.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T5.js index 4eae2ddafe95..ee39f67ee97d 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T5.js @@ -17,9 +17,6 @@ var obj = {}; f.apply(obj); -//CHECK#1 -if (!(obj.touched)) { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert(obj.touched, 'The value of obj.touched is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T6.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T6.js index e043d779d2e3..1251383daff8 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T6.js @@ -15,9 +15,6 @@ var obj = new String("soap"); this.touched = true; }).apply(obj); -//CHECK#1 -if (!(obj.touched)) { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert(obj.touched, 'The value of obj.touched is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T7.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T7.js index 0c9ee5e26f69..3e73fd5c2244 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T7.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T7.js @@ -13,9 +13,6 @@ var obj = new Number(1); Function("this.touched= true;").apply(obj); -//CHECK#1 -if (!(obj.touched)) { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert(obj.touched, 'The value of obj.touched is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T8.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T8.js index b4b0d1a6a862..4107519a6ecc 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T8.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A5_T8.js @@ -13,9 +13,6 @@ var obj = Function(); new Function("this.touched= true; return this;").apply(obj); -//CHECK#1 -if (!(obj.touched)) { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert(obj.touched, 'The value of obj.touched is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T1.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T1.js index 9c74c0945488..b87d4f9477e7 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T1.js @@ -11,9 +11,6 @@ description: argArray is (null,[1]) Function("a1,a2,a3", "this.shifted=a1;").apply(null, [1]); -//CHECK#1 -if (this["shifted"] !== 1) { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(this["shifted"], 1, 'The value of this["shifted"] is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T10.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T10.js index c4addfc1c1f1..82dbdec6af59 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T10.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T10.js @@ -17,14 +17,12 @@ var obj = {}; Function("a1,a2,a3", "this.shifted=a1+a2+a3;").apply(obj, arguments); })("", 4, 2); -//CHECK#1 -if (obj["shifted"] !== "42") { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(obj["shifted"], "42", 'The value of obj["shifted"] is expected to be "42"'); -//CHECK#2 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#2: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T2.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T2.js index 35834ea3ebb9..6a567da061c3 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T2.js @@ -11,9 +11,6 @@ description: argArray is (null,[1,2,3]) new Function("a1,a2", "a3", "this.shifted=a2;").apply(null, [1, 2, 3]); -//CHECK#1 -if (this["shifted"] !== 2) { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(this["shifted"], 2, 'The value of this["shifted"] is expected to be 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T3.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T3.js index a4413810d35e..cc892830b3a5 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T3.js @@ -21,14 +21,12 @@ var obj = {}; Function(p, "a2,a3", "this.shifted=a1;").apply(obj, new Array("nine", "inch", "nails")); -//CHECK#1 -if (obj["shifted"] !== "nine") { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(obj["shifted"], "nine", 'The value of obj["shifted"] is expected to be "nine"'); -//CHECK#2 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#2: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T4.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T4.js index 2ad746974c3d..cba2cedc0669 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T4.js @@ -25,14 +25,12 @@ new Function(p, p, p, "this.shifted=a3;").apply(obj, (function() { return arguments; })("a", "b", "c")); -//CHECK#1 -if (obj["shifted"] !== "c") { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(obj["shifted"], "c", 'The value of obj["shifted"] is expected to be "c"'); -//CHECK#2 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#2: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T5.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T5.js index 25c6afc46e1a..42df4ad2c047 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T5.js @@ -15,14 +15,7 @@ function FACTORY() { var obj = new FACTORY("", 1, 2); -//CHECK#1 -if (this["shifted"] !== "12") { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} - -//CHECK#2 -if (typeof obj.shifted !== "undefined") { - throw new Test262Error('#2: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(this["shifted"], "12", 'The value of this["shifted"] is expected to be "12"'); +assert.sameValue(typeof obj.shifted, "undefined", 'The value of `typeof obj.shifted` is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T6.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T6.js index c9b404d13e23..fd83bfcb70ad 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T6.js @@ -15,14 +15,12 @@ function FACTORY() { var obj = new FACTORY("", 4, 2); -//CHECK#1 -if (obj["shifted"] !== "42") { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(obj["shifted"], "42", 'The value of obj["shifted"] is expected to be "42"'); -//CHECK#2 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#2: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T7.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T7.js index fcbe0ea841f9..7bea364ab326 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T7.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T7.js @@ -15,9 +15,6 @@ description: > Function("a1,a2,a3", "this.shifted=a1+a2+a3;").apply(null, arguments); })("", 1, 2); -//CHECK#1 -if (this["shifted"] !== "12") { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(this["shifted"], "12", 'The value of this["shifted"] is expected to be "12"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T8.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T8.js index ea06638479c5..cec72bf167a5 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T8.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T8.js @@ -15,9 +15,6 @@ description: > Function("a1,a2,a3", "this.shifted=a1+a2+a3;").apply(this, arguments); })("", 4, 2); -//CHECK#2 -if (this["shifted"] !== "42") { - throw new Test262Error('#2: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(this["shifted"], "42", 'The value of this["shifted"] is expected to be "42"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T9.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T9.js index 95cb1789e6d8..3b5b7295e9e4 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T9.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A7_T9.js @@ -19,14 +19,12 @@ function FACTORY() { var obj = new FACTORY("", 1, 2); -//CHECK#1 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); -//CHECK#2 -if (obj.shifted !== "12") { - throw new Test262Error('#2: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(obj.shifted, "12", 'The value of obj.shifted is expected to be "12"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T1.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T1.js deleted file mode 100644 index f83414e963d2..000000000000 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T1.js +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Function.prototype.apply can`t be used as [[Construct]] caller -es5id: 15.3.4.3_A8_T1 -description: Checking if creating "new Function.prototype.apply" fails ----*/ - -try { - var obj = new Function.prototype.apply; - throw new Test262Error('#1: Function.prototype.apply can\'t be used as [[Construct]] caller'); -} catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.apply can\'t be used as [[Construct]] caller'); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T2.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T2.js deleted file mode 100644 index fbbab18b5dd8..000000000000 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T2.js +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Function.prototype.apply can`t be used as [[Construct]] caller -es5id: 15.3.4.3_A8_T2 -description: Checking if creating "new Function.prototype.apply()" fails ----*/ - -try { - var obj = new Function.prototype.apply(); - throw new Test262Error('#1: Function.prototype.apply can\'t be used as [[Construct]] caller'); -} catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.apply can\'t be used as [[Construct]] caller'); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T3.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T3.js index ef7ed67ad5e3..6abf2d08879e 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T3.js @@ -11,9 +11,7 @@ try { var obj = new Function.apply; throw new Test262Error('#1: Function.prototype.apply can\'t be used as [[Construct]] caller'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.apply can\'t be used as [[Construct]] caller'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T4.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T4.js index 04d805bd7994..d2a4f31ecbb2 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T4.js @@ -11,9 +11,7 @@ try { var obj = new(Function("this.p1=1").apply); throw new Test262Error('#1: Function.prototype.apply can\'t be used as [[Construct]] caller'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.apply can\'t be used as [[Construct]] caller'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T5.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T5.js index 8578c63d937e..f5adac61f123 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T5.js @@ -12,9 +12,7 @@ try { var obj = new FACTORY(); throw new Test262Error('#1: Function.prototype.apply can\'t be used as [[Construct]] caller'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.apply can\'t be used as [[Construct]] caller'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T6.js b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T6.js index c830140f5cef..4f278d44c13b 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/S15.3.4.3_A8_T6.js @@ -9,16 +9,12 @@ description: > f(){this.p1=1;};return f").apply())" fails ---*/ -//CHECK#1 try { var obj = new(Function("function f(){this.p1=1;};return f").apply()); } catch (e) { throw new Test262Error('#1: Function.prototype.apply can\'t be used as [[Construct]] caller'); } -//CHECK#2 -if (obj.p1 !== 1) { - throw new Test262Error('#2: Function.prototype.apply can\'t be used as [[Construct]] caller'); -} +assert.sameValue(obj.p1, 1, 'The value of obj.p1 is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/apply/not-a-constructor.js b/js/src/tests/test262/built-ins/Function/prototype/apply/not-a-constructor.js index ae390849e4bc..43275e54f01e 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/apply/not-a-constructor.js +++ b/js/src/tests/test262/built-ins/Function/prototype/apply/not-a-constructor.js @@ -27,9 +27,12 @@ assert.sameValue( 'isConstructor(Function.prototype.apply) must return false' ); +assert.throws(TypeError, () => { + new Function.prototype.apply; +}, '`new Function.prototype.apply` throws TypeError'); + assert.throws(TypeError, () => { new Function.prototype.apply(); }, '`new Function.prototype.apply()` throws TypeError'); - reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A1.js b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A1.js index df1bee5f050f..6a3d1fc9dd27 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A1.js @@ -18,6 +18,6 @@ function baz() { assert.throws(TypeError, function() { baz(); -}); +}, 'baz() throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A13.js b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A13.js index b17bad8ae124..01147fa0e9e4 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A13.js +++ b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A13.js @@ -8,6 +8,6 @@ description: If IsCallable(func) is false, then throw a TypeError exception. assert.throws(TypeError, function() { Function.prototype.bind.call(undefined, {}); -}); +}, 'Function.prototype.bind.call(undefined, {}) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A14.js b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A14.js index 2412d6d4ac49..ef80439ee130 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A14.js +++ b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A14.js @@ -8,6 +8,6 @@ description: If IsCallable(func) is false, then throw a TypeError exception. assert.throws(TypeError, function() { Function.prototype.bind.call(null, {}); -}); +}, 'Function.prototype.bind.call(null, {}) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A15.js b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A15.js index 9eb8a23f534d..31ea5be65f17 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A15.js +++ b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A15.js @@ -8,6 +8,6 @@ description: If IsCallable(func) is false, then throw a TypeError exception. assert.throws(TypeError, function() { Function.prototype.bind.call({}, {}); -}); +}, 'Function.prototype.bind.call({}, {}) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A16.js b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A16.js index 5b54ba0a247f..22cb39531b67 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A16.js +++ b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A16.js @@ -19,9 +19,7 @@ if (typeof re === 'function') { throw new Test262Error('#1: If IsCallable(func) is false, ' + 'then (bind should) throw a TypeError exception'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: TypeError expected. Actual: ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } } diff --git a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A2.js b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A2.js index 0e26ba2243be..fe00b327a97e 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A2.js @@ -18,6 +18,6 @@ function baz() { assert.throws(TypeError, function() { baz(); -}); +}, 'baz() throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A3.js b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A3.js index 425b5c436bba..334561651a8b 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A3.js @@ -5,9 +5,9 @@ es5id: 15.3.4.5_A3 description: Function.prototype.bind must exist ---*/ - -if (!('bind' in Function.prototype)) { - throw new Test262Error('Function.prototype.bind is missing'); -} +assert( + 'bind' in Function.prototype, + 'The result of evaluating (\'bind\' in Function.prototype) is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A5.js b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A5.js index 87afc9b8af6c..55061a1aa522 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/bind/S15.3.4.5_A5.js @@ -13,8 +13,11 @@ function construct(f, args) { return new bound(); } var d = construct(Date, [1957, 4, 27]); -if (Object.prototype.toString.call(d) !== '[object Date]') { - throw new Test262Error('Using the Date constructor via .bind did not create a Date.'); -} + +assert.sameValue( + Object.prototype.toString.call(d), + '[object Date]', + 'Object.prototype.toString.call(construct(Date, [1957, 4, 27])) must return "[object Date]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A10.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A10.js index d32014eef6eb..fbe9afc864b2 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A10.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A10.js @@ -9,11 +9,10 @@ description: > fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (!(Function.prototype.call.hasOwnProperty('length'))) { - throw new Test262Error('#1: the Function.prototype.call has length property.'); -} +assert( + Function.prototype.call.hasOwnProperty('length'), + 'Function.prototype.call.hasOwnProperty(\'length\') must return true' +); var obj = Function.prototype.call.length; @@ -21,9 +20,12 @@ verifyNotWritable(Function.prototype.call, "length", null, function() { return "shifted"; }); -//CHECK#2 -if (Function.prototype.call.length !== obj) { - throw new Test262Error('#2: the Function.prototype.call length property has the attributes ReadOnly.'); -} +assert.sameValue( + Function.prototype.call.length, + obj, + 'The value of Function.prototype.call.length is expected to equal the value of obj' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A11.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A11.js index be1b8ec98ae9..9263fb61136e 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A11.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A11.js @@ -8,22 +8,21 @@ description: > Checking if enumerating the Function.prototype.call.length property fails ---*/ +assert( + Function.prototype.call.hasOwnProperty('length'), + 'Function.prototype.call.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if (!(Function.prototype.call.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Function.prototype.call has length property.'); -} - - -// CHECK#1 -if (Function.prototype.call.propertyIsEnumerable('length')) { - throw new Test262Error('#1: the Function.prototype.call.length property has the attributes DontEnum'); -} +assert( + !Function.prototype.call.propertyIsEnumerable('length'), + 'The value of !Function.prototype.call.propertyIsEnumerable(\'length\') is expected to be true' +); // CHECK#2 for (var p in Function.prototype.call) { - if (p === "length") - throw new Test262Error('#2: the Function.prototype.call.length property has the attributes DontEnum'); + assert.notSameValue(p, "length", 'The value of p is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A12.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A12.js index e3f1586d8664..1ad9112456ec 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A12.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A12.js @@ -8,10 +8,10 @@ description: > Checking if obtaining the prototype property of Function.prototype.call fails ---*/ - -//CHECK#1 -if (Function.prototype.call.prototype !== undefined) { - throw new Test262Error('#1: Function.prototype.call has not prototype property' + Function.prototype.call.prototype); -} +assert.sameValue( + Function.prototype.call.prototype, + undefined, + 'The value of Function.prototype.call.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A13.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A13.js index ec28751eeef0..4e028072748d 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A13.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A13.js @@ -8,6 +8,6 @@ description: If IsCallable(func) is false, then throw a TypeError exception. assert.throws(TypeError, function() { Function.prototype.call.call(undefined, {}); -}); +}, 'Function.prototype.call.call(undefined, {}) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A14.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A14.js index 3a98c3641359..4d0b259054b5 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A14.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A14.js @@ -8,6 +8,6 @@ description: If IsCallable(func) is false, then throw a TypeError exception. assert.throws(TypeError, function() { Function.prototype.call.call(null, {}); -}); +}, 'Function.prototype.call.call(null, {}) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A15.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A15.js index c4ca5a0914ef..412b447fc4d8 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A15.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A15.js @@ -8,6 +8,6 @@ description: If IsCallable(func) is false, then throw a TypeError exception. assert.throws(TypeError, function() { Function.prototype.call.call({}, {}); -}); +}, 'Function.prototype.call.call({}, {}) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A16.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A16.js index e4ecdafad153..604e931effe2 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A16.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A16.js @@ -19,9 +19,7 @@ if (typeof re === 'function') { throw new Test262Error('#1: If IsCallable(func) is false, ' + 'then (bind should) throw a TypeError exception'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: TypeError expected. Actual: ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } } diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A1_T1.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A1_T1.js index 77d3524780d1..2181d122e717 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A1_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A1_T1.js @@ -14,25 +14,19 @@ description: > var proto = Function(); -function FACTORY() {}; +function FACTORY() {} FACTORY.prototype = proto; var obj = new FACTORY; -//CHECK#1 -if (typeof obj.call !== "function") { - throw new Test262Error('#1: call method accessed'); -} +assert.sameValue(typeof obj.call, "function", 'The value of `typeof obj.call` is expected to be "function"'); -//CHECK#2 try { obj.call(); throw new Test262Error('#2: If the object does not have a [[Call]] property, a TypeError exception is thrown'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2.1: If the object does not have a [[Call]] property, a TypeError exception is thrown'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A1_T2.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A1_T2.js index 432c40e2b937..b0fe479c164f 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A1_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A1_T2.js @@ -12,25 +12,19 @@ description: > property. Prototype of the object is Function.prototype ---*/ -function FACTORY() {}; +function FACTORY() {} FACTORY.prototype = Function.prototype; var obj = new FACTORY; -//CHECK#1 -if (typeof obj.call !== "function") { - throw new Test262Error('#1: call method accessed'); -} +assert.sameValue(typeof obj.call, "function", 'The value of `typeof obj.call` is expected to be "function"'); -//CHECK#2 try { obj.call(); throw new Test262Error('#2: If the object does not have a [[Call]] property, a TypeError exception is thrown'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2.1: If the object does not have a [[Call]] property, a TypeError exception is thrown'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A2_T1.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A2_T1.js index 75da761dd61b..ad0916147734 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A2_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A2_T1.js @@ -6,20 +6,18 @@ info: The length property of the call method is 1 es5id: 15.3.4.4_A2_T1 description: Checking Function.prototype.call.length ---*/ +assert.sameValue( + typeof Function.prototype.call, + "function", + 'The value of `typeof Function.prototype.call` is expected to be "function"' +); -//CHECK#1 -if (typeof Function.prototype.call !== "function") { - throw new Test262Error('#1: call method defined'); -} +assert.notSameValue( + typeof Function.prototype.call.length, + "undefined", + 'The value of typeof Function.prototype.call.length is not "undefined"' +); -//CHECK#2 -if (typeof Function.prototype.call.length === "undefined") { - throw new Test262Error('#2: length property of call method defined'); -} - -//CHECK#3 -if (Function.prototype.call.length !== 1) { - throw new Test262Error('#3: The length property of the call method is 1'); -} +assert.sameValue(Function.prototype.call.length, 1, 'The value of Function.prototype.call.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A2_T2.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A2_T2.js index a10fc9fff382..d0845a1a8566 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A2_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A2_T2.js @@ -9,19 +9,8 @@ description: Checking f.call.length, where f is new Function var f = new Function; -//CHECK#1 -if (typeof f.call !== "function") { - throw new Test262Error('#1: call method accessed'); -} - -//CHECK#2 -if (typeof f.call.length === "undefined") { - throw new Test262Error('#2: length property of call method defined'); -} - -//CHECK#3 -if (f.call.length !== 1) { - throw new Test262Error('#3: The length property of the call method is 1'); -} +assert.sameValue(typeof f.call, "function", 'The value of `typeof f.call` is expected to be "function"'); +assert.notSameValue(typeof f.call.length, "undefined", 'The value of typeof f.call.length is not "undefined"'); +assert.sameValue(f.call.length, 1, 'The value of f.call.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T1.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T1.js index ae1f34a99150..58dd4fa91be3 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T1.js @@ -11,9 +11,6 @@ description: Not any arguments at call function Function("this.field=\"strawberry\"").call(); -//CHECK#1 -if (this["field"] !== "strawberry") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["field"], "strawberry", 'The value of this["field"] is expected to be "strawberry"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T10.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T10.js index 6129c4d14e53..5ba2630d126c 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T10.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T10.js @@ -12,9 +12,6 @@ flags: [noStrict] eval(" (function(){this.feat=1}).call()"); -//CHECK#1 -if (this["feat"] !== 1) { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], 1, 'The value of this["feat"] is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T2.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T2.js index 05b7fb23fd84..b2012d589d51 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T2.js @@ -11,9 +11,6 @@ description: Argument at call function is null Function("this.field=\"green\"").call(null); -//CHECK#1 -if (this["field"] !== "green") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["field"], "green", 'The value of this["field"] is expected to be "green"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T3.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T3.js index cc98b78202f2..770dbb618359 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T3.js @@ -11,9 +11,6 @@ description: Argument at call function is void 0 Function("this.field=\"battle\"").call(void 0); -//CHECK#1 -if (this["field"] !== "battle") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["field"], "battle", 'The value of this["field"] is expected to be "battle"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T4.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T4.js index 8ff0a896a8fe..a7c48ffbef7b 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T4.js @@ -11,9 +11,6 @@ description: Argument at call function is undefined Function("this.field=\"oil\"").call(undefined); -//CHECK#1 -if (this["field"] !== "oil") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["field"], "oil", 'The value of this["field"] is expected to be "oil"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T5.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T5.js index 717dd7ff0af1..7e107200d7b7 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T5.js @@ -13,18 +13,11 @@ description: > function FACTORY() { Function("this.feat=\"in da haus\"").call(); -}; +} var obj = new FACTORY; -//CHECK#1 -if (this["feat"] !== "in da haus") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} - -//CHECK#2 -if (typeof obj.feat !== "undefined") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], "in da haus", 'The value of this["feat"] is expected to be "in da haus"'); +assert.sameValue(typeof obj.feat, "undefined", 'The value of `typeof obj.feat` is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T6.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T6.js index 426f1a6e6c32..1b91976f6dcb 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T6.js @@ -16,18 +16,11 @@ function FACTORY() { (function() { this.feat = "kamon beyba" }).call(null); -}; +} var obj = new FACTORY; -//CHECK#1 -if (this["feat"] !== "kamon beyba") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} - -//CHECK#2 -if (typeof obj.feat !== "undefined") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], "kamon beyba", 'The value of this["feat"] is expected to be "kamon beyba"'); +assert.sameValue(typeof obj.feat, "undefined", 'The value of `typeof obj.feat` is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T7.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T7.js index 75fa8c8ba5c9..4bbb732e069b 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T7.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T7.js @@ -16,9 +16,6 @@ description: > })(); -//CHECK#1 -if (this["feat"] !== "in da haus") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], "in da haus", 'The value of this["feat"] is expected to be "in da haus"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T8.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T8.js index 251febcccf59..7bf141e483ec 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T8.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T8.js @@ -19,9 +19,6 @@ flags: [noStrict] })(); -//CHECK#1 -if (this["feat"] !== "kamon beyba") { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], "kamon beyba", 'The value of this["feat"] is expected to be "kamon beyba"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T9.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T9.js index cfd821b02201..47962ebc3056 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T9.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A3_T9.js @@ -12,9 +12,6 @@ description: Checking by using eval, argument at call function is void 0 eval(" Function(\"this.feat=1\").call(void 0) "); -//CHECK#1 -if (this["feat"] !== 1) { - throw new Test262Error('#1: If thisArg is null or undefined, the called function is passed the global object as the this value'); -} +assert.sameValue(this["feat"], 1, 'The value of this["feat"] is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T1.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T1.js index 2b805c4e640d..4255230d8313 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T1.js @@ -13,14 +13,7 @@ var obj = 1; var retobj = Function("this.touched= true; return this;").call(obj); -//CHECK#1 -if (typeof obj.touched !== "undefined") { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} - -//CHECK#2 -if (!(retobj["touched"])) { - throw new Test262Error('#2: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert.sameValue(typeof obj.touched, "undefined", 'The value of `typeof obj.touched` is expected to be "undefined"'); +assert(retobj["touched"], 'The value of retobj["touched"] is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T2.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T2.js index 77f422ae9ff0..7194b044be40 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T2.js @@ -13,14 +13,7 @@ var obj = true; var retobj = new Function("this.touched= true; return this;").call(obj); -//CHECK#1 -if (typeof obj.touched !== "undefined") { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} - -//CHECK#2 -if (!(retobj["touched"])) { - throw new Test262Error('#2: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert.sameValue(typeof obj.touched, "undefined", 'The value of `typeof obj.touched` is expected to be "undefined"'); +assert(retobj["touched"], 'The value of retobj["touched"] is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T3.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T3.js index 0ad49bf505d9..8b5c52d4d0d5 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T3.js @@ -17,14 +17,7 @@ var retobj = (function() { return this; }).call(obj); -//CHECK#1 -if (typeof obj.touched !== "undefined") { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} - -//CHECK#2 -if (!(retobj["touched"])) { - throw new Test262Error('#2: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert.sameValue(typeof obj.touched, "undefined", 'The value of `typeof obj.touched` is expected to be "undefined"'); +assert(retobj["touched"], 'The value of retobj["touched"] is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T4.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T4.js index f7565e6edef3..f2e10b1020b4 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T4.js @@ -17,15 +17,8 @@ var f = function() { var retobj = f.call(obj); -//CHECK#1 -if (typeof obj !== "undefined") { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} - -//CHECK#2 -if (!(retobj["touched"])) { - throw new Test262Error('#2: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert.sameValue(typeof obj, "undefined", 'The value of `typeof obj` is expected to be "undefined"'); +assert(retobj["touched"], 'The value of retobj["touched"] is expected to be true'); var obj; diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T5.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T5.js index a2aef9d7c674..e1e34c9ade2e 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T5.js @@ -17,9 +17,6 @@ var obj = {}; f.call(obj); -//CHECK#1 -if (!(obj.touched)) { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert(obj.touched, 'The value of obj.touched is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T6.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T6.js index f0ec0415917e..1a1d96d6cf99 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T6.js @@ -15,9 +15,6 @@ var obj = new String("soap"); this.touched = true; }).call(obj); -//CHECK#1 -if (!(obj.touched)) { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert(obj.touched, 'The value of obj.touched is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T7.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T7.js index 79c2a3a2499e..0497ca630d57 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T7.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T7.js @@ -13,9 +13,6 @@ var obj = new Number(1); Function("this.touched= true;").call(obj); -//CHECK#1 -if (!(obj.touched)) { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert(obj.touched, 'The value of obj.touched is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T8.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T8.js index 8208469c8c40..bd7a7d454bac 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T8.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A5_T8.js @@ -13,9 +13,6 @@ var obj = Function(); new Function("this.touched= true; return this;").call(obj); -//CHECK#1 -if (!(obj.touched)) { - throw new Test262Error('#1: If thisArg is not null(defined) the called function is passed ToObject(thisArg) as the this value'); -} +assert(obj.touched, 'The value of obj.touched is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T1.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T1.js index 105c50203594..095ca34cd725 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T1.js @@ -11,19 +11,13 @@ description: Argunemts of call function is (null,[1]) Function("a1,a2,a3", "this.shifted=a1;").call(null, [1]); -//CHECK#1 -if (this["shifted"].constructor !== Array) { - throw new Test262Error('#1: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue( + this["shifted"].constructor, + Array, + 'The value of this["shifted"].constructor is expected to equal the value of Array' +); -//CHECK#2 -if (this["shifted"].length !== 1) { - throw new Test262Error('#2: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} - -//CHECK#3 -if (this["shifted"][0] !== 1) { - throw new Test262Error('#3: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(this["shifted"].length, 1, 'The value of this["shifted"].length is expected to be 1'); +assert.sameValue(this["shifted"][0], 1, 'The value of this["shifted"][0] is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T10.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T10.js index f05f05063e72..dbdc95ea2ac4 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T10.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T10.js @@ -17,14 +17,12 @@ var obj = {}; Function("a1,a2,a3", "this.shifted=a1.length+a2+a3;").call(obj, arguments, "", "2"); })("", 4, 2, "a"); -//CHECK#1 -if (obj["shifted"] !== "42") { - throw new Test262Error('#1: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(obj["shifted"], "42", 'The value of obj["shifted"] is expected to be "42"'); -//CHECK#2 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#2: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T2.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T2.js index 80ff852261e3..55ca9efc3b51 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T2.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T2.js @@ -11,12 +11,8 @@ description: Argunemts of call function is (null,[3,2,1]) new Function("a1,a2", "a3", "this.shifted=a1;").call(null, [3, 2, 1]); -//CHECK#1 -if (this["shifted"].length !== 3) { - throw new Test262Error('#1: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(this["shifted"].length, 3); -//CHECK#2 if ((this["shifted"][0] !== 3) || (this["shifted"][1] !== 2) || (this["shifted"][2] !== 1)) { throw new Test262Error('#2: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); } diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T3.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T3.js index 9ccbad446f85..b64be6bfb107 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T3.js @@ -23,17 +23,12 @@ var obj = {}; Function(p, "a2,a3", "this.shifted=a1;").call(obj, new Array("nine", "inch", "nails")); -//CHECK#1 -if (obj["shifted"].length !== 3) { - throw new Test262Error('#1: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(obj["shifted"].length, 3); -//CHECK#2 if ((obj["shifted"][0] !== "nine") || (obj["shifted"][1] !== "inch") || (obj["shifted"][2] !== "nails")) { throw new Test262Error('#2: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); } -//CHECK#3 if (typeof this["shifted"] !== "undefined") { throw new Test262Error('#3: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); } diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T4.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T4.js index ec9625e8950d..9050ef44f8d7 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T4.js @@ -25,14 +25,12 @@ new Function(p, p, p, "this.shifted=a3+a2+a1.length;").call(obj, (function() { return arguments; })("a", "b", "c", "d"), "", 2); -//CHECK#1 -if (obj["shifted"] !== "24") { - throw new Test262Error('#1: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(obj["shifted"], "24", 'The value of obj["shifted"] is expected to be "24"'); -//CHECK#2 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#2: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T5.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T5.js index 755e873de9e0..232a96d70bcb 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T5.js @@ -17,14 +17,7 @@ function FACTORY() { var obj = new FACTORY("", 1, 2, "A"); -//CHECK#1 -if (this["shifted"] !== "42") { - throw new Test262Error('#1: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} - -//CHECK#2 -if (typeof obj.shifted !== "undefined") { - throw new Test262Error('#2: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(this["shifted"], "42", 'The value of this["shifted"] is expected to be "42"'); +assert.sameValue(typeof obj.shifted, "undefined", 'The value of `typeof obj.shifted` is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T6.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T6.js index 889b425f2256..f69635c16884 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T6.js @@ -17,14 +17,12 @@ function FACTORY() { var obj = new FACTORY("", 4, 2, "A"); -//CHECK#1 -if (obj["shifted"] !== "42") { - throw new Test262Error('#1: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(obj["shifted"], "42", 'The value of obj["shifted"] is expected to be "42"'); -//CHECK#2 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#2: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T7.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T7.js index f801719f0d56..ad606b30934c 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T7.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T7.js @@ -15,9 +15,6 @@ description: > Function("a1,a2,a3", "this.shifted=a1.length+a2+a3;").call(null, arguments, "", 2); })("", 1, 2, true); -//CHECK#1 -if (this["shifted"] !== "42") { - throw new Test262Error('#1: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(this["shifted"], "42", 'The value of this["shifted"] is expected to be "42"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T8.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T8.js index 7222d7fee0dc..7bf2c014a901 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T8.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T8.js @@ -15,9 +15,6 @@ description: > Function("a1,a2,a3", "this.shifted=a1.length+a2+a3;").call(this, arguments, "", 2); })("", 4, 2, null); -//CHECK#2 -if (this["shifted"] !== "42") { - throw new Test262Error('#2: The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object'); -} +assert.sameValue(this["shifted"], "42", 'The value of this["shifted"] is expected to be "42"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T9.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T9.js index 788a273d5488..cca95016d207 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T9.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A6_T9.js @@ -19,14 +19,12 @@ function FACTORY() { var obj = new FACTORY("", 1, 2, void 0); -//CHECK#1 -if (typeof this["shifted"] !== "undefined") { - throw new Test262Error('#1: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue( + typeof this["shifted"], + "undefined", + 'The value of `typeof this["shifted"]` is expected to be "undefined"' +); -//CHECK#2 -if (obj.shifted !== "42") { - throw new Test262Error('#2: If argArray is either an array or an arguments object, the function is passed the...'); -} +assert.sameValue(obj.shifted, "42", 'The value of obj.shifted is expected to be "42"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T1.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T1.js deleted file mode 100644 index 46937f839a8b..000000000000 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T1.js +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Function.prototype.call can't be used as [[Construct]] caller -es5id: 15.3.4.4_A7_T1 -description: Checking if creating "new Function.prototype.call" fails ----*/ - -try { - var obj = new Function.prototype.call; - throw new Test262Error('#1: Function.prototype.call can\'t be used as [[Construct]] caller'); -} catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.call can\'t be used as [[Construct]] caller'); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T2.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T2.js deleted file mode 100644 index c86d9fe3ac6c..000000000000 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T2.js +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Function.prototype.call can't be used as [[Construct]] caller -es5id: 15.3.4.4_A7_T2 -description: Checking if creating "new Function.prototype.call()" fails ----*/ - -try { - var FACTORY = Function.prototype.call; - var obj = new FACTORY(); - throw new Test262Error('#1: Function.prototype.call can\'t be used as [[Construct]] caller'); -} catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.call can\'t be used as [[Construct]] caller'); - } -} - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T3.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T3.js index 71843f468fde..c567e3cd9972 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T3.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T3.js @@ -11,9 +11,7 @@ try { var obj = new Function.call; throw new Test262Error('#1: Function.prototype.call can\'t be used as [[Construct]] caller'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.call can\'t be used as [[Construct]] caller'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T4.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T4.js index f2c988889e00..0134e8f31522 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T4.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T4.js @@ -11,9 +11,7 @@ try { var obj = new(Function("this.p1=1").call); throw new Test262Error('#1: Function.prototype.call can\'t be used as [[Construct]] caller'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.call can\'t be used as [[Construct]] caller'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T5.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T5.js index 49a20ced0774..2c911dda0b4c 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T5.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T5.js @@ -12,9 +12,7 @@ try { var obj = new FACTORY(); throw new Test262Error('#1: Function.prototype.call can\'t be used as [[Construct]] caller'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1.1: Function.prototype.call can\'t be used as [[Construct]] caller'); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T6.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T6.js index 68ec1f77433e..5e0c6494de0e 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A7_T6.js @@ -9,16 +9,12 @@ description: > f(){this.p1=1;};return f").call())" fails ---*/ -//CHECK#1 try { var obj = new(Function("function f(){this.p1=1;};return f").call()); } catch (e) { throw new Test262Error('#1: Function.prototype.call can\'t be used as [[Construct]] caller'); } -//CHECK#2 -if (obj.p1 !== 1) { - throw new Test262Error('#2: Function.prototype.call can\'t be used as [[Construct]] caller'); -} +assert.sameValue(obj.p1, 1, 'The value of obj.p1 is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A9.js b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A9.js index a8a5caa9a0bf..043f28af3cdd 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A9.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/S15.3.4.4_A9.js @@ -10,20 +10,21 @@ description: > Checking if deleting the Function.prototype.call.length property fails ---*/ +assert( + Function.prototype.call.hasOwnProperty('length'), + 'Function.prototype.call.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if (!(Function.prototype.call.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Function.prototype.call has length property'); -} +assert( + delete Function.prototype.call.length, + 'The value of delete Function.prototype.call.length is expected to be true' +); -//CHECK#1 -if (!delete Function.prototype.call.length) { - throw new Test262Error('#1: The Function.prototype.call.length property does not have the attributes DontDelete'); -} +assert( + !Function.prototype.call.hasOwnProperty('length'), + 'The value of !Function.prototype.call.hasOwnProperty(\'length\') is expected to be true' +); -//CHECK#2 -if (Function.prototype.call.hasOwnProperty('length')) { - throw new Test262Error('#2: The Function.prototype.call.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/call/not-a-constructor.js b/js/src/tests/test262/built-ins/Function/prototype/call/not-a-constructor.js index 6858ea919444..1ae179235e27 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/call/not-a-constructor.js +++ b/js/src/tests/test262/built-ins/Function/prototype/call/not-a-constructor.js @@ -31,5 +31,13 @@ assert.throws(TypeError, () => { new Function.prototype.call(); }, '`new Function.prototype.call()` throws TypeError'); +assert.throws(TypeError, () => { + new Function.prototype.call; +}, '`new Function.prototype.call` throws TypeError'); + +var call = Function.prototype.call; +assert.throws(TypeError, () => { + new call; +}, '`new call()` throws TypeError'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/constructor/S15.3.4.1_A1_T1.js b/js/src/tests/test262/built-ins/Function/prototype/constructor/S15.3.4.1_A1_T1.js index 4e6b0f0f9ab6..95b8bc023cbe 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/constructor/S15.3.4.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Function/prototype/constructor/S15.3.4.1_A1_T1.js @@ -8,10 +8,10 @@ info: | es5id: 15.3.4.1_A1_T1 description: Checking Function.prototype.constructor ---*/ - -//CHECK#1 -if (Function.prototype.constructor !== Function) { - throw new Test262Error('#1: The initial value of Function.prototype.constructor is the built-in Function constructor'); -} +assert.sameValue( + Function.prototype.constructor, + Function, + 'The value of Function.prototype.constructor is expected to equal the value of Function' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/restricted-property-arguments.js b/js/src/tests/test262/built-ins/Function/prototype/restricted-property-arguments.js index 477cd51805b8..fc2a877636d4 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/restricted-property-arguments.js +++ b/js/src/tests/test262/built-ins/Function/prototype/restricted-property-arguments.js @@ -3,8 +3,7 @@ /*--- description: Intrinsic %FunctionPrototype% has poisoned own property "arguments" -includes: - - propertyHelper.js +includes: [propertyHelper.js] es6id: 8.2.2 S12, 9.2.7 ---*/ diff --git a/js/src/tests/test262/built-ins/Function/prototype/restricted-property-caller.js b/js/src/tests/test262/built-ins/Function/prototype/restricted-property-caller.js index d8164c843a5e..23daa62fddf9 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/restricted-property-caller.js +++ b/js/src/tests/test262/built-ins/Function/prototype/restricted-property-caller.js @@ -3,8 +3,7 @@ /*--- description: Intrinsic %FunctionPrototype% has poisoned own property "caller" -includes: - - propertyHelper.js +includes: [propertyHelper.js] es6id: 8.2.2 S12, 9.2.7 ---*/ diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A10.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A10.js index 579640731068..66a078c52cd2 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A10.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A10.js @@ -9,19 +9,21 @@ description: > property fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (!(Function.prototype.toString.hasOwnProperty('length'))) { - throw new Test262Error('#1: the Function.prototype.toString has length property.'); -} +assert( + Function.prototype.toString.hasOwnProperty('length'), + 'Function.prototype.toString.hasOwnProperty(\'length\') must return true' +); var obj = Function.prototype.toString.length; verifyNotWritable(Function.prototype.toString, "length", null, function(){return "shifted";}); -//CHECK#2 -if (Function.prototype.toString.length !== obj) { - throw new Test262Error('#2: the Function.prototype.toString length property has the attributes ReadOnly.'); -} +assert.sameValue( + Function.prototype.toString.length, + obj, + 'The value of Function.prototype.toString.length is expected to equal the value of obj' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A11.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A11.js index c401db2c9576..380f72c93f44 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A11.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A11.js @@ -6,15 +6,15 @@ info: The length property of the toString method is 0 es5id: 15.3.4.2_A11 description: Checking Function.prototype.toString.length ---*/ +assert( + Function.prototype.toString.hasOwnProperty("length"), + 'Function.prototype.toString.hasOwnProperty("length") must return true' +); -//CHECK#1 -if (!(Function.prototype.toString.hasOwnProperty("length"))) { - throw new Test262Error('#1: The Function.prototype.toString has the length property'); -} - -//CHECK#2 -if (Function.prototype.toString.length !== 0) { - throw new Test262Error('#2: The length property of the toString method is 0'); -} +assert.sameValue( + Function.prototype.toString.length, + 0, + 'The value of Function.prototype.toString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A12.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A12.js index e6b90da9a8e8..854d7ee3599d 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A12.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A12.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Function.prototype.toString.call(undefined); -}); +}, 'Function.prototype.toString.call(undefined) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A13.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A13.js index 19f624e3cdb9..59400e6d15a8 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A13.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A13.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Function.prototype.toString.call(null); -}); +}, 'Function.prototype.toString.call(null) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A14.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A14.js index ad895cfb13ea..eabf5af56835 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A14.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A14.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Function.prototype.toString.call({}); -}); +}, 'Function.prototype.toString.call({}) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A16.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A16.js index 13cf65c94c74..308b4ffbd46d 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A16.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A16.js @@ -16,6 +16,6 @@ var obj = {toString: Function.prototype.toString}; assert.throws(TypeError, function() { String(obj); -}); +}, 'String(obj) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A6.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A6.js index 3c9accea606c..8a6acb5b5881 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A6.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A6.js @@ -8,10 +8,10 @@ description: > Checking if obtaining the prototype property of Function.prototype.toString fails ---*/ - -//CHECK#1 -if (Function.prototype.toString.prototype !== undefined) { - throw new Test262Error('#1: Function.prototype.toString has not prototype property'+Function.prototype.toString.prototype); -} +assert.sameValue( + Function.prototype.toString.prototype, + undefined, + 'The value of Function.prototype.toString.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A7.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A7.js deleted file mode 100644 index 4da4238fe5fb..000000000000 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A7.js +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Function.prototype.toString can't be used as constructor -es5id: 15.3.4.2_A7 -description: Checking if creating "new Function.prototype.toString" fails ----*/ - -var FACTORY = Function.prototype.toString; - -assert.throws(TypeError, function() { - new FACTORY; -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A8.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A8.js index f3929e648776..d8cf033e4d1e 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A8.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A8.js @@ -8,22 +8,21 @@ description: > Checking if enumerating the Function.prototype.toString.length property fails ---*/ +assert( + Function.prototype.toString.hasOwnProperty('length'), + 'Function.prototype.toString.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if (!(Function.prototype.toString.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Function.prototype.toString has length property.'); -} - - -// CHECK#1 -if (Function.prototype.toString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: the Function.prototype.toString.length property has the attributes DontEnum'); -} +assert( + !Function.prototype.toString.propertyIsEnumerable('length'), + 'The value of !Function.prototype.toString.propertyIsEnumerable(\'length\') is expected to be true' +); // CHECK#2 for (var p in Function.prototype.toString){ - if (p==="length") - throw new Test262Error('#2: the Function.prototype.toString.length property has the attributes DontEnum'); + assert.notSameValue(p, "length", 'The value of p is not "length"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A9.js b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A9.js index ebbc6da37371..5e2676e33080 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A9.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/S15.3.4.2_A9.js @@ -10,20 +10,21 @@ description: > Checking if deleting the Function.prototype.toString.length property fails ---*/ +assert( + Function.prototype.toString.hasOwnProperty('length'), + 'Function.prototype.toString.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if (!(Function.prototype.toString.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Function.prototype.toString has length property'); -} +assert( + delete Function.prototype.toString.length, + 'The value of delete Function.prototype.toString.length is expected to be true' +); -//CHECK#1 -if (!delete Function.prototype.toString.length) { - throw new Test262Error('#1: The Function.prototype.toString.length property does not have the attributes DontDelete'); -} +assert( + !Function.prototype.toString.hasOwnProperty('length'), + 'The value of !Function.prototype.toString.hasOwnProperty(\'length\') is expected to be true' +); -//CHECK#2 -if (Function.prototype.toString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Function.prototype.toString.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Function/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Function/prototype/toString/not-a-constructor.js index b8f98d243682..b13c0c51a27b 100644 --- a/js/src/tests/test262/built-ins/Function/prototype/toString/not-a-constructor.js +++ b/js/src/tests/test262/built-ins/Function/prototype/toString/not-a-constructor.js @@ -31,5 +31,9 @@ assert.throws(TypeError, () => { new Function.prototype.toString(); }, '`new Function.prototype.toString()` throws TypeError'); +var toString = Function.prototype.toString; +assert.throws(TypeError, () => { + new toString; +}, '`new toString` throws TypeError'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A1.js b/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A1.js index d2846b887675..5d590b58c084 100644 --- a/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A1.js +++ b/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A1.js @@ -6,26 +6,14 @@ info: The initial value of Infinity is Number.POSITIVE_INFINITY es5id: 15.1.1.2_A1 description: Use typeof, isNaN, isFinite ---*/ +assert.sameValue(typeof(Infinity), "number", 'The value of `typeof(Infinity)` is expected to be "number"'); +assert.sameValue(isFinite(Infinity), false, 'isFinite(Infinity) must return false'); +assert.sameValue(isNaN(Infinity), false, 'isNaN(Infinity) must return false'); -// CHECK#1 -if (typeof(Infinity) !== "number") { - throw new Test262Error('#1: typeof(Infinity) === "number". Actual: ' + (typeof(Infinity))); -} - -// CHECK#2 -if (isFinite(Infinity) !== false) { - throw new Test262Error('#2: Infinity === Not-a-Finite. Actual: ' + (Infinity)); -} - -// CHECK#3 -if (isNaN(Infinity) !== false) { - throw new Test262Error('#3: Infinity === Not-a-Number. Actual: ' + (Infinity)); -} - - -// CHECK#4 -if (Infinity !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#4: Infinity === Number.POSITIVE_INFINITY. Actual: ' + (Infinity)); -} +assert.sameValue( + Infinity, + Number.POSITIVE_INFINITY, + 'The value of Infinity is expected to equal the value of Number.POSITIVE_INFINITY' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A2_T2.js b/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A2_T2.js index 2353668b1f92..ab3a30005c25 100644 --- a/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A2_T2.js +++ b/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A2_T2.js @@ -10,8 +10,8 @@ flags: [noStrict] // CHECK#1 Infinity = true; -if (typeof(Infinity) === "boolean") { - throw new Test262Error('#1: Infinity = true; typeof(Infinity) !== "boolean". Actual: ' + (typeof(Infinity))); -} +assert.notSameValue(typeof(Infinity), "boolean", 'The value of typeof(Infinity) is not "boolean"'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A3_T2.js b/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A3_T2.js index f3a299cca3f8..c168f458a0fa 100644 --- a/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A3_T2.js +++ b/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A3_T2.js @@ -7,10 +7,8 @@ es5id: 15.1.1.2_A3_T2 description: Use delete flags: [noStrict] ---*/ +assert.sameValue(delete Infinity, false, 'The value of `delete Infinity` is expected to be false'); -// CHECK#1 -if (delete Infinity !== false) { - throw new Test262Error('#1: delete Infinity === false. Actual: ' + (delete Infinity)); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A4.js b/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A4.js index cd12aa07679b..c54ce9e7c11a 100644 --- a/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A4.js +++ b/js/src/tests/test262/built-ins/Infinity/S15.1.1.2_A4.js @@ -9,9 +9,9 @@ description: Use for-in statement // CHECK#1 for (var prop in this) { - if (prop === "Infinity") { - throw new Test262Error('#1: The Infinity is DontEnum'); - } + assert.notSameValue(prop, "Infinity", 'The value of prop is not "Infinity"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/S15.12.2_A1.js b/js/src/tests/test262/built-ins/JSON/parse/S15.12.2_A1.js index 5f0d77d7aa0b..2de3caa3c943 100644 --- a/js/src/tests/test262/built-ins/JSON/parse/S15.12.2_A1.js +++ b/js/src/tests/test262/built-ins/JSON/parse/S15.12.2_A1.js @@ -8,11 +8,13 @@ description: Tests that JSON.parse treats "__proto__" as a regular property name ---*/ var x = JSON.parse('{"__proto__":[]}'); -if (Object.getPrototypeOf(x) !== Object.prototype) { - throw new Test262Error('#1: JSON.parse confused by "__proto__"'); -} -if (!Array.isArray(x.__proto__)) { - throw new Test262Error('#2: JSON.parse did not set "__proto__" as a regular property'); -} + +assert.sameValue( + Object.getPrototypeOf(x), + Object.prototype, + 'Object.getPrototypeOf("JSON.parse(\'{"__proto__":[]}\')") returns Object.prototype' +); + +assert(Array.isArray(x.__proto__), 'Array.isArray(x.__proto__) must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Map/bigint-number-same-value.js b/js/src/tests/test262/built-ins/Map/bigint-number-same-value.js new file mode 100644 index 000000000000..783afd421b4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Map/bigint-number-same-value.js @@ -0,0 +1,46 @@ +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-map.prototype.set +description: > + Observing the expected behavior of keys when a BigInt and Number have + the same value. +info: | + Map.prototype.set ( key , value ) + + ... + Let p be the Record {[[key]]: key, [[value]]: value}. + Append p as the last element of entries. + ... + +features: [BigInt] +---*/ + +const number = 9007199254740991; +const bigint = 9007199254740991n; + +const m = new Map([ + [number, number], + [bigint, bigint], +]); + +assert.sameValue(m.size, 2); +assert.sameValue(m.has(number), true); +assert.sameValue(m.has(bigint), true); + +assert.sameValue(m.get(number), number); +assert.sameValue(m.get(bigint), bigint); + +m.delete(number); +assert.sameValue(m.size, 1); +assert.sameValue(m.has(number), false); +m.delete(bigint); +assert.sameValue(m.size, 0); +assert.sameValue(m.has(bigint), false); + +m.set(number, number); +assert.sameValue(m.size, 1); +m.set(bigint, bigint); +assert.sameValue(m.size, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Map/constructor.js b/js/src/tests/test262/built-ins/Map/constructor.js index f96f47fd44fc..f37c74de67de 100644 --- a/js/src/tests/test262/built-ins/Map/constructor.js +++ b/js/src/tests/test262/built-ins/Map/constructor.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1 +esid: sec-map-constructor description: > The Map constructor is the %Map% intrinsic object and the initial value of the Map property of the global object. diff --git a/js/src/tests/test262/built-ins/Map/does-not-throw-when-set-is-not-callable.js b/js/src/tests/test262/built-ins/Map/does-not-throw-when-set-is-not-callable.js index d61fa0435e6c..9d758b00161d 100644 --- a/js/src/tests/test262/built-ins/Map/does-not-throw-when-set-is-not-callable.js +++ b/js/src/tests/test262/built-ins/Map/does-not-throw-when-set-is-not-callable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Creating a new Map object without arguments doesn't throw if `set` is not callable diff --git a/js/src/tests/test262/built-ins/Map/get-set-method-failure.js b/js/src/tests/test262/built-ins/Map/get-set-method-failure.js index 0f00f969cf3b..978a6a3a2720 100644 --- a/js/src/tests/test262/built-ins/Map/get-set-method-failure.js +++ b/js/src/tests/test262/built-ins/Map/get-set-method-failure.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > new Map returns abrupt from getting Map.prototype.set. info: | diff --git a/js/src/tests/test262/built-ins/Map/iterable-calls-set.js b/js/src/tests/test262/built-ins/Map/iterable-calls-set.js index 56fd358a2bb6..26c58a78d104 100644 --- a/js/src/tests/test262/built-ins/Map/iterable-calls-set.js +++ b/js/src/tests/test262/built-ins/Map/iterable-calls-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > new Map calls `set` for each item on the iterable argument in order. info: | @@ -36,8 +36,8 @@ var map = new Map(iterable); assert.sameValue(counter, 2, "`Map.prototype.set` called twice."); -assert(compareArray(results[0], iterable[0])); -assert(compareArray(results[1], iterable[1])); +assert.compareArray(results[0], iterable[0]); +assert.compareArray(results[1], iterable[1]); assert.sameValue(_this[0], map); assert.sameValue(_this[1], map); diff --git a/js/src/tests/test262/built-ins/Map/iterator-close-after-set-failure.js b/js/src/tests/test262/built-ins/Map/iterator-close-after-set-failure.js index 234d358cea5b..17645d1ccb53 100644 --- a/js/src/tests/test262/built-ins/Map/iterator-close-after-set-failure.js +++ b/js/src/tests/test262/built-ins/Map/iterator-close-after-set-failure.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > The iterator is closed when `Map.prototype.set` throws an error. info: | diff --git a/js/src/tests/test262/built-ins/Map/iterator-item-first-entry-returns-abrupt.js b/js/src/tests/test262/built-ins/Map/iterator-item-first-entry-returns-abrupt.js index 3d8d2bb7dbea..0f311043383e 100644 --- a/js/src/tests/test262/built-ins/Map/iterator-item-first-entry-returns-abrupt.js +++ b/js/src/tests/test262/built-ins/Map/iterator-item-first-entry-returns-abrupt.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Closes iterator if item first entry completes abruptly. info: | diff --git a/js/src/tests/test262/built-ins/Map/iterator-item-second-entry-returns-abrupt.js b/js/src/tests/test262/built-ins/Map/iterator-item-second-entry-returns-abrupt.js index bc475f47eea1..b7eefd9891be 100644 --- a/js/src/tests/test262/built-ins/Map/iterator-item-second-entry-returns-abrupt.js +++ b/js/src/tests/test262/built-ins/Map/iterator-item-second-entry-returns-abrupt.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Closes iterator if item second entry completes abruptly. info: | diff --git a/js/src/tests/test262/built-ins/Map/iterator-items-are-not-object-close-iterator.js b/js/src/tests/test262/built-ins/Map/iterator-items-are-not-object-close-iterator.js index 8daeef13d7e4..62d40c0bbf87 100644 --- a/js/src/tests/test262/built-ins/Map/iterator-items-are-not-object-close-iterator.js +++ b/js/src/tests/test262/built-ins/Map/iterator-items-are-not-object-close-iterator.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Closes the iterator after `not Object` error. info: | diff --git a/js/src/tests/test262/built-ins/Map/iterator-items-are-not-object.js b/js/src/tests/test262/built-ins/Map/iterator-items-are-not-object.js index b08b82516905..3dc770ae8daa 100644 --- a/js/src/tests/test262/built-ins/Map/iterator-items-are-not-object.js +++ b/js/src/tests/test262/built-ins/Map/iterator-items-are-not-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Throws a TypeError if iterable items are not Objects. info: | diff --git a/js/src/tests/test262/built-ins/Map/iterator-next-failure.js b/js/src/tests/test262/built-ins/Map/iterator-next-failure.js index 65c2fd7d3dca..a60349a5e438 100644 --- a/js/src/tests/test262/built-ins/Map/iterator-next-failure.js +++ b/js/src/tests/test262/built-ins/Map/iterator-next-failure.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > The iterator is closed when iterable `next` throws an error. info: | diff --git a/js/src/tests/test262/built-ins/Map/iterator-value-failure.js b/js/src/tests/test262/built-ins/Map/iterator-value-failure.js index d0cc7f4e4637..d7d684df21c8 100644 --- a/js/src/tests/test262/built-ins/Map/iterator-value-failure.js +++ b/js/src/tests/test262/built-ins/Map/iterator-value-failure.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > The iterator is closed when iterable `next` value throws an error. info: | diff --git a/js/src/tests/test262/built-ins/Map/map-iterable-empty-does-not-call-set.js b/js/src/tests/test262/built-ins/Map/map-iterable-empty-does-not-call-set.js index b561e0a8f148..26461bb7f98a 100644 --- a/js/src/tests/test262/built-ins/Map/map-iterable-empty-does-not-call-set.js +++ b/js/src/tests/test262/built-ins/Map/map-iterable-empty-does-not-call-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > A Map constructed with an empty iterable argument does not call set. info: | diff --git a/js/src/tests/test262/built-ins/Map/map-iterable-throws-when-set-is-not-callable.js b/js/src/tests/test262/built-ins/Map/map-iterable-throws-when-set-is-not-callable.js index 233c87520819..bd69dd063648 100644 --- a/js/src/tests/test262/built-ins/Map/map-iterable-throws-when-set-is-not-callable.js +++ b/js/src/tests/test262/built-ins/Map/map-iterable-throws-when-set-is-not-callable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Throws a TypeError if `set` is not callable on Map constructor with a iterable argument. diff --git a/js/src/tests/test262/built-ins/Map/map-iterable.js b/js/src/tests/test262/built-ins/Map/map-iterable.js index 82d8e1985e2d..32918cea9bd5 100644 --- a/js/src/tests/test262/built-ins/Map/map-iterable.js +++ b/js/src/tests/test262/built-ins/Map/map-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Contructor returns a map object set with the elements from the iterable argument. diff --git a/js/src/tests/test262/built-ins/Map/map-no-iterable-does-not-call-set.js b/js/src/tests/test262/built-ins/Map/map-no-iterable-does-not-call-set.js index 1eb4fd5b1306..0d293d61c7d3 100644 --- a/js/src/tests/test262/built-ins/Map/map-no-iterable-does-not-call-set.js +++ b/js/src/tests/test262/built-ins/Map/map-no-iterable-does-not-call-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > A Map constructed without a iterable argument does not call set. info: | diff --git a/js/src/tests/test262/built-ins/Map/map-no-iterable.js b/js/src/tests/test262/built-ins/Map/map-no-iterable.js index 4ac19417914b..e1793ef57862 100644 --- a/js/src/tests/test262/built-ins/Map/map-no-iterable.js +++ b/js/src/tests/test262/built-ins/Map/map-no-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Returns the new Map object with the new empty list if the iterable argument is undefined. diff --git a/js/src/tests/test262/built-ins/Map/map.js b/js/src/tests/test262/built-ins/Map/map.js index 19187bf12e09..211626fc6ec4 100644 --- a/js/src/tests/test262/built-ins/Map/map.js +++ b/js/src/tests/test262/built-ins/Map/map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Map descriptor as a standard built-in object. info: | diff --git a/js/src/tests/test262/built-ins/Map/name.js b/js/src/tests/test262/built-ins/Map/name.js index 9eec4210dd33..4ff6542786de 100644 --- a/js/src/tests/test262/built-ins/Map/name.js +++ b/js/src/tests/test262/built-ins/Map/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: Map.name value and descriptor. info: | Map ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Map/newtarget.js b/js/src/tests/test262/built-ins/Map/newtarget.js index 628d014865f0..36f820fac794 100644 --- a/js/src/tests/test262/built-ins/Map/newtarget.js +++ b/js/src/tests/test262/built-ins/Map/newtarget.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > The new Map object's prototype is Map.prototype info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/Symbol.iterator.js b/js/src/tests/test262/built-ins/Map/prototype/Symbol.iterator.js index f36d1319fc01..cd54db305b58 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/Symbol.iterator.js +++ b/js/src/tests/test262/built-ins/Map/prototype/Symbol.iterator.js @@ -1,7 +1,7 @@ // Copyright (C) 2014 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.12 +esid: sec-map.prototype-@@iterator description: Initial state of the Symbol.iterator property info: | The initial value of the @@iterator property is the same function object as diff --git a/js/src/tests/test262/built-ins/Map/prototype/Symbol.toStringTag.js b/js/src/tests/test262/built-ins/Map/prototype/Symbol.toStringTag.js index 403b73a5187d..a26629037205 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/Symbol.toStringTag.js +++ b/js/src/tests/test262/built-ins/Map/prototype/Symbol.toStringTag.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.13 +esid: sec-map.prototype-@@tostringtag description: > `Symbol.toStringTag` property descriptor info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/clear-map.js b/js/src/tests/test262/built-ins/Map/prototype/clear/clear-map.js index c2035dd42dea..5cd54d887365 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/clear-map.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/clear-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Clears a Map. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/clear.js b/js/src/tests/test262/built-ins/Map/prototype/clear/clear.js index 8160750a6ba8..3cc3a7f8bfac 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/clear.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/clear.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Map.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-not-map-object.js b/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-not-map-object.js index 0ac7ce809484..56a74bf16502 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-not-map-object.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-not-map-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Throws a TypeError if `this` does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-not-object.js b/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-not-object.js index 171ed317ebdf..c0403d215992 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-not-object.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-not-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-set-object-throws.js b/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-set-object-throws.js index 562c2b0ccbb7..e09a49314ee2 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-set-object-throws.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-set-object-throws.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-weakmap-object-throws.js b/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-weakmap-object-throws.js index d465404f203d..ab2097b38b30 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-weakmap-object-throws.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/context-is-weakmap-object-throws.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/length.js b/js/src/tests/test262/built-ins/Map/prototype/clear/length.js index e8cc8ee28550..7cc8f3126fdc 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Map.prototype.clear.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/map-data-list-is-preserved.js b/js/src/tests/test262/built-ins/Map/prototype/clear/map-data-list-is-preserved.js index 45776fdf7339..269cecf34682 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/map-data-list-is-preserved.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/map-data-list-is-preserved.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > The existing [[MapData]] List is preserved. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/name.js b/js/src/tests/test262/built-ins/Map/prototype/clear/name.js index 4f3192f74d11..0bef8b8fe7c9 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Map.prototype.entries.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/clear/returns-undefined.js b/js/src/tests/test262/built-ins/Map/prototype/clear/returns-undefined.js index 84790473b3aa..396511db2f56 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/clear/returns-undefined.js +++ b/js/src/tests/test262/built-ins/Map/prototype/clear/returns-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.1 +esid: sec-map.prototype.clear description: > Returns undefined. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/constructor.js b/js/src/tests/test262/built-ins/Map/prototype/constructor.js index 0b731c694c20..6e09bd7231ec 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/constructor.js +++ b/js/src/tests/test262/built-ins/Map/prototype/constructor.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.2 +esid: sec-map-constructor description: Map.prototype.constructor value and descriptor info: | The initial value of Map.prototype.constructor is the intrinsic object %Map%. diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-not-map-object.js b/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-not-map-object.js index 9443d41d46fb..310e802730c8 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-not-map-object.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-not-map-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Throws a TypeError if `this` does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-not-object.js b/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-not-object.js index cd4d92a8a8bc..c2eaabf156d1 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-not-object.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-not-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-set-object-throws.js b/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-set-object-throws.js index ab0c778afafc..152c54616d20 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-set-object-throws.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-set-object-throws.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-weakmap-object-throws.js b/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-weakmap-object-throws.js index bf61a5e71bc2..ed9b730ba3e0 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-weakmap-object-throws.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/context-is-weakmap-object-throws.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/delete.js b/js/src/tests/test262/built-ins/Map/prototype/delete/delete.js index 2458200e6efa..7aca1a2ff705 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/delete.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/delete.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Map.prototype.delete ( ) diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/does-not-break-iterators.js b/js/src/tests/test262/built-ins/Map/prototype/delete/does-not-break-iterators.js index 2f7ddb4a47f3..28e4a365127b 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/does-not-break-iterators.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/does-not-break-iterators.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Deleting an entry does not break a [[MapData]] List. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/length.js b/js/src/tests/test262/built-ins/Map/prototype/delete/length.js index 4dc4dcb6ddd4..2be05ee2b1cb 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Map.prototype.delete.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/name.js b/js/src/tests/test262/built-ins/Map/prototype/delete/name.js index 265086297d03..dcacf4f3eee6 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Map.prototype.delete.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/returns-false.js b/js/src/tests/test262/built-ins/Map/prototype/delete/returns-false.js index 8a3a3fe45f3a..975d6e6ceb23 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/returns-false.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/returns-false.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Returns false when it does not delete an entry. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/delete/returns-true-for-deleted-entry.js b/js/src/tests/test262/built-ins/Map/prototype/delete/returns-true-for-deleted-entry.js index 3b9ffc44940e..11b650212185 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/delete/returns-true-for-deleted-entry.js +++ b/js/src/tests/test262/built-ins/Map/prototype/delete/returns-true-for-deleted-entry.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.3 +esid: sec-map.prototype.delete description: > Returns true when deletes an entry. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/descriptor.js b/js/src/tests/test262/built-ins/Map/prototype/descriptor.js index a1d5287cd5b3..6e4de86aff21 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/descriptor.js +++ b/js/src/tests/test262/built-ins/Map/prototype/descriptor.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.2.1 +esid: sec-map.prototype description: Map.prototype property attributes. info: | This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-set.js b/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-set.js index 6fb16af8cc76..d3b6325a6c05 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-weakmap.js b/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-weakmap.js index 4aa2bd38b392..87eb91ab40f0 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-weakmap.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-weakmap.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot.js b/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot.js index c62687482a88..ce76b2353e0f 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Throws a TypeError if `this` object does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/entries.js b/js/src/tests/test262/built-ins/Map/prototype/entries/entries.js index 102c6f095126..c4a37be588a3 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/entries.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/entries.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Property type and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/length.js b/js/src/tests/test262/built-ins/Map/prototype/entries/length.js index 061fb37a9f78..593e9181333f 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Map.prototype.entries.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/name.js b/js/src/tests/test262/built-ins/Map/prototype/entries/name.js index ccdd641cf2f5..533b2fa97ee5 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Map.prototype.entries.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/returns-iterator-empty.js b/js/src/tests/test262/built-ins/Map/prototype/entries/returns-iterator-empty.js index 7b467ef46e00..adda70f48377 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/returns-iterator-empty.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/returns-iterator-empty.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Returns an iterator on an empty Map object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/returns-iterator.js b/js/src/tests/test262/built-ins/Map/prototype/entries/returns-iterator.js index c258f17ca60c..aeae3eb81b3b 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/returns-iterator.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/returns-iterator.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Returns an iterator. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/entries/this-not-object-throw.js b/js/src/tests/test262/built-ins/Map/prototype/entries/this-not-object-throw.js index 17c6914fd834..3b8144ef05e9 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/entries/this-not-object-throw.js +++ b/js/src/tests/test262/built-ins/Map/prototype/entries/this-not-object-throw.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.4 +esid: sec-map.prototype.entries description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-parameters.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-parameters.js index 68f1d1fe770a..80120ec0f33f 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-parameters.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-parameters.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Verify the parameters order on the given callback. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-result-is-abrupt.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-result-is-abrupt.js index 2a99ee3ba1b3..db210e806ad4 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-result-is-abrupt.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-result-is-abrupt.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Returns error from callback result is abrupt. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-this-non-strict.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-this-non-strict.js index a20afec5b512..d28c2691d26c 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-this-non-strict.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-this-non-strict.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > If a thisArg is not provided, undefined will be used as the this value for each invocation of callbackfn. diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-this-strict-strict.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-this-strict-strict.js index 1a8006089b57..97abaf89b5ca 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-this-strict-strict.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/callback-this-strict-strict.js @@ -2,7 +2,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > If a thisArg is not provided, undefined will be used as the this value for each invocation of callbackfn. diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/deleted-values-during-foreach.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/deleted-values-during-foreach.js index 84c773f4a4f2..76498de30013 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/deleted-values-during-foreach.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/deleted-values-during-foreach.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Map state with deleted values during forEach. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-set.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-set.js index 1cfea0915f67..45dff89fd353 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-weakmap.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-weakmap.js index deb205d22732..f53d2ca50a43 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-weakmap.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-weakmap.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot.js index 4030d454a8c6..1f7f9c860cd9 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Throws a TypeError if `this` object does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/first-argument-is-not-callable.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/first-argument-is-not-callable.js index 630484f435f2..c88ef521af8a 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/first-argument-is-not-callable.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/first-argument-is-not-callable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Throws a TypeError if first argument is not callable. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/forEach.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/forEach.js index 267898297239..20f4b5b7587c 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/forEach.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/forEach.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Property type and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-in-key-insertion-order.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-in-key-insertion-order.js index e064c061ef5c..24012f435ba5 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-in-key-insertion-order.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-in-key-insertion-order.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Repeats for each non-empty record, in original key insertion order. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-values-added-after-foreach-begins.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-values-added-after-foreach-begins.js index eb120ee61113..f728b86d9bb8 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-values-added-after-foreach-begins.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-values-added-after-foreach-begins.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > New keys are visited if created during forEach execution. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-values-deleted-then-readded.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-values-deleted-then-readded.js index 1f2d8a62b87b..a0cce8e52551 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-values-deleted-then-readded.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/iterates-values-deleted-then-readded.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > New keys are visited if created during forEach execution. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/length.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/length.js index 072bdb3ea417..d0e0c95dc8ef 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Map.prototype.forEach.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/name.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/name.js index 7656ab1df1ad..ea6f8c57fd89 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Map.prototype.forEach.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/return-undefined.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/return-undefined.js index 8e3a0d52f338..f3f2d3b2fde1 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/return-undefined.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/return-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Returns undefined. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/second-parameter-as-callback-context.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/second-parameter-as-callback-context.js index 162b3c047c6b..16c5def0d456 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/second-parameter-as-callback-context.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/second-parameter-as-callback-context.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackfn. diff --git a/js/src/tests/test262/built-ins/Map/prototype/forEach/this-not-object-throw.js b/js/src/tests/test262/built-ins/Map/prototype/forEach/this-not-object-throw.js index 649b4778357d..0e281c65857e 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/forEach/this-not-object-throw.js +++ b/js/src/tests/test262/built-ins/Map/prototype/forEach/this-not-object-throw.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.5 +esid: sec-map.prototype.forEach description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-set.js b/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-set.js index 1bb2bd09b818..05dd6be15b29 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-weakmap.js b/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-weakmap.js index 06a6ad62b61c..618f1201df08 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-weakmap.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-weakmap.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot.js b/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot.js index 0e3c065582eb..1cc52a9e222e 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Throws a TypeError if `this` object does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/get.js b/js/src/tests/test262/built-ins/Map/prototype/get/get.js index 2463ed994302..98525e86462e 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/get.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/get.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Property type and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/length.js b/js/src/tests/test262/built-ins/Map/prototype/get/length.js index 7c7ba35a4d97..4d6e66ffcb6a 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Map.prototype.get.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/name.js b/js/src/tests/test262/built-ins/Map/prototype/get/name.js index 986bb39b67d8..ef63a260eeb7 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Map.prototype.get.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/returns-undefined.js b/js/src/tests/test262/built-ins/Map/prototype/get/returns-undefined.js index 220528d5da61..9af716299312 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/returns-undefined.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/returns-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Returns undefined when key is not on the map. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/returns-value-different-key-types.js b/js/src/tests/test262/built-ins/Map/prototype/get/returns-value-different-key-types.js index a495876ee8e0..b773a87e48eb 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/returns-value-different-key-types.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/returns-value-different-key-types.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Returns the value from the specified key on different types. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/returns-value-normalized-zero-key.js b/js/src/tests/test262/built-ins/Map/prototype/get/returns-value-normalized-zero-key.js index b2671b3d006d..194b18600208 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/returns-value-normalized-zero-key.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/returns-value-normalized-zero-key.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > -0 and +0 are normalized to +0; info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/get/this-not-object-throw.js b/js/src/tests/test262/built-ins/Map/prototype/get/this-not-object-throw.js index 360a5b3999de..46d5ea11af34 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/get/this-not-object-throw.js +++ b/js/src/tests/test262/built-ins/Map/prototype/get/this-not-object-throw.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.6 +esid: sec-map.prototype.get description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-set.js b/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-set.js index 5cc316d7b215..be7b3296ead4 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-weakmap.js b/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-weakmap.js index e0dfd6c4590d..d470bbdb8c10 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-weakmap.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-weakmap.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot.js b/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot.js index 78bf50665505..77cb5284b264 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Throws a TypeError if `this` object does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/has.js b/js/src/tests/test262/built-ins/Map/prototype/has/has.js index d90141e50b8f..0ff8d0b6eb85 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/has.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/has.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Property type and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/length.js b/js/src/tests/test262/built-ins/Map/prototype/has/length.js index be24d24fcadf..d5e9b5b48efc 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Map.prototype.has.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/name.js b/js/src/tests/test262/built-ins/Map/prototype/has/name.js index 11d7853e3ff3..82e1dc3f0146 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Map.prototype.has.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/normalizes-zero-key.js b/js/src/tests/test262/built-ins/Map/prototype/has/normalizes-zero-key.js index faadc82fc497..8bdc66d59cfe 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/normalizes-zero-key.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/normalizes-zero-key.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > -0 and +0 are normalized to +0; info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/return-false-different-key-types.js b/js/src/tests/test262/built-ins/Map/prototype/has/return-false-different-key-types.js index 31e7c6d24e5f..a790c9964c12 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/return-false-different-key-types.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/return-false-different-key-types.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Returns true for existing keys, using different key types. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/return-true-different-key-types.js b/js/src/tests/test262/built-ins/Map/prototype/has/return-true-different-key-types.js index b90060e93a18..1d56cae345cf 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/return-true-different-key-types.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/return-true-different-key-types.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Returns true for existing keys, using different key types. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/has/this-not-object-throw.js b/js/src/tests/test262/built-ins/Map/prototype/has/this-not-object-throw.js index 3c76da555b6a..219a48a2ae77 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/has/this-not-object-throw.js +++ b/js/src/tests/test262/built-ins/Map/prototype/has/this-not-object-throw.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.7 +esid: sec-map.prototype.has description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-set.js b/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-set.js index e0ce7827079b..b32534b4a092 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-weakmap.js b/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-weakmap.js index 2a0f750f91f7..b12d4c2a9622 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-weakmap.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-weakmap.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot.js b/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot.js index af2864b3cdc9..7869123ad130 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Throws a TypeError if `this` object does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/keys.js b/js/src/tests/test262/built-ins/Map/prototype/keys/keys.js index 1c9b01aca817..3ba771c73562 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/keys.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/keys.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Property type and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/length.js b/js/src/tests/test262/built-ins/Map/prototype/keys/length.js index 2821d98197c0..6a5c19fd9691 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Map.prototype.keys.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/name.js b/js/src/tests/test262/built-ins/Map/prototype/keys/name.js index 95c8920db712..ce3aa466612a 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Map.prototype.keys.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/returns-iterator-empty.js b/js/src/tests/test262/built-ins/Map/prototype/keys/returns-iterator-empty.js index 7791949cc06c..d00763f142b1 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/returns-iterator-empty.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/returns-iterator-empty.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Returns an iterator on an empty Map object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/returns-iterator.js b/js/src/tests/test262/built-ins/Map/prototype/keys/returns-iterator.js index 6a4f0925ef0c..4fbcff7d2183 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/returns-iterator.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/returns-iterator.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Returns an iterator. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/keys/this-not-object-throw.js b/js/src/tests/test262/built-ins/Map/prototype/keys/this-not-object-throw.js index cdea87a66372..14fc88245d10 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/keys/this-not-object-throw.js +++ b/js/src/tests/test262/built-ins/Map/prototype/keys/this-not-object-throw.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.8 +esid: sec-map.prototype.keys description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values-normalizes-zero-key.js b/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values-normalizes-zero-key.js index 9a5401a41fcd..55122ae9adf1 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values-normalizes-zero-key.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values-normalizes-zero-key.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Appends new value in the map normalizing +0 and -0. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values-return-map.js b/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values-return-map.js index 61b2768adfb5..a7c2008bab36 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values-return-map.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values-return-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Map.prototype.set returns the given `this` object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values.js b/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values.js index 6ee18502f23f..f567db5d72b4 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/append-new-values.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Append a new value as the last element of entries. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-set.js b/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-set.js index 56776de5ecc5..9a80c6f6cf6d 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-weakmap.js b/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-weakmap.js index c3050b5e3e5c..cbabc7bab1d7 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-weakmap.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-weakmap.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot.js b/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot.js index 5934f5acc75c..ff591840b351 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Throws a TypeError if `this` object does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/length.js b/js/src/tests/test262/built-ins/Map/prototype/set/length.js index 573208670a2f..939b633c34d7 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Map.prototype.set.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/name.js b/js/src/tests/test262/built-ins/Map/prototype/set/name.js index 8f41b1adda89..7c0b83f69674 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Map.prototype.set.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value-normalizes-zero-key.js b/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value-normalizes-zero-key.js index 675193a542df..6c4b708a16f1 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value-normalizes-zero-key.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value-normalizes-zero-key.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Replaces a value in the map normalizing +0 and -0. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value-returns-map.js b/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value-returns-map.js index 7619f756279a..b7f0e189091e 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value-returns-map.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value-returns-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Map.prototype.set returns the given `this` map object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value.js b/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value.js index 4fa2a58fa388..9fe4e95c3ff0 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/replaces-a-value.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Replaces a value in the map. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/set.js b/js/src/tests/test262/built-ins/Map/prototype/set/set.js index d38341daa097..f8a12db77917 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Property type and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/set/this-not-object-throw.js b/js/src/tests/test262/built-ins/Map/prototype/set/this-not-object-throw.js index c75043c11554..7f42b3e5efae 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/set/this-not-object-throw.js +++ b/js/src/tests/test262/built-ins/Map/prototype/set/this-not-object-throw.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-map.prototype.set description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-set.js b/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-set.js index 44a432c7e6fb..228d8068bab9 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-set.js @@ -1,14 +1,12 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Throws a TypeError if `this` is a Set object. info: | - Map.prototype.set ( key , value ) - ... - 3. If M does not have a [[MapData]] internal slot, throw a TypeError + If M does not have a [[MapData]] internal slot, throw a TypeError exception. ... features: [Set] diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-weakmap.js b/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-weakmap.js index da31eea7e60c..a2385ada8c08 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-weakmap.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-weakmap.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-get-map.prototype.size description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot.js b/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot.js index 7cac8871ee20..00ba29073dcc 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.9 +esid: sec-get-map.prototype.size description: > Throws a TypeError if `this` object does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/length.js b/js/src/tests/test262/built-ins/Map/prototype/size/length.js index ed357b3cc214..b3812e1ec64d 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Map.prototype.size.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/name.js b/js/src/tests/test262/built-ins/Map/prototype/size/name.js index 4c60a9651015..596e1a23c51f 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Map.prototype.size.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-before-after-set-clear.js b/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-before-after-set-clear.js index 8d22fb0bde68..94316f9055e8 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-before-after-set-clear.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-before-after-set-clear.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Returns count of present values before and after using `set` and `clear`. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-before-after-set-delete.js b/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-before-after-set-delete.js index d0934a81499a..3903b4403342 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-before-after-set-delete.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-before-after-set-delete.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Returns count of present values before and after using `set` and `delete`. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-by-insertion.js b/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-by-insertion.js index 20cc59a7d056..f8dcb3497bb2 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-by-insertion.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-by-insertion.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Returns count of present values inserted with set. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-by-iterable.js b/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-by-iterable.js index 200d42926a4e..f8ca96cf0bb6 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-by-iterable.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/returns-count-of-present-values-by-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Returns count of present values inserted via iterable argument. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/size.js b/js/src/tests/test262/built-ins/Map/prototype/size/size.js index 8e3d9ec6e78a..c13c0c58ac7a 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/size.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/size.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Property type and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/size/this-not-object-throw.js b/js/src/tests/test262/built-ins/Map/prototype/size/this-not-object-throw.js index 7df988ccbd54..aa1f911dbcfc 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/size/this-not-object-throw.js +++ b/js/src/tests/test262/built-ins/Map/prototype/size/this-not-object-throw.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.10 +esid: sec-get-map.prototype.size description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-set.js b/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-set.js index e6bae49dc209..489e6b7331f6 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-set.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Throws a TypeError if `this` is a Set object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-weakmap.js b/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-weakmap.js index 0a47c8df37b6..82f02364b6b8 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-weakmap.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-weakmap.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Throws a TypeError if `this` is a WeakMap object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot.js b/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot.js index 06e0790ccde2..65ea9ca971ed 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Throws a TypeError if `this` object does not have a [[MapData]] internal slot. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/length.js b/js/src/tests/test262/built-ins/Map/prototype/values/length.js index 61aad1377529..304cdd798382 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/length.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Map.prototype.values.length value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/name.js b/js/src/tests/test262/built-ins/Map/prototype/values/name.js index b003edde22d3..03827d01f3d9 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/name.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Map.prototype.values.name value and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/returns-iterator-empty.js b/js/src/tests/test262/built-ins/Map/prototype/values/returns-iterator-empty.js index 4f90ebb16251..990723ff8708 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/returns-iterator-empty.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/returns-iterator-empty.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Returns an iterator on an empty Map object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/returns-iterator.js b/js/src/tests/test262/built-ins/Map/prototype/values/returns-iterator.js index 3fa7e712d159..006b4975fc24 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/returns-iterator.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/returns-iterator.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Returns an iterator. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/this-not-object-throw.js b/js/src/tests/test262/built-ins/Map/prototype/values/this-not-object-throw.js index 59a5580fd457..372aec3a0254 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/this-not-object-throw.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/this-not-object-throw.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Throws a TypeError if `this` is not an Object. info: | diff --git a/js/src/tests/test262/built-ins/Map/prototype/values/values.js b/js/src/tests/test262/built-ins/Map/prototype/values/values.js index 5504c7a23d70..3ec0c35c6ff6 100644 --- a/js/src/tests/test262/built-ins/Map/prototype/values/values.js +++ b/js/src/tests/test262/built-ins/Map/prototype/values/values.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.3.11 +esid: sec-map.prototype.values description: > Property type and descriptor. info: | diff --git a/js/src/tests/test262/built-ins/Map/symbol-as-entry-key.js b/js/src/tests/test262/built-ins/Map/symbol-as-entry-key.js deleted file mode 100644 index 3bb5d3dc1b83..000000000000 --- a/js/src/tests/test262/built-ins/Map/symbol-as-entry-key.js +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2013 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -es6id: 19.4 -description: > - Symbol as Map key -features: [Symbol] ----*/ -var map = new Map(); -var sym = Symbol(); - -map.set(sym, 1); - -assert.sameValue(map.size, 1, "The value of `map.size` is `1`, after executing `map.set(sym, 1)`"); -assert.sameValue(map.has(sym), true, "`map.has(sym)` returns `true`"); -assert.sameValue(map.get(sym), 1, "`map.get(sym)` returns `1`"); -assert.sameValue(map.delete(sym), true, "`map.delete(sym)` returns `true`"); -assert.sameValue(map.size, 0, "The value of `map.size` is `0`"); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Map/undefined-newtarget.js b/js/src/tests/test262/built-ins/Map/undefined-newtarget.js index 31e4067208f7..94e6bd397a86 100644 --- a/js/src/tests/test262/built-ins/Map/undefined-newtarget.js +++ b/js/src/tests/test262/built-ins/Map/undefined-newtarget.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.1.1.1 +esid: sec-map-iterable description: > Throws a TypeError if Map is called without a newTarget. info: | diff --git a/js/src/tests/test262/built-ins/Map/valid-keys.js b/js/src/tests/test262/built-ins/Map/valid-keys.js new file mode 100644 index 000000000000..a162436b4899 --- /dev/null +++ b/js/src/tests/test262/built-ins/Map/valid-keys.js @@ -0,0 +1,486 @@ +// |reftest| skip-if(!this.hasOwnProperty('WeakRef')) -- WeakRef is not enabled unconditionally +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-map.prototype.set +description: Observing the expected behavior of valid keys +info: | + Map.prototype.set ( key , value ) + + ... + Let p be the Record {[[key]]: key, [[value]]: value}. + Append p as the last element of entries. + ... + +features: [BigInt, Symbol, TypedArray, WeakRef] +---*/ + + +const negativeZero = -0; +const positiveZero = +0; +const zero = 0; +const one = 1; +const twoRaisedToFiftyThreeMinusOne = 2 ** 53 - 1; +const int32Array = new Int32Array([zero, one]); +const uint32Array = new Uint32Array([zero, one]); +const n = 100000000000000000000000000000000000000000000000000000000000000000000000000000000001n; +const bigInt = BigInt('100000000000000000000000000000000000000000000000000000000000000000000000000000000001'); +const n1 = 1n; +const n53 = 9007199254740991n; +const fiftyThree = BigInt('9007199254740991'); +const bigInt64Array = new BigInt64Array([n1, n53]); +const bigUint64Array = new BigUint64Array([n1, n53]); +const symbol = Symbol(''); +const object = {}; +const array = {}; +const string = ''; +const booleanTrue = true; +const booleanFalse = true; +const functionExprValue = function() {}; +const arrowFunctionValue = () => {}; +const classValue = class {}; +const map = new Map(); +const set = new Set(); +const weakMap = new WeakMap(); +const weakRef = new WeakRef({}); +const weakSet = new WeakSet(); +const nullValue = null; +const undefinedValue = undefined; +let unassigned; + +{ + const m = new Map([[negativeZero, negativeZero]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(negativeZero), true); + assert.sameValue(m.get(negativeZero), negativeZero); + m.delete(negativeZero); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(negativeZero), false); + m.set(negativeZero, negativeZero); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(negativeZero), true); + assert.sameValue(m.get(negativeZero), negativeZero); +}; + +{ + const m = new Map([[positiveZero, positiveZero]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(positiveZero), true); + assert.sameValue(m.get(positiveZero), positiveZero); + m.delete(positiveZero); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(positiveZero), false); + m.set(positiveZero, positiveZero); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(positiveZero), true); + assert.sameValue(m.get(positiveZero), positiveZero); +}; + +{ + const m = new Map([[zero, zero]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(zero), true); + assert.sameValue(m.get(zero), zero); + m.delete(zero); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(zero), false); + m.set(zero, zero); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(zero), true); + assert.sameValue(m.get(zero), zero); +}; + +{ + const m = new Map([[one, one]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(one), true); + assert.sameValue(m.get(one), one); + m.delete(one); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(one), false); + m.set(one, one); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(one), true); + assert.sameValue(m.get(one), one); +}; + +{ + const m = new Map([[twoRaisedToFiftyThreeMinusOne, twoRaisedToFiftyThreeMinusOne]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(twoRaisedToFiftyThreeMinusOne), true); + assert.sameValue(m.get(twoRaisedToFiftyThreeMinusOne), twoRaisedToFiftyThreeMinusOne); + m.delete(twoRaisedToFiftyThreeMinusOne); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(twoRaisedToFiftyThreeMinusOne), false); + m.set(twoRaisedToFiftyThreeMinusOne, twoRaisedToFiftyThreeMinusOne); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(twoRaisedToFiftyThreeMinusOne), true); + assert.sameValue(m.get(twoRaisedToFiftyThreeMinusOne), twoRaisedToFiftyThreeMinusOne); +}; + +{ + const m = new Map([[int32Array, int32Array]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(int32Array), true); + assert.sameValue(m.get(int32Array), int32Array); + m.delete(int32Array); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(int32Array), false); + m.set(int32Array, int32Array); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(int32Array), true); + assert.sameValue(m.get(int32Array), int32Array); +}; + +{ + const m = new Map([[uint32Array, uint32Array]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(uint32Array), true); + assert.sameValue(m.get(uint32Array), uint32Array); + m.delete(uint32Array); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(uint32Array), false); + m.set(uint32Array, uint32Array); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(uint32Array), true); + assert.sameValue(m.get(uint32Array), uint32Array); +}; + +{ + const m = new Map([[n, n]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(n), true); + assert.sameValue(m.get(n), n); + m.delete(n); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(n), false); + m.set(n, n); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(n), true); + assert.sameValue(m.get(n), n); +}; + +{ + const m = new Map([[bigInt, bigInt]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(bigInt), true); + assert.sameValue(m.get(bigInt), bigInt); + m.delete(bigInt); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(bigInt), false); + m.set(bigInt, bigInt); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(bigInt), true); + assert.sameValue(m.get(bigInt), bigInt); +}; + +{ + const m = new Map([[n1, n1]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(n1), true); + assert.sameValue(m.get(n1), n1); + m.delete(n1); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(n1), false); + m.set(n1, n1); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(n1), true); + assert.sameValue(m.get(n1), n1); +}; + +{ + const m = new Map([[n53, n53]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(n53), true); + assert.sameValue(m.get(n53), n53); + m.delete(n53); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(n53), false); + m.set(n53, n53); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(n53), true); + assert.sameValue(m.get(n53), n53); +}; + +{ + const m = new Map([[fiftyThree, fiftyThree]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(fiftyThree), true); + assert.sameValue(m.get(fiftyThree), fiftyThree); + m.delete(fiftyThree); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(fiftyThree), false); + m.set(fiftyThree, fiftyThree); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(fiftyThree), true); + assert.sameValue(m.get(fiftyThree), fiftyThree); +}; + +{ + const m = new Map([[bigInt64Array, bigInt64Array]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(bigInt64Array), true); + assert.sameValue(m.get(bigInt64Array), bigInt64Array); + m.delete(bigInt64Array); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(bigInt64Array), false); + m.set(bigInt64Array, bigInt64Array); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(bigInt64Array), true); + assert.sameValue(m.get(bigInt64Array), bigInt64Array); +}; + +{ + const m = new Map([[bigUint64Array, bigUint64Array]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(bigUint64Array), true); + assert.sameValue(m.get(bigUint64Array), bigUint64Array); + m.delete(bigUint64Array); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(bigUint64Array), false); + m.set(bigUint64Array, bigUint64Array); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(bigUint64Array), true); + assert.sameValue(m.get(bigUint64Array), bigUint64Array); +}; + +{ + const m = new Map([[symbol, symbol]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(symbol), true); + assert.sameValue(m.get(symbol), symbol); + m.delete(symbol); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(symbol), false); + m.set(symbol, symbol); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(symbol), true); + assert.sameValue(m.get(symbol), symbol); +}; + +{ + const m = new Map([[object, object]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(object), true); + assert.sameValue(m.get(object), object); + m.delete(object); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(object), false); + m.set(object, object); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(object), true); + assert.sameValue(m.get(object), object); +}; + +{ + const m = new Map([[array, array]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(array), true); + assert.sameValue(m.get(array), array); + m.delete(array); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(array), false); + m.set(array, array); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(array), true); + assert.sameValue(m.get(array), array); +}; + +{ + const m = new Map([[string, string]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(string), true); + assert.sameValue(m.get(string), string); + m.delete(string); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(string), false); + m.set(string, string); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(string), true); + assert.sameValue(m.get(string), string); +}; + +{ + const m = new Map([[booleanTrue, booleanTrue]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(booleanTrue), true); + assert.sameValue(m.get(booleanTrue), booleanTrue); + m.delete(booleanTrue); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(booleanTrue), false); + m.set(booleanTrue, booleanTrue); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(booleanTrue), true); + assert.sameValue(m.get(booleanTrue), booleanTrue); +}; + +{ + const m = new Map([[booleanFalse, booleanFalse]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(booleanFalse), true); + assert.sameValue(m.get(booleanFalse), booleanFalse); + m.delete(booleanFalse); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(booleanFalse), false); + m.set(booleanFalse, booleanFalse); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(booleanFalse), true); + assert.sameValue(m.get(booleanFalse), booleanFalse); +}; + +{ + const m = new Map([[functionExprValue, functionExprValue]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(functionExprValue), true); + assert.sameValue(m.get(functionExprValue), functionExprValue); + m.delete(functionExprValue); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(functionExprValue), false); + m.set(functionExprValue, functionExprValue); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(functionExprValue), true); + assert.sameValue(m.get(functionExprValue), functionExprValue); +}; + +{ + const m = new Map([[arrowFunctionValue, arrowFunctionValue]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(arrowFunctionValue), true); + assert.sameValue(m.get(arrowFunctionValue), arrowFunctionValue); + m.delete(arrowFunctionValue); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(arrowFunctionValue), false); + m.set(arrowFunctionValue, arrowFunctionValue); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(arrowFunctionValue), true); + assert.sameValue(m.get(arrowFunctionValue), arrowFunctionValue); +}; + +{ + const m = new Map([[classValue, classValue]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(classValue), true); + assert.sameValue(m.get(classValue), classValue); + m.delete(classValue); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(classValue), false); + m.set(classValue, classValue); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(classValue), true); + assert.sameValue(m.get(classValue), classValue); +}; + +{ + const m = new Map([[map, map]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(map), true); + assert.sameValue(m.get(map), map); + m.delete(map); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(map), false); + m.set(map, map); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(map), true); + assert.sameValue(m.get(map), map); +}; + +{ + const m = new Map([[set, set]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(set), true); + assert.sameValue(m.get(set), set); + m.delete(set); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(set), false); + m.set(set, set); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(set), true); + assert.sameValue(m.get(set), set); +}; + +{ + const m = new Map([[weakMap, weakMap]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(weakMap), true); + assert.sameValue(m.get(weakMap), weakMap); + m.delete(weakMap); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(weakMap), false); + m.set(weakMap, weakMap); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(weakMap), true); + assert.sameValue(m.get(weakMap), weakMap); +}; + +{ + const m = new Map([[weakRef, weakRef]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(weakRef), true); + assert.sameValue(m.get(weakRef), weakRef); + m.delete(weakRef); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(weakRef), false); + m.set(weakRef, weakRef); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(weakRef), true); + assert.sameValue(m.get(weakRef), weakRef); +}; + +{ + const m = new Map([[weakSet, weakSet]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(weakSet), true); + assert.sameValue(m.get(weakSet), weakSet); + m.delete(weakSet); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(weakSet), false); + m.set(weakSet, weakSet); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(weakSet), true); + assert.sameValue(m.get(weakSet), weakSet); +}; + +{ + const m = new Map([[nullValue, nullValue]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(nullValue), true); + assert.sameValue(m.get(nullValue), nullValue); + m.delete(nullValue); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(nullValue), false); + m.set(nullValue, nullValue); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(nullValue), true); + assert.sameValue(m.get(nullValue), nullValue); +}; + +{ + const m = new Map([[undefinedValue, undefinedValue]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(undefinedValue), true); + assert.sameValue(m.get(undefinedValue), undefinedValue); + m.delete(undefinedValue); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(undefinedValue), false); + m.set(undefinedValue, undefinedValue); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(undefinedValue), true); + assert.sameValue(m.get(undefinedValue), undefinedValue); +}; + +{ + const m = new Map([[unassigned, unassigned]]); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(unassigned), true); + assert.sameValue(m.get(unassigned), unassigned); + m.delete(unassigned); + assert.sameValue(m.size, 0); + assert.sameValue(m.has(unassigned), false); + m.set(unassigned, unassigned); + assert.sameValue(m.size, 1); + assert.sameValue(m.has(unassigned), true); + assert.sameValue(m.get(unassigned), unassigned); +}; + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Math/hypot/Math.hypot_ToNumberErr.js b/js/src/tests/test262/built-ins/Math/hypot/Math.hypot_ToNumberErr.js new file mode 100644 index 000000000000..ae2fc40f1bd7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Math/hypot/Math.hypot_ToNumberErr.js @@ -0,0 +1,37 @@ +// Copyright (c) 2021 Richard Gibson. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Math.hypot should coerce all arguments before inspecting them. +esid: sec-math.hypot +info: | + 1. Let _coerced_ be a new empty List. + 2. For each element _arg_ of _args_, do + a. Let _n_ be ? ToNumber(_arg_). + b. Append _n_ to _coerced_. + 3. For each element _number_ of _coerced_, do +---*/ + +var counter = 0; + +assert.throws( + Test262Error, + function() { + Math.hypot( + Infinity, + -Infinity, + NaN, + 0, + -0, + {valueOf: function(){ throw new Test262Error(); }}, + {valueOf: function(){ counter++; }} + ); + }, + 'Math.hypot propagates an abrupt completion from coercing an argument to Number' +); + +assert.sameValue(counter, 0, + 'Math.hypot aborts argument processing at the first abrupt completion'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Math/hypot/Math.hypot_Zero_2.js b/js/src/tests/test262/built-ins/Math/hypot/Math.hypot_Zero_2.js index 7471d21e795b..0e121bd021c1 100644 --- a/js/src/tests/test262/built-ins/Math/hypot/Math.hypot_Zero_2.js +++ b/js/src/tests/test262/built-ins/Math/hypot/Math.hypot_Zero_2.js @@ -2,14 +2,18 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: sec-math.hypot es6id: 20.2.2.18 author: Ryan Lewis -description: Return 0 if all arguments being are 0 or -0. +description: Math.hypot should return 0 if all arguments are 0 or -0. ---*/ +assert.sameValue(Math.hypot(0), 0, 'Math.hypot(0)'); +assert.sameValue(Math.hypot(-0), 0, 'Math.hypot(-0)'); assert.sameValue(Math.hypot(0, 0), 0, 'Math.hypot(0, 0)'); assert.sameValue(Math.hypot(0, -0), 0, 'Math.hypot(0, -0)'); assert.sameValue(Math.hypot(-0, 0), 0, 'Math.hypot(-0, 0)'); assert.sameValue(Math.hypot(-0, -0), 0, 'Math.hypot(-0, -0)'); +assert.sameValue(Math.hypot(0, -0, -0), 0, 'Math.hypot(0, -0, -0)'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A2_T2.js b/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A2_T2.js index f33563710095..43a4423d3c96 100644 --- a/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A2_T2.js @@ -10,8 +10,8 @@ flags: [noStrict] // CHECK#1 NaN = true; -if (typeof(NaN) === "boolean") { - throw new Test262Error('#1: NaN = true; typeof(NaN) !== "boolean". Actual: ' + (typeof(NaN))); -} +assert.notSameValue(typeof(NaN), "boolean", 'The value of typeof(NaN) is not "boolean"'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A3_T2.js b/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A3_T2.js index 431fb6e5065b..6402c7dbd7ab 100644 --- a/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A3_T2.js @@ -7,10 +7,8 @@ es5id: 15.1.1.1_A3_T2 description: Use delete flags: [noStrict] ---*/ +assert.sameValue(delete NaN, false, 'The value of `delete NaN` is expected to be false'); -// CHECK#1 -if (delete NaN !== false) { - throw new Test262Error('#1: delete NaN === false. Actual: ' + (delete NaN)); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A4.js b/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A4.js index c31137ae8367..86a17cc3e87c 100644 --- a/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A4.js +++ b/js/src/tests/test262/built-ins/NaN/S15.1.1.1_A4.js @@ -9,9 +9,9 @@ description: Use for-in statement // CHECK#1 for (var prop in this) { - if (prop === "NaN") { - throw new Test262Error('#1: The NaN is DontEnum'); - } + assert.notSameValue(prop, "NaN", 'The value of prop is not "NaN"'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A2.js b/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A2.js index 5e4422c7c4b1..11e996f7df3b 100644 --- a/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A2.js +++ b/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A2.js @@ -11,8 +11,8 @@ includes: [propertyHelper.js] // CHECK#1 var x = Number.MAX_VALUE; verifyNotWritable(Number, "MAX_VALUE", null, 1); -if (Number.MAX_VALUE !== x) { - throw new Test262Error('#1: x = Number.MAX_VALUE; Number.MAX_VALUE = 1; Number.MAX_VALUE === x'); -} +assert.sameValue(Number.MAX_VALUE, x, 'The value of Number.MAX_VALUE is expected to equal the value of x'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A3.js b/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A3.js index af9e6e7e74af..17717c902cdb 100644 --- a/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A3.js +++ b/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A3.js @@ -12,12 +12,14 @@ verifyNotConfigurable(Number, "MAX_VALUE"); // CHECK#1 try { - if (delete Number.MAX_VALUE !== false) { - throw new Test262Error('#1: delete Number.MAX_VALUE === false'); - } + assert.sameValue(delete Number.MAX_VALUE, false); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } assert(e instanceof TypeError); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A4.js b/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A4.js index 07e079a95c10..03668588ecbe 100644 --- a/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A4.js +++ b/js/src/tests/test262/built-ins/Number/MAX_VALUE/S15.7.3.2_A4.js @@ -7,15 +7,15 @@ es5id: 15.7.3.2_A4 description: Checking if enumerating Number.MAX_VALUE fails ---*/ -//CHECK#1 for (var x in Number) { - if (x === "MAX_VALUE") { - throw new Test262Error('#1: Number.MAX_VALUE has the attribute DontEnum'); - } + assert.notSameValue(x, "MAX_VALUE", 'The value of x is not "MAX_VALUE"'); } -if (Number.propertyIsEnumerable('MAX_VALUE')) { - throw new Test262Error('#2: Number.MAX_VALUE has the attribute DontEnum'); -} +assert( + !Number.propertyIsEnumerable('MAX_VALUE'), + 'The value of !Number.propertyIsEnumerable(\'MAX_VALUE\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A2.js b/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A2.js index 45f88a9d0854..450fcf96b841 100644 --- a/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A2.js +++ b/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A2.js @@ -11,8 +11,8 @@ includes: [propertyHelper.js] // CHECK#1 var x = Number.MIN_VALUE; verifyNotWritable(Number, "MIN_VALUE", null, 1); -if (Number.MIN_VALUE !== x) { - throw new Test262Error('#1: x = Number.MIN_VALUE; Number.MIN_VALUE = 1; Number.MIN_VALUE === x'); -} +assert.sameValue(Number.MIN_VALUE, x, 'The value of Number.MIN_VALUE is expected to equal the value of x'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A3.js b/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A3.js index c5ce7358b8ec..9411c6c300e5 100644 --- a/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A3.js +++ b/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A3.js @@ -10,14 +10,15 @@ includes: [propertyHelper.js] verifyNotConfigurable(Number, "MIN_VALUE"); -//CHECK#1 try { - if (delete Number.MIN_VALUE !== false) { - throw new Test262Error('#1: delete Number.MIN_VALUE === false'); - } + assert.sameValue(delete Number.MIN_VALUE, false); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } assert(e instanceof TypeError); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A4.js b/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A4.js index e7cd9a6c8736..3bbbd9f5163f 100644 --- a/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A4.js +++ b/js/src/tests/test262/built-ins/Number/MIN_VALUE/S15.7.3.3_A4.js @@ -7,15 +7,15 @@ es5id: 15.7.3.3_A4 description: Checking if enumerating Number.MIN_VALUE fails ---*/ -//CHECK#1 for (var x in Number) { - if (x === "MIN_VALUE") { - throw new Test262Error('#1: Number.MIN_VALUE has the attribute DontEnum'); - } + assert.notSameValue(x, "MIN_VALUE", 'The value of x is not "MIN_VALUE"'); } -if (Number.propertyIsEnumerable('MIN_VALUE')) { - throw new Test262Error('#2: Number.MIN_VALUE has the attribute DontEnum'); -} +assert( + !Number.propertyIsEnumerable('MIN_VALUE'), + 'The value of !Number.propertyIsEnumerable(\'MIN_VALUE\') is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/NEGATIVE_INFINITY/S15.7.3.5_A1.js b/js/src/tests/test262/built-ins/Number/NEGATIVE_INFINITY/S15.7.3.5_A1.js index db589cc4e505..aa19a869b19f 100644 --- a/js/src/tests/test262/built-ins/Number/NEGATIVE_INFINITY/S15.7.3.5_A1.js +++ b/js/src/tests/test262/built-ins/Number/NEGATIVE_INFINITY/S15.7.3.5_A1.js @@ -6,14 +6,6 @@ info: Number.NEGATIVE_INFINITY is -Infinity es5id: 15.7.3.5_A1 description: Checking sign and finiteness of Number.NEGATIVE_INFINITY ---*/ - -// CHECK#1 -if (isFinite(Number.NEGATIVE_INFINITY) !== false) { - throw new Test262Error('#1: Number.NEGATIVE_INFINITY === Not-a-Finite'); -} else { - if ((Number.NEGATIVE_INFINITY < 0) !== true) { - throw new Test262Error('#1: Number.NEGATIVE_INFINITY === -Infinity'); - } -} +assert.sameValue(isFinite(Number.NEGATIVE_INFINITY), false, 'isFinite(Number.NEGATIVE_INFINITY) must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/NEGATIVE_INFINITY/S15.7.3.5_A2.js b/js/src/tests/test262/built-ins/Number/NEGATIVE_INFINITY/S15.7.3.5_A2.js index a426f4042be5..483c818acc0a 100644 --- a/js/src/tests/test262/built-ins/Number/NEGATIVE_INFINITY/S15.7.3.5_A2.js +++ b/js/src/tests/test262/built-ins/Number/NEGATIVE_INFINITY/S15.7.3.5_A2.js @@ -10,12 +10,12 @@ includes: [propertyHelper.js] // CHECK#1 verifyNotWritable(Number, "NEGATIVE_INFINITY", null, 1); -if (isFinite(Number.NEGATIVE_INFINITY)) { - throw new Test262Error('#1: Number.NEGATIVE_INFINITY = 1; Number.NEGATIVE_INFINITY === -Infinity'); -} else { - if (Number.NEGATIVE_INFINITY >= 0) { - throw new Test262Error('#1: Number.NEGATIVE_INFINITY = 1; Number.NEGATIVE_INFINITY === -Infinity'); - } -} + +assert( + !isFinite(Number.NEGATIVE_INFINITY), + 'The value of !isFinite(Number.NEGATIVE_INFINITY) is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/POSITIVE_INFINITY/S15.7.3.6_A1.js b/js/src/tests/test262/built-ins/Number/POSITIVE_INFINITY/S15.7.3.6_A1.js index 9f1bb8daf4ca..952ffa04ba02 100644 --- a/js/src/tests/test262/built-ins/Number/POSITIVE_INFINITY/S15.7.3.6_A1.js +++ b/js/src/tests/test262/built-ins/Number/POSITIVE_INFINITY/S15.7.3.6_A1.js @@ -6,14 +6,6 @@ info: Number.POSITIVE_INFINITY is +Infinity es5id: 15.7.3.6_A1 description: Checking sign and finiteness of Number.POSITIVE_INFINITY ---*/ - -// CHECK#1 -if (isFinite(Number.POSITIVE_INFINITY) !== false) { - throw new Test262Error('#1: Number.POSITIVE_INFINITY === Not-a-Finite'); -} else { - if ((Number.POSITIVE_INFINITY > 0) !== true) { - throw new Test262Error('#1: Number.POSITIVE_INFINITY === +Infinity'); - } -} +assert.sameValue(isFinite(Number.POSITIVE_INFINITY), false, 'isFinite(Number.POSITIVE_INFINITY) must return false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/POSITIVE_INFINITY/S15.7.3.6_A2.js b/js/src/tests/test262/built-ins/Number/POSITIVE_INFINITY/S15.7.3.6_A2.js index 34cb2a02bd6e..f4cb7e4165b9 100644 --- a/js/src/tests/test262/built-ins/Number/POSITIVE_INFINITY/S15.7.3.6_A2.js +++ b/js/src/tests/test262/built-ins/Number/POSITIVE_INFINITY/S15.7.3.6_A2.js @@ -10,12 +10,12 @@ includes: [propertyHelper.js] // CHECK#1 verifyNotWritable(Number, "POSITIVE_INFINITY", null, 1); -if (isFinite(Number.POSITIVE_INFINITY)) { - throw new Test262Error('#1: Number.POSITIVE_INFINITY = 1; Number.POSITIVE_INFINITY === +Infinity'); -} else { - if (Number.POSITIVE_INFINITY <= 0) { - throw new Test262Error('#1: Number.POSITIVE_INFINITY = 1; Number.POSITIVE_INFINITY === +Infinity'); - } -} + +assert( + !isFinite(Number.POSITIVE_INFINITY), + 'The value of !isFinite(Number.POSITIVE_INFINITY) is expected to be true' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.1.1_A1.js b/js/src/tests/test262/built-ins/Number/S15.7.1.1_A1.js index c6ee7ca43c80..0e4eb4fc9277 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.1.1_A1.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.1.1_A1.js @@ -8,28 +8,23 @@ info: | es5id: 15.7.1.1_A1 description: Used values "10", 10, new String("10"), new Object(10) and "abc" ---*/ +assert.sameValue(typeof Number("10"), "number", 'The value of `typeof Number("10")` is expected to be "number"'); +assert.sameValue(typeof Number(10), "number", 'The value of `typeof Number(10)` is expected to be "number"'); -//CHECK#1 -if (typeof Number("10") !== "number") { - throw new Test262Error('#1: typeof Number("10") should be "number", actual is "' + typeof Number("10") + '"'); -} +assert.sameValue( + typeof Number(new String("10")), + "number", + 'The value of `typeof Number(new String("10"))` is expected to be "number"' +); -//CHECK#2 -if (typeof Number(10) !== "number") { - throw new Test262Error('#2: typeof Number(10) should be "number", actual is "' + typeof Number(10) + '"'); -} +assert.sameValue( + typeof Number(new Object(10)), + "number", + 'The value of `typeof Number(new Object(10))` is expected to be "number"' +); -//CHECK#3 -if (typeof Number(new String("10")) !== "number") { - throw new Test262Error('#3: typeof Number(new String("10")) should be "number", actual is "' + typeof Number(new String("10")) + '"'); -} - -//CHECK#4 -if (typeof Number(new Object(10)) !== "number") { - throw new Test262Error('#4: typeof Number(new Object(10)) should be "number", actual is "' + typeof Number(new Object(10)) + '"'); -} - -//CHECK #5 -assert.sameValue(Number("abc"), NaN, "Number('abc')"); +assert.sameValue(Number("abc"), NaN, 'Number("abc") returns NaN'); +assert.sameValue(Number("INFINITY"), NaN, 'Number("INFINITY") returns NaN'); +assert.sameValue(Number("infinity"), NaN, 'Number("infinity") returns NaN'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.1.1_A2.js b/js/src/tests/test262/built-ins/Number/S15.7.1.1_A2.js index f1fcccc9de98..33366b121ccf 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.1.1_A2.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.1.1_A2.js @@ -6,17 +6,7 @@ info: Number() returns +0 es5id: 15.7.1.1_A2 description: Call Number() and check result ---*/ - -//CHECK#1 -if (typeof Number() !== "number") { - throw new Test262Error('#1: typeof Number() should be "number", actual is "' + typeof Number() + '"'); -} - -//CHECK#2 -if (Number() !== 0) { - throw new Test262Error('#2: Number() === 0, actual is ' + Number()); -} else if (1 / Number() !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#2: Number() === +0, actual is ' + Number()); -} +assert.sameValue(typeof Number(), "number", 'The value of `typeof Number()` is expected to be "number"'); +assert.sameValue(Number(), 0, 'Number() must return 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.2.1_A1.js b/js/src/tests/test262/built-ins/Number/S15.7.2.1_A1.js index 8ebe554fd559..098440c68ac0 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.2.1_A1.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.2.1_A1.js @@ -8,49 +8,21 @@ info: | es5id: 15.7.2.1_A1 description: Checking type of the newly created object and it value ---*/ +assert.sameValue(typeof new Number(), "object", 'The value of `typeof new Number()` is expected to be "object"'); +assert.notSameValue(new Number(), undefined, 'new Number() is expected to not equal ``undefined``'); -//CHECK#1 -if (typeof new Number() !== "object") { - throw new Test262Error("#1: typeof new Number() === 'object'"); -} - -//CHECK#2 -if (new Number() === undefined) { - throw new Test262Error("#2: new Number() should not be undefined"); -} - -//CHECK#3 var x3 = new Number(); -if (typeof x3 !== "object") { - throw new Test262Error("#3: typeof new Number() === 'object'"); -} +assert.sameValue(typeof x3, "object", 'The value of `typeof x3` is expected to be "object"'); -//CHECK#4 var x4 = new Number(); -if (x4 === undefined) { - throw new Test262Error("#4: new Number() should not be undefined"); -} +assert.notSameValue(x4, undefined, 'The value of x4 is expected to not equal ``undefined``'); +assert.sameValue(typeof new Number(10), "object", 'The value of `typeof new Number(10)` is expected to be "object"'); +assert.notSameValue(new Number(10), undefined, 'new Number(10) is expected to not equal ``undefined``'); -//CHECK#5 -if (typeof new Number(10) !== "object") { - throw new Test262Error("#5: typeof new Number(10) === 'object'"); -} - -//CHECK#6 -if (new Number(10) === undefined) { - throw new Test262Error("#6: new Number(10) should not be undefined"); -} - -//CHECK#7 var x7 = new Number(10); -if (typeof x7 !== "object") { - throw new Test262Error("#7: typeof new Number(10) === 'object'"); -} +assert.sameValue(typeof x7, "object", 'The value of `typeof x7` is expected to be "object"'); -//CHECK#8 var x8 = new Number(10); -if (x8 === undefined) { - throw new Test262Error("#8: new Number(10) should not be undefined"); -} +assert.notSameValue(x8, undefined, 'The value of x8 is expected to not equal ``undefined``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.2.1_A2.js b/js/src/tests/test262/built-ins/Number/S15.7.2.1_A2.js index bc986ee73db5..a20ca2036a1f 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.2.1_A2.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.2.1_A2.js @@ -12,20 +12,22 @@ description: Checking prototype property of the newly created objects // CHECK#1 var x1 = new Number(1); -if (typeof x1.constructor.prototype !== "object") { - throw new Test262Error('#1: typeof x1.constructor.prototype === "object"'); -} -//CHECK#2 +assert.sameValue( + typeof x1.constructor.prototype, + "object", + 'The value of `typeof x1.constructor.prototype` is expected to be "object"' +); + var x2 = new Number(2); -if (!Number.prototype.isPrototypeOf(x2)) { - throw new Test262Error('#2: Number.prototype.isPrototypeOf(x2)'); -} +assert(Number.prototype.isPrototypeOf(x2), 'Number.prototype.isPrototypeOf(x2) must return true'); -//CHECK#3 var x3 = new Number(3); -if (Number.prototype !== x3.constructor.prototype) { - throw new Test262Error('#3: Number.prototype === x3.constructor.prototype'); -} + +assert.sameValue( + Number.prototype, + x3.constructor.prototype, + 'The value of Number.prototype is expected to equal the value of x3.constructor.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.2.1_A3.js b/js/src/tests/test262/built-ins/Number/S15.7.2.1_A3.js index 42ac50b299ca..769160fe4777 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.2.1_A3.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.2.1_A3.js @@ -9,18 +9,10 @@ es5id: 15.7.2.1_A3 description: Checking value of the newly created object ---*/ -//CHECK#1 var x1 = new Number(1); -if (x1.valueOf() !== 1) { - throw new Test262Error('#1: var x1 = new Number(1); x1.valueOf() === 1'); -} +assert.sameValue(x1.valueOf(), 1, 'x1.valueOf() must return 1'); -//CHECK#2 var x2 = new Number(); -if (x2.valueOf() !== 0) { - throw new Test262Error('#2.1: var x2 = new Number(); x2.valueOf() === 0'); -} else if (1 / x2.valueOf() !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#2.2: var x2 = new Number(); x2.valueOf() === +0'); -} +assert.sameValue(x2.valueOf(), 0, 'x2.valueOf() must return 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.2.1_A4.js b/js/src/tests/test262/built-ins/Number/S15.7.2.1_A4.js index 9e912712725b..828f6ee7e420 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.2.1_A4.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.2.1_A4.js @@ -13,9 +13,6 @@ delete Number.prototype.toString; var obj = new Number(); -//CHECK#1 -if (obj.toString() !== "[object Number]") { - throw new Test262Error('#1: The [[Class]] property of the newly constructed object is set to "Number"'); -} +assert.sameValue(obj.toString(), "[object Number]", 'obj.toString() must return "[object Number]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.3_A1.js b/js/src/tests/test262/built-ins/Number/S15.7.3_A1.js index 5a405c90c585..6c437d1647a4 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.3_A1.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.3_A1.js @@ -6,9 +6,6 @@ info: The Number constructor has the property "prototype" es5id: 15.7.3_A1 description: Checking existence of the property "prototype" ---*/ - -if (!Number.hasOwnProperty("prototype")) { - throw new Test262Error('#1: The Number constructor has the property "prototype"'); -} +assert(Number.hasOwnProperty("prototype"), 'Number.hasOwnProperty("prototype") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.3_A2.js b/js/src/tests/test262/built-ins/Number/S15.7.3_A2.js index 65aded8d2cc2..461661c9274b 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.3_A2.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.3_A2.js @@ -6,9 +6,6 @@ info: The Number constructor has the property "MAX_VALUE" es5id: 15.7.3_A2 description: Checking existence of the property "MAX_VALUE" ---*/ - -if (!Number.hasOwnProperty("MAX_VALUE")) { - throw new Test262Error('#1: The Number constructor has the property "MAX_VALUE"'); -} +assert(Number.hasOwnProperty("MAX_VALUE"), 'Number.hasOwnProperty("MAX_VALUE") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.3_A3.js b/js/src/tests/test262/built-ins/Number/S15.7.3_A3.js index 8bdb666036ea..667be90e5d7e 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.3_A3.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.3_A3.js @@ -6,9 +6,6 @@ info: The Number constructor has the property "MIN_VALUE" es5id: 15.7.3_A3 description: Checking existence of the property "MIN_VALUE" ---*/ - -if (!Number.hasOwnProperty("MIN_VALUE")) { - throw new Test262Error('#1: The Number constructor has the property "MIN_VALUE"'); -} +assert(Number.hasOwnProperty("MIN_VALUE"), 'Number.hasOwnProperty("MIN_VALUE") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.3_A4.js b/js/src/tests/test262/built-ins/Number/S15.7.3_A4.js index 4e70d1fa830c..a29ab88e7c30 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.3_A4.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.3_A4.js @@ -6,9 +6,6 @@ info: The Number constructor has the property "NaN" es5id: 15.7.3_A4 description: Checking existence of the property "NaN" ---*/ - -if (!Number.hasOwnProperty("NaN")) { - throw new Test262Error('#1: The Number constructor has the property "NaN"'); -} +assert(Number.hasOwnProperty("NaN"), 'Number.hasOwnProperty("NaN") must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.3_A5.js b/js/src/tests/test262/built-ins/Number/S15.7.3_A5.js index 4fc802b404d8..1532cb554724 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.3_A5.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.3_A5.js @@ -6,9 +6,9 @@ info: The Number constructor has the property "NEGATIVE_INFINITY" es5id: 15.7.3_A5 description: Checking existence of the property "NEGATIVE_INFINITY" ---*/ - -if (!Number.hasOwnProperty("NEGATIVE_INFINITY")) { - throw new Test262Error('#1: The Number constructor has the property "NEGATIVE_INFINITY"'); -} +assert( + Number.hasOwnProperty("NEGATIVE_INFINITY"), + 'Number.hasOwnProperty("NEGATIVE_INFINITY") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.3_A6.js b/js/src/tests/test262/built-ins/Number/S15.7.3_A6.js index d2aad1ac0471..6128b1e3b1ce 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.3_A6.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.3_A6.js @@ -6,9 +6,9 @@ info: The Number constructor has the property "POSITIVE_INFINITY" es5id: 15.7.3_A6 description: Checking existence of the property "POSITIVE_INFINITY" ---*/ - -if (!Number.hasOwnProperty("POSITIVE_INFINITY")) { - throw new Test262Error('#1: The Number constructor has the property "POSITIVE_INFINITY"'); -} +assert( + Number.hasOwnProperty("POSITIVE_INFINITY"), + 'Number.hasOwnProperty("POSITIVE_INFINITY") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.3_A7.js b/js/src/tests/test262/built-ins/Number/S15.7.3_A7.js index 8addb25d5ddb..ddeff380b126 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.3_A7.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.3_A7.js @@ -8,10 +8,9 @@ info: | es5id: 15.7.3_A7 description: Checking Function.prototype.isPrototypeOf(Number) ---*/ - -//CHECK#1 -if (!(Function.prototype.isPrototypeOf(Number))) { - throw new Test262Error('#1: the value of the internal [[Prototype]] property of the Number constructor is the Function prototype object.'); -} +assert( + Function.prototype.isPrototypeOf(Number), + 'Function.prototype.isPrototypeOf(Number) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.3_A8.js b/js/src/tests/test262/built-ins/Number/S15.7.3_A8.js index 5414ed90a0c5..d2a8008e1372 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.3_A8.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.3_A8.js @@ -6,15 +6,7 @@ info: Number constructor has length property whose value is 1 es5id: 15.7.3_A8 description: Checking Number.length property ---*/ - -//CHECK#1 -if (!Number.hasOwnProperty("length")) { - throw new Test262Error('#1: Number constructor has length property'); -} - -//CHECK#2 -if (Number.length !== 1) { - throw new Test262Error('#2: Number constructor length property value is 1'); -} +assert(Number.hasOwnProperty("length"), 'Number.hasOwnProperty("length") must return true'); +assert.sameValue(Number.length, 1, 'The value of Number.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T01.js b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T01.js index 4c928170a722..17087e7bebdb 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T01.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T01.js @@ -8,15 +8,16 @@ info: | es5id: 15.7.5_A1_T01 description: Checking property constructor ---*/ +assert.sameValue( + (new Number()).hasOwnProperty("constructor"), + false, + '(new Number()).hasOwnProperty("constructor") must return false' +); -//CHECK#1 -if ((new Number()).hasOwnProperty("constructor") !== false) { - throw new Test262Error('#1: Number instance must have no special property "constructor"'); -} - -//CHECK#2 -if ((new Number()).constructor !== Number.prototype.constructor) { - throw new Test262Error('#2: Number instance property "constructor" must be inherited from Number prototype object'); -} +assert.sameValue( + (new Number()).constructor, + Number.prototype.constructor, + 'The value of (new Number()).constructor is expected to equal the value of Number.prototype.constructor' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T02.js b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T02.js index 7f4346b9ade6..0133a5363520 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T02.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T02.js @@ -8,15 +8,16 @@ info: | es5id: 15.7.5_A1_T02 description: Checking property toString ---*/ +assert.sameValue( + (new Number()).hasOwnProperty("toString"), + false, + '(new Number()).hasOwnProperty("toString") must return false' +); -//CHECK#1 -if ((new Number()).hasOwnProperty("toString") !== false) { - throw new Test262Error('#1: Number instance must have no special property "toString"'); -} - -//CHECK#2 -if ((new Number()).toString !== Number.prototype.toString) { - throw new Test262Error('#2: Number instance property "toString" must be inherited from Number prototype object'); -} +assert.sameValue( + (new Number()).toString, + Number.prototype.toString, + 'The value of (new Number()).toString is expected to equal the value of Number.prototype.toString' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T03.js b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T03.js index cf55508e0cf9..e44a4fca309f 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T03.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T03.js @@ -8,15 +8,16 @@ info: | es5id: 15.7.5_A1_T03 description: Checking property toLocaleString ---*/ +assert.sameValue( + (new Number()).hasOwnProperty("toLocaleString"), + false, + '(new Number()).hasOwnProperty("toLocaleString") must return false' +); -//CHECK#1 -if ((new Number()).hasOwnProperty("toLocaleString") !== false) { - throw new Test262Error('#1: Number instance must have no special property "toLocaleString"'); -} - -//CHECK#2 -if ((new Number()).toLocaleString !== Number.prototype.toLocaleString) { - throw new Test262Error('#2: Number instance property "toLocaleString" must be inherited from Number prototype object'); -} +assert.sameValue( + (new Number()).toLocaleString, + Number.prototype.toLocaleString, + 'The value of (new Number()).toLocaleString is expected to equal the value of Number.prototype.toLocaleString' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T04.js b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T04.js index f5fc5257076d..15fc2b0174cb 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T04.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T04.js @@ -8,15 +8,16 @@ info: | es5id: 15.7.5_A1_T04 description: Checking property valueOf ---*/ +assert.sameValue( + (new Number()).hasOwnProperty("valueOf"), + false, + '(new Number()).hasOwnProperty("valueOf") must return false' +); -//CHECK#1 -if ((new Number()).hasOwnProperty("valueOf") !== false) { - throw new Test262Error('#1: Number instance must have no special property "valueOf"'); -} - -//CHECK#2 -if ((new Number()).valueOf !== Number.prototype.valueOf) { - throw new Test262Error('#2: Number instance property "valueOf" must be inherited from Number prototype object'); -} +assert.sameValue( + (new Number()).valueOf, + Number.prototype.valueOf, + 'The value of (new Number()).valueOf is expected to equal the value of Number.prototype.valueOf' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T05.js b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T05.js index 466c8c84e2d7..9018d6943749 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T05.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T05.js @@ -8,15 +8,16 @@ info: | es5id: 15.7.5_A1_T05 description: Checking property toFixed ---*/ +assert.sameValue( + (new Number()).hasOwnProperty("toFixed"), + false, + '(new Number()).hasOwnProperty("toFixed") must return false' +); -//CHECK#1 -if ((new Number()).hasOwnProperty("toFixed") !== false) { - throw new Test262Error('#1: Number instance must have no special property "toFixed"'); -} - -//CHECK#2 -if ((new Number()).toFixed !== Number.prototype.toFixed) { - throw new Test262Error('#2: Number instance property "toFixed" must be inherited from Number prototype object'); -} +assert.sameValue( + (new Number()).toFixed, + Number.prototype.toFixed, + 'The value of (new Number()).toFixed is expected to equal the value of Number.prototype.toFixed' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T06.js b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T06.js index fcf95953f3ae..171fee6baacb 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T06.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T06.js @@ -8,15 +8,16 @@ info: | es5id: 15.7.5_A1_T06 description: Checking property toExponential ---*/ +assert.sameValue( + (new Number()).hasOwnProperty("toExponential"), + false, + '(new Number()).hasOwnProperty("toExponential") must return false' +); -//CHECK#1 -if ((new Number()).hasOwnProperty("toExponential") !== false) { - throw new Test262Error('#1: Number instance must have no special property "toExponential"'); -} - -//CHECK#2 -if ((new Number()).toExponential !== Number.prototype.toExponential) { - throw new Test262Error('#2: Number instance property "toExponential" must be inherited from Number prototype object'); -} +assert.sameValue( + (new Number()).toExponential, + Number.prototype.toExponential, + 'The value of (new Number()).toExponential is expected to equal the value of Number.prototype.toExponential' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T07.js b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T07.js index eaacbdad6b4b..0425a8f39da5 100644 --- a/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T07.js +++ b/js/src/tests/test262/built-ins/Number/S15.7.5_A1_T07.js @@ -8,15 +8,16 @@ info: | es5id: 15.7.5_A1_T07 description: Checking property toPrecision ---*/ +assert.sameValue( + (new Number()).hasOwnProperty("toPrecision"), + false, + '(new Number()).hasOwnProperty("toPrecision") must return false' +); -//CHECK#1 -if ((new Number()).hasOwnProperty("toPrecision") !== false) { - throw new Test262Error('#1: Number instance must have no special property "toPrecision"'); -} - -//CHECK#2 -if ((new Number()).toPrecision !== Number.prototype.toPrecision) { - throw new Test262Error('#2: Number instance property "toPrecision" must be inherited from Number prototype object'); -} +assert.sameValue( + (new Number()).toPrecision, + Number.prototype.toPrecision, + 'The value of (new Number()).toPrecision is expected to equal the value of Number.prototype.toPrecision' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S8.12.8_A3.js b/js/src/tests/test262/built-ins/Number/S8.12.8_A3.js index 43fb538de043..8026aeb04e9e 100644 --- a/js/src/tests/test262/built-ins/Number/S8.12.8_A3.js +++ b/js/src/tests/test262/built-ins/Number/S8.12.8_A3.js @@ -21,9 +21,12 @@ try return new Object(); } } - if (Number(__obj) !== 1) { - throw new Test262Error('#1.1: var __obj = {toNumber: function() {return "1"}, valueOf: function() {return new Object();}}; Number(__obj) === 1. Actual: ' + (Number(__obj))); - } + + assert.sameValue( + Number(__obj), + 1, + 'Number("{toString: function() {return "1"}, valueOf: function() {return new Object();}}) must return 1' + ); } catch (e) { diff --git a/js/src/tests/test262/built-ins/Number/S8.12.8_A4.js b/js/src/tests/test262/built-ins/Number/S8.12.8_A4.js index 99ab54e57911..368cccc2afef 100644 --- a/js/src/tests/test262/built-ins/Number/S8.12.8_A4.js +++ b/js/src/tests/test262/built-ins/Number/S8.12.8_A4.js @@ -26,9 +26,11 @@ try } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: var __obj = {valueOf:function(){return new Object;},toNumber: function() {return new Object();}}; Number(__obj) throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.1_A1_T1.js b/js/src/tests/test262/built-ins/Number/S9.1_A1_T1.js index 1f46ead2b3c4..0b1ba8b0b454 100644 --- a/js/src/tests/test262/built-ins/Number/S9.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.1_A1_T1.js @@ -20,9 +20,12 @@ var object = { return 0 } }; -if (Number(object) !== 1) { - throw new Test262Error('#1: var object = {valueOf: function() {return "1"}, toString: function() {return 0}}; Number(object) === 1. Actual: ' + (Number(object))); -} + +assert.sameValue( + Number(object), + 1, + 'Number({valueOf: function() {return "1"}, toString: function() {return 0}}) must return 1' +); // CHECK#2 var object = { @@ -33,8 +36,11 @@ var object = { return "0" } }; -if (Number(object) !== 0) { - throw new Test262Error('#2: var object = {valueOf: function() {return {}}, toString: function() {return "0"}}; Number(object) === 0. Actual: ' + (Number(object))); -} + +assert.sameValue( + Number(object), + 0, + 'Number({valueOf: function() {return {}}, toString: function() {return "0"}}) must return 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A1.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A1.js index 0a0c24c1b2d3..dc7a2cbbfaec 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A1.js @@ -6,14 +6,6 @@ info: "The MV of StringNumericLiteral ::: [empty] is 0" es5id: 9.3.1_A1 description: Number('') convert to Number by explicit transformation ---*/ - -// CHECK#1 -if (Number("") !== 0) { - throw new Test262Error('#1.1: Number("") === 0. Actual: ' + (Number(""))); -} else { - if (1 / Number("") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#1.2: Number("") == +0. Actual: -0'); - } -} +assert.sameValue(Number(""), 0, 'Number("") must return 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A10.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A10.js index 93ed99fc1f55..c472cc68ec72 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A10.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A10.js @@ -9,10 +9,6 @@ info: | es5id: 9.3.1_A10 description: Compare Number('.12345') with +('12345')*1e-5 ---*/ - -// CHECK#1 -if (Number(".12345") !== +("12345") * 1e-5) { - throw new Test262Error('#1: Number(".12345") === +("12345")*1e-5'); -} +assert.sameValue(+('12345')*1e-5, 0.12345); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A11.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A11.js index 59e138aeff99..7c6fd6935a03 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A11.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A11.js @@ -11,15 +11,11 @@ description: > Compare Number('.12345e6') with +('12345')*1e1, and Number('.12345e-3') !== Number('12345')*1e-8 ---*/ +assert.sameValue(+('12345')*1e1, 0.12345e6); -// CHECK#1 -if (Number(".12345e6") !== +("12345") * 1e1) { - throw new Test262Error('#1: Number(".12345e6") === +("12345")*1e1'); -} - -// CHECK#2 -if (Number(".12345e-3") !== Number("12345") * 1e-8) { - throw new Test262Error('#2: Number(".12345e-3") === Number("12345")*1e-8'); -} +assert.sameValue( + Number(".12345e-3"), + 0.00012345 +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A12.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A12.js index f344d613cfed..9c4620550638 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A12.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A12.js @@ -10,15 +10,7 @@ description: > Compare Number('12345e6') with +('12345')*1e1, and Number('12345e-6') !== Number('12345')*1e-6 ---*/ - -// CHECK#1 -if (Number("12345e6") !== +("12345") * 1e6) { - throw new Test262Error('#1: Number("12345e6") === +("12345")*1e6'); -} - -// CHECK#2 -if (Number("12345e-6") !== Number("12345") * 1e-6) { - throw new Test262Error('#2: Number("12345e-6") === Number("12345")*1e-6'); -} +assert.sameValue(Number("12345e6"), 12345000000, 'Number("12345e6") must return 12345000000'); +assert.sameValue(Number("12345e-6"), 0.012345, 'Number("12345e-6") must return 0.012345'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A13.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A13.js index ee14d3145143..75eff28871d9 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A13.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A13.js @@ -8,20 +8,22 @@ info: | es5id: 9.3.1_A13 description: Compare '12' with Number("1")*10+Number("2") and analogous ---*/ +assert.sameValue( + +("12"), + 12, + 'The value of `+("12")` is expected to be 12' +); -// CHECK#1 -if (+("12") !== Number("1") * 10 + Number("2")) { - throw new Test262Error('#1: +("12") === Number("1")*10+Number("2")'); -} +assert.sameValue( + Number("123"), + 123, + 'Number("123") must return 123' +); -// CHECK#2 -if (Number("123") !== Number("12") * 10 + Number("3")) { - throw new Test262Error('#2: Number("123") === Number("12")*10+Number("3")'); -} - -// CHECK#2 -if (Number("1234") !== Number("123") * 10 + Number("4")) { - throw new Test262Error('#2: Number("1234") === Number("123")*10+Number("4")'); -} +assert.sameValue( + Number("1234"), + 1234, + 'Number("1234") must return 1234' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A14.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A14.js index 3a20d457cc04..fd93b601f8e4 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A14.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A14.js @@ -6,10 +6,6 @@ info: "The MV of SignedInteger ::: + DecimalDigits is the MV of DecimalDigits" es5id: 9.3.1_A14 description: Compare Number('+1234567890') with +('1234567890') ---*/ - -// CHECK#1 -if (Number("+1234567890") !== +("1234567890")) { - throw new Test262Error('#1: Number("+1234567890") === +("1234567890")'); -} +assert.sameValue(Number("+1234567890"), 1234567890, 'Number("+1234567890") must return 1234567890'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A15.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A15.js index d027a0684ac0..f0ca373bd01a 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A15.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A15.js @@ -8,10 +8,10 @@ info: | es5id: 9.3.1_A15 description: Compare -Number('1234567890') with ('-1234567890') ---*/ - -// CHECK#1 -if (+("-1234567890") !== -Number("1234567890")) { - throw new Test262Error('#1: +("-1234567890") === -Number("1234567890")'); -} +assert.sameValue( + +("-1234567890"), + -1234567890, + 'The value of `+("-1234567890")` is expected to be -1234567890' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A16.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A16.js index 33ad0790295c..f8736d7d624a 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A16.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A16.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 0 or of HexDigit ::: 0 is 0" es5id: 9.3.1_A16 description: Compare Number('0x0') and Number('0X0') with 0 ---*/ - -// CHECK#1 -if (Number("0") !== 0) { - throw new Test262Error('#1: Number("0") === 0. Actual: ' + (Number("0"))); -} - -// CHECK#2 -if (+("0x0") !== 0) { - throw new Test262Error('#2: +("0x0") === 0. Actual: ' + (+("0x0"))); -} - -// CHECK#3 -if (Number("0X0") !== 0) { - throw new Test262Error('#3: Number("0X0") === 0. Actual: ' + (Number("0X0"))); -} +assert.sameValue(Number("0"), 0, 'Number("0") must return 0'); +assert.sameValue(+("0x0"), 0, 'The value of `+("0x0")` is expected to be 0'); +assert.sameValue(Number("0X0"), 0, 'Number("0X0") must return 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A17.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A17.js index 7deb85d631f0..a2890bf77c7f 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A17.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A17.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 1 or of HexDigit ::: 1 is 1" es5id: 9.3.1_A17 description: Compare Number('0x1') and Number('0X1') with 1 ---*/ - -// CHECK#1 -if (Number("1") !== 1) { - throw new Test262Error('#1: Number("1") === 1. Actual: ' + (Number("1"))); -} - -// CHECK#2 -if (Number("0x1") !== 1) { - throw new Test262Error('#2: Number("0x1") === 1. Actual: ' + (Number("0x1"))); -} - -// CHECK#3 -if (+("0X1") !== 1) { - throw new Test262Error('#3: +("0X1") === 1. Actual: ' + (+("0X1"))); -} +assert.sameValue(Number("1"), 1, 'Number("1") must return 1'); +assert.sameValue(Number("0x1"), 1, 'Number("0x1") must return 1'); +assert.sameValue(+("0X1"), 1, 'The value of `+("0X1")` is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A18.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A18.js index 82d00d5fb324..624beabf606d 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A18.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A18.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 2 or of HexDigit ::: 2 is 2" es5id: 9.3.1_A18 description: Compare Number('0x2') and Number('0X2') with 2 ---*/ - -// CHECK#1 -if (+("2") !== 2) { - throw new Test262Error('#1: +("2") === 2. Actual: ' + (+("2"))); -} - -// CHECK#2 -if (Number("0x2") !== 2) { - throw new Test262Error('#2: Number("0x2") === 2. Actual: ' + (Number("0x2"))); -} - -// CHECK#3 -if (Number("0X2") !== 2) { - throw new Test262Error('#3: Number("0X2") === 2. Actual: ' + (Number("0X2"))); -} +assert.sameValue(+("2"), 2, 'The value of `+("2")` is expected to be 2'); +assert.sameValue(Number("0x2"), 2, 'Number("0x2") must return 2'); +assert.sameValue(Number("0X2"), 2, 'Number("0X2") must return 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A19.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A19.js index aacc923dc594..0a8dce1020f0 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A19.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A19.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 3 or of HexDigit ::: 3 is 3" es5id: 9.3.1_A19 description: Compare Number('0x3') and Number('0X3') with 3 ---*/ - -// CHECK#1 -if (Number("3") !== 3) { - throw new Test262Error('#1: Number("3") === 3. Actual: ' + (Number("3"))); -} - -// CHECK#2 -if (+("0x3") !== 3) { - throw new Test262Error('#2: +("0x3") === 3. Actual: ' + (+("0x3"))); -} - -// CHECK#3 -if (Number("0X3") !== 3) { - throw new Test262Error('#3: Number("0X3") === 3. Actual: ' + (Number("0X3"))); -} +assert.sameValue(Number("3"), 3, 'Number("3") must return 3'); +assert.sameValue(+("0x3"), 3, 'The value of `+("0x3")` is expected to be 3'); +assert.sameValue(Number("0X3"), 3, 'Number("0X3") must return 3'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A2.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A2.js index 834c4b543f94..69a8293140d3 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A2.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A2.js @@ -8,275 +8,40 @@ description: > Strings with various WhiteSpaces convert to Number by explicit transformation ---*/ +assert.sameValue( + Number("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000"), + 0, + 'Number("u0009u000Cu0020u00A0u000Bu000Au000Du2028u2029u1680u2000u2001u2002u2003u2004u2005u2006u2007u2008u2009u200Au202Fu205Fu3000") must return 0' +); -// CHECK#1 -if (Number("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000") !== 0) { - throw new Test262Error('#1.1: Number("\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") === 0. Actual: ' + (Number("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000"))); -} else { - if (1 / Number("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#1.2: Number("\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") === +0. Actual: -0'); - } -} - -// CHECK#2 -if (Number(" ") !== 0) { - throw new Test262Error('#2.1: Number(" ") === 0. Actual: ' + (Number(" "))); -} else { - if (1 / Number(" ") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#2.2: Number(" ") === +0. Actual: -0'); - } -} - -// CHECK#3 -if (Number("\t") !== 0) { - throw new Test262Error('#3.1: Number("\\t") === 0. Actual: ' + (Number("\t"))); -} else { - if (1 / Number("\t") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#3.2: Number("\\t") === +0. Actual: -0'); - } -} - -// CHECK#4 -if (Number("\r") !== 0) { - throw new Test262Error('#4.1: Number("\\r") === 0. Actual: ' + (Number("\r"))); -} else { - if (1 / Number("\r") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#4.2: Number("\\r") === +0. Actual: -0'); - } -} - -// CHECK#5 -if (Number("\n") !== 0) { - throw new Test262Error('#5.1: Number("\\n") === 0. Actual: ' + (Number("\n"))); -} else { - if (1 / Number("\n") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#5.2: Number("\\n") === +0. Actual: -0'); - } -} - -// CHECK#6 -if (Number("\f") !== 0) { - throw new Test262Error('#6.1: Number("\\f") === 0. Actual: ' + (Number("\f"))); -} else { - if (1 / Number("\f") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#6.2: Number("\\f") === +0. Actual: -0'); - } -} - -// CHECK#7 -if (Number("\u0009") !== 0) { - throw new Test262Error('#7.1: Number("\\u0009") === 0. Actual: ' + (Number("\u0009"))); -} else { - if (1 / Number("\u0009") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#7.2: Number("\\u0009") === +0. Actual: -0'); - } -} - -// CHECK#8 -if (Number("\u000A") !== 0) { - throw new Test262Error('#8.1: Number("\\u000A") === 0. Actual: ' + (Number("\u000A"))); -} else { - if (1 / Number("\u000A") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#8.2: Number("\\u000A") === +0. Actual: -0'); - } -} - -// CHECK#9 -if (Number("\u000B") !== 0) { - throw new Test262Error('#9.1: Number("\\u000B") === 0. Actual: ' + (Number("\u000B"))); -} else { - if (1 / Number("\u000B") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#9.1.2: Number("\\u000B") === +0. Actual: -0'); - } -} - -// CHECK#10 -if (Number("\u000C") !== 0) { - throw new Test262Error('#10.1: Number("\\u000C") === 0. Actual: ' + (Number("\u000C"))); -} else { - if (1 / Number("\u000C") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#10.2: Number("\\u000C") === +0. Actual: -0'); - } -} - -// CHECK#11 -if (Number("\u000D") !== 0) { - throw new Test262Error('#11.1: Number("\\u000D") === 0. Actual: ' + (Number("\u000D"))); -} else { - if (1 / Number("\u000D") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#11.2: Number("\\u000D") === +0. Actual: -0'); - } -} - -// CHECK#12 -if (Number("\u00A0") !== 0) { - throw new Test262Error('#12.1: Number("\\u00A0") === 0. Actual: ' + (Number("\u00A0"))); -} else { - if (1 / Number("\u00A0") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#12.2: Number("\\u00A0") === +0. Actual: -0'); - } -} - -// CHECK#13 -if (Number("\u0020") !== 0) { - throw new Test262Error('#13.1: Number("\\u0020") === 0. Actual: ' + (Number("\u0020"))); -} else { - if (1 / Number("\u0020") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#13.2: Number("\\u0020") === +0. Actual: -0'); - } -} - -// CHECK#14 -if (Number("\u2028") !== 0) { - throw new Test262Error('#14.1: Number("\\u2028") === 0. Actual: ' + (Number("\u2028"))); -} else { - if (1 / Number("\u2028") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#14.2: Number("\\u2028") === +0. Actual: -0'); - } -} - -// CHECK#15 -if (Number("\u2029") !== 0) { - throw new Test262Error('#15.1: Number("\\u2029") === 0. Actual: ' + (Number("\u2029"))); -} else { - if (1 / Number("\u2029") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#15.2: Number("\\u2029") === +0. Actual: -0'); - } -} - -// CHECK#16 -if (Number("\u1680") !== 0) { - throw new Test262Error('#16.1: Number("\\u1680") === 0. Actual: ' + (Number("\u1680"))); -} else { - if (1 / Number("\u1680") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#16.2: Number("\\u1680") === +0. Actual: -0'); - } -} - -// CHECK#17 -if (Number("\u2000") !== 0) { - throw new Test262Error('#17.1: Number("\\u2000") === 0. Actual: ' + (Number("\u2000"))); -} else { - if (1 / Number("\u2000") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#17.2: Number("\\u2000") === +0. Actual: -0'); - } -} - -// CHECK#18 -if (Number("\u2001") !== 0) { - throw new Test262Error('#18.1: Number("\\u2001") === 0. Actual: ' + (Number("\u2001"))); -} else { - if (1 / Number("\u2001") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#18.2: Number("\\u2001") === +0. Actual: -0'); - } -} - -// CHECK#19 -if (Number("\u2002") !== 0) { - throw new Test262Error('#19.1: Number("\\u2002") === 0. Actual: ' + (Number("\u2002"))); -} else { - if (1 / Number("\u2002") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#19.2: Number("\\u2002") === +0. Actual: -0'); - } -} - -// CHECK#20 -if (Number("\u2003") !== 0) { - throw new Test262Error('#20.1: Number("\\u2003") === 0. Actual: ' + (Number("\u2003"))); -} else { - if (1 / Number("\u2003") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#20.2: Number("\\u2003") === +0. Actual: -0'); - } -} - -// CHECK#21 -if (Number("\u2004") !== 0) { - throw new Test262Error('#21.1: Number("\\u2004") === 0. Actual: ' + (Number("\u2004"))); -} else { - if (1 / Number("\u2004") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#21.2: Number("\\u2004") === +0. Actual: -0'); - } -} - -// CHECK#22 -if (Number("\u2005") !== 0) { - throw new Test262Error('#22.1: Number("\\u2005") === 0. Actual: ' + (Number("\u2005"))); -} else { - if (1 / Number("\u2005") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#22.2: Number("\\u2005") === +0. Actual: -0'); - } -} - -// CHECK#23 -if (Number("\u2006") !== 0) { - throw new Test262Error('#23.1: Number("\\u2006") === 0. Actual: ' + (Number("\u2006"))); -} else { - if (1 / Number("\u2006") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#23.2: Number("\\u2006") === +0. Actual: -0'); - } -} - -// CHECK#24 -if (Number("\u2007") !== 0) { - throw new Test262Error('#24.1: Number("\\u2007") === 0. Actual: ' + (Number("\u2007"))); -} else { - if (1 / Number("\u2007") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#24.2: Number("\\u2007") === +0. Actual: -0'); - } -} - -// CHECK#25 -if (Number("\u2008") !== 0) { - throw new Test262Error('#25.1: Number("\\u2008") === 0. Actual: ' + (Number("\u2008"))); -} else { - if (1 / Number("\u2008") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#25.2: Number("\\u2008") === +0. Actual: -0'); - } -} - -// CHECK#26 -if (Number("\u2009") !== 0) { - throw new Test262Error('#26.1: Number("\\u2009") === 0. Actual: ' + (Number("\u2009"))); -} else { - if (1 / Number("\u2009") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#26.2: Number("\\u2009") === +0. Actual: -0'); - } -} - -// CHECK#27 -if (Number("\u200A") !== 0) { - throw new Test262Error('#27.1: Number("\\u200A") === 0. Actual: ' + (Number("\u200A"))); -} else { - if (1 / Number("\u200A") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#27.2: Number("\\u200A") === +0. Actual: -0'); - } -} - -// CHECK#28 -if (Number("\u202F") !== 0) { - throw new Test262Error('#28.1: Number("\\u202F") === 0. Actual: ' + (Number("\u202F"))); -} else { - if (1 / Number("\u202F") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#28.2: Number("\\u202F") === +0. Actual: -0'); - } -} - -// CHECK#29 -if (Number("\u205F") !== 0) { - throw new Test262Error('#29.1: Number("\\u205F") === 0. Actual: ' + (Number("\u205F"))); -} else { - if (1 / Number("\u205F") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#29.2: Number("\\u205F") === +0. Actual: -0'); - } -} - -// CHECK#30 -if (Number("\u3000") !== 0) { - throw new Test262Error('#30.1: Number("\\u3000") === 0. Actual: ' + (Number("\u3000"))); -} else { - if (1 / Number("\u3000") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#30.2: Number("\\u3000") === +0. Actual: -0'); - } -} +assert.sameValue(Number(" "), 0, 'Number(" ") must return 0'); +assert.sameValue(Number("\t"), 0, 'Number("t") must return 0'); +assert.sameValue(Number("\r"), 0, 'Number("r") must return 0'); +assert.sameValue(Number("\n"), 0, 'Number("n") must return 0'); +assert.sameValue(Number("\f"), 0, 'Number("f") must return 0'); +assert.sameValue(Number("\u0009"), 0, 'Number("u0009") must return 0'); +assert.sameValue(Number("\u000A"), 0, 'Number("u000A") must return 0'); +assert.sameValue(Number("\u000B"), 0, 'Number("u000B") must return 0'); +assert.sameValue(Number("\u000C"), 0, 'Number("u000C") must return 0'); +assert.sameValue(Number("\u000D"), 0, 'Number("u000D") must return 0'); +assert.sameValue(Number("\u00A0"), 0, 'Number("u00A0") must return 0'); +assert.sameValue(Number("\u0020"), 0, 'Number("u0020") must return 0'); +assert.sameValue(Number("\u2028"), 0, 'Number("u2028") must return 0'); +assert.sameValue(Number("\u2029"), 0, 'Number("u2029") must return 0'); +assert.sameValue(Number("\u1680"), 0, 'Number("u1680") must return 0'); +assert.sameValue(Number("\u2000"), 0, 'Number("u2000") must return 0'); +assert.sameValue(Number("\u2001"), 0, 'Number("u2001") must return 0'); +assert.sameValue(Number("\u2002"), 0, 'Number("u2002") must return 0'); +assert.sameValue(Number("\u2003"), 0, 'Number("u2003") must return 0'); +assert.sameValue(Number("\u2004"), 0, 'Number("u2004") must return 0'); +assert.sameValue(Number("\u2005"), 0, 'Number("u2005") must return 0'); +assert.sameValue(Number("\u2006"), 0, 'Number("u2006") must return 0'); +assert.sameValue(Number("\u2007"), 0, 'Number("u2007") must return 0'); +assert.sameValue(Number("\u2008"), 0, 'Number("u2008") must return 0'); +assert.sameValue(Number("\u2009"), 0, 'Number("u2009") must return 0'); +assert.sameValue(Number("\u200A"), 0, 'Number("u200A") must return 0'); +assert.sameValue(Number("\u202F"), 0, 'Number("u202F") must return 0'); +assert.sameValue(Number("\u205F"), 0, 'Number("u205F") must return 0'); +assert.sameValue(Number("\u3000"), 0, 'Number("u3000") must return 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A20.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A20.js index 034728552a48..8e97858fb042 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A20.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A20.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 4 or of HexDigit ::: 4 is 4" es5id: 9.3.1_A20 description: Compare Number('0x4') and Number('0X4') with 4 ---*/ - -// CHECK#1 -if (Number("4") !== 4) { - throw new Test262Error('#1: Number("4") === 4. Actual: ' + (Number("4"))); -} - -// CHECK#2 -if (Number("0x4") !== 4) { - throw new Test262Error('#2: Number("0x4") === 4. Actual: ' + (Number("0x4"))); -} - -// CHECK#3 -if (+("0X4") !== 4) { - throw new Test262Error('#3: +("0X4") === 4. Actual: ' + (+("0X4"))); -} +assert.sameValue(Number("4"), 4, 'Number("4") must return 4'); +assert.sameValue(Number("0x4"), 4, 'Number("0x4") must return 4'); +assert.sameValue(+("0X4"), 4, 'The value of `+("0X4")` is expected to be 4'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A21.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A21.js index af7cb290fc55..016c5c98a34a 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A21.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A21.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 5 or of HexDigit ::: 5 is 5" es5id: 9.3.1_A21 description: Compare Number('0x5') and Number('0X5') with 5 ---*/ - -// CHECK#1 -if (+("5") !== 5) { - throw new Test262Error('#1: +("5") === 5. Actual: ' + (+("5"))); -} - -// CHECK#2 -if (Number("0x5") !== 5) { - throw new Test262Error('#2: Number("0x5") === 5. Actual: ' + (Number("0x5"))); -} - -// CHECK#3 -if (Number("0X5") !== 5) { - throw new Test262Error('#3: Number("0X5") === 5. Actual: ' + (Number("0X5"))); -} +assert.sameValue(+("5"), 5, 'The value of `+("5")` is expected to be 5'); +assert.sameValue(Number("0x5"), 5, 'Number("0x5") must return 5'); +assert.sameValue(Number("0X5"), 5, 'Number("0X5") must return 5'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A22.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A22.js index bf39a5990a82..d7100193f29c 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A22.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A22.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 6 or of HexDigit ::: 6 is 6" es5id: 9.3.1_A22 description: Compare Number('0x6') and Number('0X6') with 6 ---*/ - -// CHECK#1 -if (Number("6") !== 6) { - throw new Test262Error('#1: Number("6") === 6. Actual: ' + (Number("6"))); -} - -// CHECK#2 -if (+("0x6") !== 6) { - throw new Test262Error('#2: +("0x6") === 6. Actual: ' + (+("0x6"))); -} - -// CHECK#3 -if (Number("0X6") !== 6) { - throw new Test262Error('#3: Number("0X6") === 6. Actual: ' + (Number("0X6"))); -} +assert.sameValue(Number("6"), 6, 'Number("6") must return 6'); +assert.sameValue(+("0x6"), 6, 'The value of `+("0x6")` is expected to be 6'); +assert.sameValue(Number("0X6"), 6, 'Number("0X6") must return 6'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A23.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A23.js index b6fe7b68d1e8..ddcf4e19479f 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A23.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A23.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 7 or of HexDigit ::: 7 is 7" es5id: 9.3.1_A23 description: Compare Number('0x7') and Number('0X7') with 7 ---*/ - -// CHECK#1 -if (Number("7") !== 7) { - throw new Test262Error('#1: Number("7") === 7. Actual: ' + (Number("7"))); -} - -// CHECK#2 -if (Number("0x7") !== 7) { - throw new Test262Error('#2: Number("0x7") === 7. Actual: ' + (Number("0x7"))); -} - -// CHECK#3 -if (+("0X7") !== 7) { - throw new Test262Error('#3: +("0X7") === 7. Actual: ' + (+("0X7"))); -} +assert.sameValue(Number("7"), 7, 'Number("7") must return 7'); +assert.sameValue(Number("0x7"), 7, 'Number("0x7") must return 7'); +assert.sameValue(+("0X7"), 7, 'The value of `+("0X7")` is expected to be 7'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A24.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A24.js index ce13911d57d7..8de2e10e0c26 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A24.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A24.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 8 or of HexDigit ::: 8 is 8" es5id: 9.3.1_A24 description: Compare Number('0x8') and Number('0X8') with 8 ---*/ - -// CHECK#1 -if (+("8") !== 8) { - throw new Test262Error('#1: +("8") === 8. Actual: ' + (+("8"))); -} - -// CHECK#2 -if (Number("0x8") !== 8) { - throw new Test262Error('#2: Number("0x8") === 8. Actual: ' + (Number("0x8"))); -} - -// CHECK#3 -if (Number("0X8") !== 8) { - throw new Test262Error('#3: Number("0X8") === 8. Actual: ' + (Number("0X8"))); -} +assert.sameValue(+("8"), 8, 'The value of `+("8")` is expected to be 8'); +assert.sameValue(Number("0x8"), 8, 'Number("0x8") must return 8'); +assert.sameValue(Number("0X8"), 8, 'Number("0X8") must return 8'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A25.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A25.js index fdd44411c633..fe774d5ef7ac 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A25.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A25.js @@ -6,20 +6,8 @@ info: "The MV of DecimalDigit ::: 9 or of HexDigit ::: 9 is 9" es5id: 9.3.1_A25 description: Compare Number('0x9') and Number('0X9') with 9 ---*/ - -// CHECK#1 -if (Number("9") !== 9) { - throw new Test262Error('#1: Number("9") === 9. Actual: ' + (Number("9"))); -} - -// CHECK#2 -if (+("0x9") !== 9) { - throw new Test262Error('#2: +("0x9") === 9. Actual: ' + (+("0x9"))); -} - -// CHECK#3 -if (Number("0X9") !== 9) { - throw new Test262Error('#3: Number("0X9") === 9. Actual: ' + (Number("0X9"))); -} +assert.sameValue(Number("9"), 9, 'Number("9") must return 9'); +assert.sameValue(+("0x9"), 9, 'The value of `+("0x9")` is expected to be 9'); +assert.sameValue(Number("0X9"), 9, 'Number("0X9") must return 9'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A26.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A26.js index 7c6254b30f86..d4478fb67503 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A26.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A26.js @@ -8,25 +8,9 @@ description: > Compare Number('0xA'), Number('0XA'), Number('0xa') and Number('0Xa') with 10 ---*/ - -// CHECK#1 -if (Number("0xa") !== 10) { - throw new Test262Error('#1: Number("0xa") === 10. Actual: ' + (Number("0xa"))); -} - -// CHECK#2 -if (Number("0xA") !== 10) { - throw new Test262Error('#2: Number("0xA") === 10. Actual: ' + (Number("0xA"))); -} - -// CHECK#3 -if (Number("0Xa") !== 10) { - throw new Test262Error('#3: Number("0Xa") === 10. Actual: ' + (Number("0Xa"))); -} - -// CHECK#4 -if (+("0XA") !== 10) { - throw new Test262Error('#4: +("0XA") === 10. Actual: ' + (+("0XA"))); -} +assert.sameValue(Number("0xa"), 10, 'Number("0xa") must return 10'); +assert.sameValue(Number("0xA"), 10, 'Number("0xA") must return 10'); +assert.sameValue(Number("0Xa"), 10, 'Number("0Xa") must return 10'); +assert.sameValue(+("0XA"), 10, 'The value of `+("0XA")` is expected to be 10'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A27.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A27.js index fa3213c65d8a..4734892980ac 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A27.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A27.js @@ -8,25 +8,9 @@ description: > Compare Number('0xB'), Number('0XB'), Number('0xb') and Number('0Xb') with 11 ---*/ - -// CHECK#1 -if (Number("0xb") !== 11) { - throw new Test262Error('#1: Number("0xb") === 11. Actual: ' + (Number("0xb"))); -} - -// CHECK#2 -if (Number("0xB") !== 11) { - throw new Test262Error('#2: Number("0xB") === 11. Actual: ' + (Number("0xB"))); -} - -// CHECK#3 -if (+("0Xb") !== 11) { - throw new Test262Error('#3: +("0Xb") === 11. Actual: ' + (+("0Xb"))); -} - -// CHECK#4 -if (Number("0XB") !== 11) { - throw new Test262Error('#4: Number("0XB") === 11. Actual: ' + (Number("0XB"))); -} +assert.sameValue(Number("0xb"), 11, 'Number("0xb") must return 11'); +assert.sameValue(Number("0xB"), 11, 'Number("0xB") must return 11'); +assert.sameValue(+("0Xb"), 11, 'The value of `+("0Xb")` is expected to be 11'); +assert.sameValue(Number("0XB"), 11, 'Number("0XB") must return 11'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A28.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A28.js index c74aec5acc2d..788a12d4f717 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A28.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A28.js @@ -8,25 +8,9 @@ description: > Compare Number('0xC'), Number('0XC'), Number('0xc') and Number('0Xc') with 12 ---*/ - -// CHECK#1 -if (Number("0xc") !== 12) { - throw new Test262Error('#1: Number("0xc") === 12. Actual: ' + (Number("0xc"))); -} - -// CHECK#2 -if (+("0xC") !== 12) { - throw new Test262Error('#2: +("0xC") === 12. Actual: ' + (+("0xC"))); -} - -// CHECK#3 -if (Number("0Xc") !== 12) { - throw new Test262Error('#3: Number("0Xc") === 12. Actual: ' + (Number("0Xc"))); -} - -// CHECK#4 -if (Number("0XC") !== 12) { - throw new Test262Error('#4: Number("0XC") === 12. Actual: ' + (Number("0XC"))); -} +assert.sameValue(Number("0xc"), 12, 'Number("0xc") must return 12'); +assert.sameValue(+("0xC"), 12, 'The value of `+("0xC")` is expected to be 12'); +assert.sameValue(Number("0Xc"), 12, 'Number("0Xc") must return 12'); +assert.sameValue(Number("0XC"), 12, 'Number("0XC") must return 12'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A29.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A29.js index e9d1d2b14945..096a492fa984 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A29.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A29.js @@ -8,25 +8,9 @@ description: > Compare Number('0xD'), Number('0XD'), Number('0xd') and Number('0Xd') with 13 ---*/ - -// CHECK#1 -if (+("0xd") !== 13) { - throw new Test262Error('#1: +("0xd") === 13. Actual: ' + (+("0xd"))); -} - -// CHECK#2 -if (Number("0xD") !== 13) { - throw new Test262Error('#2: Number("0xD") === 13. Actual: ' + (Number("0xD"))); -} - -// CHECK#3 -if (Number("0Xd") !== 13) { - throw new Test262Error('#3: Number("0Xd") === 13. Actual: ' + (Number("0Xd"))); -} - -// CHECK#4 -if (Number("0XD") !== 13) { - throw new Test262Error('#4: Number("0XD") === 13. Actual: ' + (Number("0XD"))); -} +assert.sameValue(+("0xd"), 13, 'The value of `+("0xd")` is expected to be 13'); +assert.sameValue(Number("0xD"), 13, 'Number("0xD") must return 13'); +assert.sameValue(Number("0Xd"), 13, 'Number("0Xd") must return 13'); +assert.sameValue(Number("0XD"), 13, 'Number("0XD") must return 13'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A30.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A30.js index 9a1a7e042456..bff5be512caf 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A30.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A30.js @@ -8,25 +8,9 @@ description: > Compare Number('0xE'), Number('0XE'), Number('0xe') and Number('0Xe') with 14 ---*/ - -// CHECK#1 -if (Number("0xe") !== 14) { - throw new Test262Error('#1: Number("0xe") === 14. Actual: ' + (Number("0xe"))); -} - -// CHECK#2 -if (Number("0xE") !== 14) { - throw new Test262Error('#2: Number("0xE") === 14. Actual: ' + (Number("0xE"))); -} - -// CHECK#3 -if (Number("0Xe") !== 14) { - throw new Test262Error('#3: Number("0Xe") === 14. Actual: ' + (Number("0Xe"))); -} - -// CHECK#4 -if (+("0XE") !== 14) { - throw new Test262Error('#4: +("0XE") === 14. Actual: ' + (+("0XE"))); -} +assert.sameValue(Number("0xe"), 14, 'Number("0xe") must return 14'); +assert.sameValue(Number("0xE"), 14, 'Number("0xE") must return 14'); +assert.sameValue(Number("0Xe"), 14, 'Number("0Xe") must return 14'); +assert.sameValue(+("0XE"), 14, 'The value of `+("0XE")` is expected to be 14'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A31.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A31.js index 34b63fa0258d..7df3cba8f25d 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A31.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A31.js @@ -8,25 +8,9 @@ description: > Compare Number('0xF'), Number('0XF'), Number('0xf') and Number('0Xf') with 15 ---*/ - -// CHECK#1 -if (Number("0xf") !== 15) { - throw new Test262Error('#1: Number("0xf") === 15. Actual: ' + (Number("0xf"))); -} - -// CHECK#2 -if (Number("0xF") !== 15) { - throw new Test262Error('#2: Number("0xF") === 15. Actual: ' + (Number("0xF"))); -} - -// CHECK#3 -if (+("0Xf") !== 15) { - throw new Test262Error('#3: +("0Xf") === 15. Actual: ' + (+("0Xf"))); -} - -// CHECK#4 -if (Number("0XF") !== 15) { - throw new Test262Error('#4: Number("0XF") === 15. Actual: ' + (Number("0XF"))); -} +assert.sameValue(Number("0xf"), 15, 'Number("0xf") must return 15'); +assert.sameValue(Number("0xF"), 15, 'Number("0xF") must return 15'); +assert.sameValue(+("0Xf"), 15, 'The value of `+("0Xf")` is expected to be 15'); +assert.sameValue(Number("0XF"), 15, 'Number("0XF") must return 15'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A32.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A32.js index ffa3e60f5434..b0318e12cd1a 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A32.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A32.js @@ -10,30 +10,34 @@ info: | es5id: 9.3.1_A32 description: Use various long numbers, for example, 1234567890.1234567890 ---*/ +assert.sameValue( + Number("1234567890.1234567890"), + 1234567890.1234567890, + 'Number("1234567890.1234567890") must return 1234567890.1234567890' +); -// CHECK#1 -if (Number("1234567890.1234567890") !== 1234567890.1234567890) { - throw new Test262Error('#1: Number("1234567890.1234567890") === 1234567890.1234567890. Actual: ' + (Number("1234567890.1234567890"))); -} +assert.sameValue( + Number("1234567890.1234567890"), + 1234567890.1234567000, + 'Number("1234567890.1234567890") must return 1234567890.1234567000' +); -// CHECK#2 -if (Number("1234567890.1234567890") !== 1234567890.1234567000) { - throw new Test262Error('#2: Number("1234567890.1234567890") === 1234567890.1234567000. Actual: ' + (Number("1234567890.1234567890"))); -} +assert.notSameValue( + +("1234567890.1234567890"), + 1234567890.123456, + 'The value of +("1234567890.1234567890") is not 1234567890.123456' +); -// CHECK#3 -if (+("1234567890.1234567890") === 1234567890.123456) { - throw new Test262Error('#3: +("1234567890.1234567890") !== 1234567890.123456'); -} +assert.sameValue( + Number("0.12345678901234567890"), + 0.123456789012345678, + 'Number("0.12345678901234567890") must return 0.123456789012345678' +); -// CHECK#4 -if (Number("0.12345678901234567890") !== 0.123456789012345678) { - throw new Test262Error('#4: Number("0.12345678901234567890") === 0.123456789012345678. Actual: ' + (Number("0.12345678901234567890"))); -} - -// CHECK#4 -if (Number("00.12345678901234567890") !== 0.123456789012345678) { - throw new Test262Error('#4: Number("00.12345678901234567890") === 0.123456789012345678. Actual: ' + (Number("00.12345678901234567890"))); -} +assert.sameValue( + Number("00.12345678901234567890"), + 0.123456789012345678, + 'Number("00.12345678901234567890") must return 0.123456789012345678' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A3_T1.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A3_T1.js index d5dc0636401b..263c04c1861c 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A3_T1.js @@ -9,25 +9,24 @@ info: | es5id: 9.3.1_A3_T1 description: static string ---*/ +assert.sameValue( + Number("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000"), + 0 +); -// CHECK#1 -if (Number("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000") !== Number("")) { - throw new Test262Error('#1: Number("\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") === Number("")'); -} +assert.sameValue( + Number("\u0009\u000C\u0020\u00A0\u000A\u000D\u2028\u2029\u000B\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u30001234567890\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000"), + 1234567890 +); -// CHECK#2 -if (Number("\u0009\u000C\u0020\u00A0\u000A\u000D\u2028\u2029\u000B\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u30001234567890\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000") !== Number("1234567890")) { - throw new Test262Error('#2: Number("\\u0009\\u000C\\u0020\\u00A0\\u000A\\u000D\\u2028\\u2029\\u000B\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u30001234567890\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") === Number("1234567890")'); -} +assert.sameValue( + +("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000Infinity\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000"), + Infinity +); -// CHECK#3 -if (!(+("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000Infinity\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000") == Number("Infinity"))) { - throw new Test262Error('#3: +("\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000Infinity\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") == Number("Infinity")'); -} - -// CHECK#4 -if (!(Number("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000-Infinity\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000") == Number(-"Infinity"))) { - throw new Test262Error('#4: Number("\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000-Infinity\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") == Number("-Infinity")'); -} +assert.sameValue( + Number("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000-Infinity\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000"), + -Infinity +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A3_T2.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A3_T2.js index 77e1eaac74dc..96eb32fd0d2d 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A3_T2.js @@ -14,24 +14,24 @@ function dynaString(s1, s2) { return String(s1) + String(s2); } -// CHECK#1 -if (Number(dynaString("\u0009\u000C\u0020\u00A0\u000B", "\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000")) !== Number("")) { - throw new Test262Error('#1: Number("\\u0009\\u000C\\u0020\\u00A0\\u000B"+"\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") === Number("")'); -} +assert.sameValue( + Number(dynaString("\u0009\u000C\u0020\u00A0\u000B", "\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000")), + 0 +); -// CHECK#2 -if (+(dynaString("\u0009\u000C\u0020\u00A0\u000A\u000D\u2028\u2029\u000B12345", "67890\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000")) !== Number("1234567890")) { - throw new Test262Error('#2: +("\\u0009\\u000C\\u0020\\u00A0\\u000A\\u000D\\u2028\\u2029\\u000B12345"+"67890\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") === Number("1234567890")'); -} +assert.sameValue( + +(dynaString("\u0009\u000C\u0020\u00A0\u000A\u000D\u2028\u2029\u000B12345", "67890\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000")), + 1234567890 +); -// CHECK#3 -if (!(Number(dynaString("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029Infi", "nity\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000")) == Number("Infinity"))) { - throw new Test262Error('#3: Number("\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029Infi"+"nity\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") == Number("Infinity")'); -} +assert.sameValue( + Number(dynaString("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029Infi", "nity\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000")), + Infinity +); -// CHECK#4 -if (!(Number(dynaString("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029-Infi", "nity\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000")) == Number(-"Infinity"))) { - throw new Test262Error('#4: Number("\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029-Infi"+"nity\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000") == Number("-Infinity")'); -} +assert.sameValue( + Number(dynaString("\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029-Infi", "nity\u0009\u000C\u0020\u00A0\u000B\u000A\u000D\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000")), + -Infinity +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A4_T1.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A4_T1.js index 68dbd77147fc..193062e2cd25 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A4_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A4_T1.js @@ -8,45 +8,36 @@ info: | es5id: 9.3.1_A4_T1 description: Compare Number('+any_number') with Number('any_number') ---*/ +assert.sameValue(Number("+0"), Number("0"), 'Number("+0") must return the same value returned by Number("0")'); -// CHECK#1 -if (Number("+0") !== Number("0")) { - throw new Test262Error('#1.1: Number("+0") === Number("0")'); -} else { - // CHECK#2 - if (1 / Number("+0") !== 1 / Number("0")) { - throw new Test262Error('#2.2: 1/Number("+0") === 1/Number("0")'); - } -} +assert.sameValue( + Number("+Infinity"), + Infinity +); -// CHECK#3 -if (Number("+Infinity") !== Number("Infinity")) { - throw new Test262Error('#3: Number("+Infinity") === Number("Infinity")'); -} +assert.sameValue( + Number("+1234.5678"), + 1234.5678 +); -// CHECK#4 -if (Number("+1234.5678") !== Number("1234.5678")) { - throw new Test262Error('#4: Number("+1234.5678") === Number("1234.5678")'); -} +assert.sameValue( + Number("+1234.5678e90"), + 1234.5678e90 +); -// CHECK#5 -if (Number("+1234.5678e90") !== Number("1234.5678e90")) { - throw new Test262Error('#5: Number("+1234.5678e90") === Number("1234.5678e90")'); -} +assert.sameValue( + Number("+1234.5678E90"), + 1234.5678E90 +); -// CHECK#6 -if (Number("+1234.5678E90") !== Number("1234.5678E90")) { - throw new Test262Error('#6: Number("+1234.5678E90") === Number("1234.5678E90")'); -} +assert.sameValue( + Number("+1234.5678e-90"), + 1234.5678e-90 +); -// CHECK#7 -if (Number("+1234.5678e-90") !== Number("1234.5678e-90")) { - throw new Test262Error('#7: Number("+1234.5678e-90") === Number("1234.5678e-90")'); -} - -// CHECK#8 -if (Number("+1234.5678E-90") !== Number("1234.5678E-90")) { - throw new Test262Error('#8: Number("+1234.5678E-90") === Number("1234.5678E-90")'); -} +assert.sameValue( + Number("+1234.5678E-90"), + 1234.5678E-90 +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A4_T2.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A4_T2.js index b93a95428495..35e753fe19c3 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A4_T2.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A4_T2.js @@ -13,44 +13,39 @@ function dynaString(s1, s2) { return String(s1) + String(s2); } -// CHECK#1 -if (Number(dynaString("+", "0")) !== Number("0")) { - throw new Test262Error('#1: Number("+"+"0") === Number("0")'); -} else { - // CHECK#2 - if (1 / Number(dynaString("+", "0")) !== 1 / Number("0")) { - throw new Test262Error('#2: 1/Number("+"+"0") === 1/Number("0")'); - } -} +assert.sameValue( + Number(dynaString("+", "0")), + 0 +); -// CHECK#3 -if (Number(dynaString("+Infi", "nity")) !== Number("Infinity")) { - throw new Test262Error('#3: Number("+Infin"+"ity") === Number("Infinity")'); -} +assert.sameValue( + Number(dynaString("+Infi", "nity")), + Infinity +); -// CHECK#4 -if (Number(dynaString("+1234.", "5678")) !== Number("1234.5678")) { - throw new Test262Error('#4: Number("+1234."+"5678") === Number("1234.5678")'); -} +assert.sameValue( + Number(dynaString("+1234.", "5678")), + 1234.5678 +); -// CHECK#5 -if (Number(dynaString("+1234.", "5678e90")) !== Number("1234.5678e90")) { - throw new Test262Error('#5: Number("+1234."+"5678e90") === Number("1234.5678e90")'); -} +assert.sameValue( + Number(dynaString("+1234.", "5678e90")), + 1234.5678e90 +); -// CHECK#6 -if (Number(dynaString("+1234.", "5678E90")) !== Number("1234.5678E90")) { - throw new Test262Error('#6: Number("+1234."+"5678E90") === Number("1234.5678E90")'); -} +assert.sameValue( + Number(dynaString("+1234.", "5678E90")), + 1234.5678E90 +); -// CHECK#7 -if (Number(dynaString("+1234.", "5678e-90")) !== Number("1234.5678e-90")) { - throw new Test262Error('#7: Number("+1234."+"5678e-90") === Number("1234.5678e-90")'); -} +assert.sameValue( + Number(dynaString("+1234.", "5678e-90")), + 1234.5678e-90 +); -// CHECK#8 -if (Number(dynaString("+1234.", "5678E-90")) !== Number("1234.5678E-90")) { - throw new Test262Error('#8: Number("+1234."+"5678E-90") === Number("1234.5678E-90")'); -} +assert.sameValue( + Number(dynaString("+1234.", "5678E-90")), + 1234.5678E-90 +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T1.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T1.js index 0e1dc370d726..ffdeced45961 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T1.js @@ -8,55 +8,39 @@ info: | es5id: 9.3.1_A5_T1 description: Compare Number('-any_number') with -Number('any_number') ---*/ +assert.sameValue(Number("-0"), -0); +assert.sameValue(Number("-Infinity"), -Infinity); -// CHECK#1 -if (Number("-0") !== -Number("0")) { - throw new Test262Error('#1: Number("-0") === -Number("0")'); -} else { - // CHECK#2 - if (1 / Number("-0") !== -1 / Number("0")) { - throw new Test262Error('#2: 1/Number("-0") === -1/Number("0")'); - } -} +assert.sameValue( + Number("-1234567890"), + -1234567890 +); -// CHECK#3 -if (Number("-Infinity") !== -Number("Infinity")) { - throw new Test262Error('#3: Number("-Infinity") === -Number("Infinity")'); -} +assert.sameValue(Number("-1234.5678"), -1234.5678); -// CHECK#4 -if (Number("-1234567890") !== -Number("1234567890")) { - throw new Test262Error('#4: Number("-1234567890") === -Number("1234567890")'); -} +assert.sameValue( + Number("-1234.5678e90"), + -1234.5678e90 +); -// CHECK#5 -if (Number("-1234.5678") !== -Number("1234.5678")) { - throw new Test262Error('#5: Number("-1234.5678") === -Number("1234.5678")'); -} +assert.sameValue( + Number("-1234.5678E90"), + -1234.5678E90 +); -// CHECK#6 -if (Number("-1234.5678e90") !== -Number("1234.5678e90")) { - throw new Test262Error('#6: Number("-1234.5678e90") === -Number("1234.5678e90")'); -} +assert.sameValue( + Number("-1234.5678e-90"), + -1234.5678e-90 +); -// CHECK#7 -if (Number("-1234.5678E90") !== -Number("1234.5678E90")) { - throw new Test262Error('#6: Number("-1234.5678E90") === -Number("1234.5678E90")'); -} +assert.sameValue( + Number("-1234.5678E-90"), + -1234.5678E-90 +); -// CHECK#8 -if (Number("-1234.5678e-90") !== -Number("1234.5678e-90")) { - throw new Test262Error('#6: Number("-1234.5678e-90") === -Number("1234.5678e-90")'); -} - -// CHECK#9 -if (Number("-1234.5678E-90") !== -Number("1234.5678E-90")) { - throw new Test262Error('#6: Number("-1234.5678E-90") === -Number("1234.5678E-90")'); -} - -// CHECK#10 -if (Number("-Infinity") !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#3: Number("-Infinity") === Number.NEGATIVE_INFINITY'); -} +assert.sameValue( + Number("-Infinity"), + Number.NEGATIVE_INFINITY +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T2.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T2.js index 93ac9bf285c6..4aa454f6c133 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T2.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T2.js @@ -8,140 +8,32 @@ info: | es5id: 9.3.1_A5_T2 description: Compare Number('-[or +]any_number') with -[or without -]any_number) ---*/ - -// CHECK#1 -if (Number("1") !== 1) { - throw new Test262Error('#1: Number("1") === 1'); -} - -// CHECK#2 -if (Number("+1") !== 1) { - throw new Test262Error('#3: Number("+1") === 1'); -} - -// CHECK#3 -if (Number("-1") !== -1) { - throw new Test262Error('#3: Number("-1") === -1'); -} - -// CHECK#4 -if (Number("2") !== 2) { - throw new Test262Error('#4: Number("2") === 2'); -} - -// CHECK#5 -if (Number("+2") !== 2) { - throw new Test262Error('#5: Number("+2") === 2'); -} - -// CHECK#6 -if (Number("-2") !== -2) { - throw new Test262Error('#6: Number("-2") === -2'); -} - -// CHECK#7 -if (Number("3") !== 3) { - throw new Test262Error('#7: Number("3") === 3'); -} - -// CHECK#8 -if (Number("+3") !== 3) { - throw new Test262Error('#8: Number("+3") === 3'); -} - -// CHECK#9 -if (Number("-3") !== -3) { - throw new Test262Error('#9: Number("-3") === -3'); -} - -// CHECK#10 -if (Number("4") !== 4) { - throw new Test262Error('#10: Number("4") === 4'); -} - -// CHECK#11 -if (Number("+4") !== 4) { - throw new Test262Error('#11: Number("+4") === 4'); -} - -// CHECK#12 -if (Number("-4") !== -4) { - throw new Test262Error('#12: Number("-4") === -4'); -} - -// CHECK#13 -if (Number("5") !== 5) { - throw new Test262Error('#13: Number("5") === 5'); -} - -// CHECK#14 -if (Number("+5") !== 5) { - throw new Test262Error('#14: Number("+5") === 5'); -} - -// CHECK#15 -if (Number("-5") !== -5) { - throw new Test262Error('#15: Number("-5") === -5'); -} - -// CHECK#16 -if (Number("6") !== 6) { - throw new Test262Error('#16: Number("6") === 6'); -} - -// CHECK#17 -if (Number("+6") !== 6) { - throw new Test262Error('#17: Number("+6") === 6'); -} - -// CHECK#18 -if (Number("-6") !== -6) { - throw new Test262Error('#18: Number("-6") === -6'); -} - -// CHECK#19 -if (Number("7") !== 7) { - throw new Test262Error('#19: Number("7") === 7'); -} - -// CHECK#20 -if (Number("+7") !== 7) { - throw new Test262Error('#20: Number("+7") === 7'); -} - -// CHECK#21 -if (Number("-7") !== -7) { - throw new Test262Error('#21: Number("-7") === -7'); -} - -// CHECK#22 -if (Number("8") !== 8) { - throw new Test262Error('#22: Number("8") === 8'); -} - -// CHECK#23 -if (Number("+8") !== 8) { - throw new Test262Error('#23: Number("+8") === 8'); -} - -// CHECK#24 -if (Number("-8") !== -8) { - throw new Test262Error('#24: Number("-8") === -8'); -} - -// CHECK#25 -if (Number("9") !== 9) { - throw new Test262Error('#25: Number("9") === 9'); -} - -// CHECK#26 -if (Number("+9") !== 9) { - throw new Test262Error('#26: Number("+9") === 9'); -} - -// CHECK#27 -if (Number("-9") !== -9) { - throw new Test262Error('#27: Number("-9") === -9'); -} +assert.sameValue(Number("1"), 1, 'Number("1") must return 1'); +assert.sameValue(Number("+1"), 1, 'Number("+1") must return 1'); +assert.sameValue(Number("-1"), -1, 'Number("-1") must return -1'); +assert.sameValue(Number("2"), 2, 'Number("2") must return 2'); +assert.sameValue(Number("+2"), 2, 'Number("+2") must return 2'); +assert.sameValue(Number("-2"), -2, 'Number("-2") must return -2'); +assert.sameValue(Number("3"), 3, 'Number("3") must return 3'); +assert.sameValue(Number("+3"), 3, 'Number("+3") must return 3'); +assert.sameValue(Number("-3"), -3, 'Number("-3") must return -3'); +assert.sameValue(Number("4"), 4, 'Number("4") must return 4'); +assert.sameValue(Number("+4"), 4, 'Number("+4") must return 4'); +assert.sameValue(Number("-4"), -4, 'Number("-4") must return -4'); +assert.sameValue(Number("5"), 5, 'Number("5") must return 5'); +assert.sameValue(Number("+5"), 5, 'Number("+5") must return 5'); +assert.sameValue(Number("-5"), -5, 'Number("-5") must return -5'); +assert.sameValue(Number("6"), 6, 'Number("6") must return 6'); +assert.sameValue(Number("+6"), 6, 'Number("+6") must return 6'); +assert.sameValue(Number("-6"), -6, 'Number("-6") must return -6'); +assert.sameValue(Number("7"), 7, 'Number("7") must return 7'); +assert.sameValue(Number("+7"), 7, 'Number("+7") must return 7'); +assert.sameValue(Number("-7"), -7, 'Number("-7") must return -7'); +assert.sameValue(Number("8"), 8, 'Number("8") must return 8'); +assert.sameValue(Number("+8"), 8, 'Number("+8") must return 8'); +assert.sameValue(Number("-8"), -8, 'Number("-8") must return -8'); +assert.sameValue(Number("9"), 9, 'Number("9") must return 9'); +assert.sameValue(Number("+9"), 9, 'Number("+9") must return 9'); +assert.sameValue(Number("-9"), -9, 'Number("-9") must return -9'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T3.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T3.js index 43c9cb2b8302..a1f4896faf62 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T3.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A5_T3.js @@ -13,54 +13,46 @@ function dynaString(s1, s2) { return String(s1) + String(s2); } -// CHECK#1 -if (Number(dynaString("-", "0")) !== -Number("0")) { - throw new Test262Error('#1: Number("-"+"0") === -Number("0")'); -} else { - // CHECK#2 - if (1 / Number(dynaString("-", "0")) !== -1 / Number("0")) { - throw new Test262Error('#2: 1/Number("-"+"0") === -1/Number("0")'); - } -} +assert.sameValue(Number(dynaString("-", "0")), -0, 'Number(dynaString("-", "0")) must return -Number("0")'); -// CHECK#3 -if (Number(dynaString("-Infi", "nity")) !== -Number("Infinity")) { - throw new Test262Error('#3: Number("-Infi"+"nity") === -Number("Infinity")'); -} +assert.sameValue( + Number(dynaString("-Infi", "nity")), + -Infinity +); -// CHECK#4 -if (Number(dynaString("-12345", "67890")) !== -Number("1234567890")) { - throw new Test262Error('#4: Number("-12345"+"67890") === -Number("1234567890")'); -} +assert.sameValue( + Number(dynaString("-12345", "67890")), + -1234567890 +); -// CHECK#5 -if (Number(dynaString("-1234.", "5678")) !== -Number("1234.5678")) { - throw new Test262Error('#5: Number("-1234."+"5678") === -Number("1234.5678")'); -} +assert.sameValue( + Number(dynaString("-1234.", "5678")), + -1234.5678 +); -// CHECK#6 -if (Number(dynaString("-1234.", "5678e90")) !== -Number("1234.5678e90")) { - throw new Test262Error('#6: Number("-1234."+"5678e90") === -Number("1234.5678e90")'); -} +assert.sameValue( + Number(dynaString("-1234.", "5678e90")), + -1234.5678e90 +); -// CHECK#7 -if (Number(dynaString("-1234.", "5678E90")) !== -Number("1234.5678E90")) { - throw new Test262Error('#6: Number("-1234."+"5678E90") === -Number("1234.5678E90")'); -} +assert.sameValue( + Number(dynaString("-1234.", "5678E90")), + -1234.5678E90 +); -// CHECK#8 -if (Number(dynaString("-1234.", "5678e-90")) !== -Number("1234.5678e-90")) { - throw new Test262Error('#6: Number("-1234."+"5678e-90") === -Number("1234.5678e-90")'); -} +assert.sameValue( + Number(dynaString("-1234.", "5678e-90")), + -1234.5678e-90 +); -// CHECK#9 -if (Number(dynaString("-1234.", "5678E-90")) !== -Number("1234.5678E-90")) { - throw new Test262Error('#6: Number("-1234."+"5678E-90") === -Number("1234.5678E-90")'); -} +assert.sameValue( + Number(dynaString("-1234.", "5678E-90")), + -1234.5678E-90 +); -// CHECK#10 -if (Number(dynaString("-Infi", "nity")) !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#3: Number("-Infi"+"nity") === Number.NEGATIVE_INFINITY'); -} +assert.sameValue( + Number(dynaString("-Infi", "nity")), + Number.NEGATIVE_INFINITY +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A6_T1.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A6_T1.js index 0384d92782f7..d82b6b027f73 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A6_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A6_T1.js @@ -10,25 +10,14 @@ description: > Compare Number('Infinity') with Number.POSITIVE_INFINITY, 10e10000, 10E10000 and Number("10e10000") ---*/ +assert.sameValue(Number("Infinity"), Number.POSITIVE_INFINITY, 'Number("Infinity") returns Number.POSITIVE_INFINITY'); +assert.sameValue(Number("Infinity"), 10e10000, 'Number("Infinity") must return 10e10000'); +assert.sameValue(Number("Infinity"), 10E10000, 'Number("Infinity") must return 10E10000'); -// CHECK#1 -if (Number("Infinity") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#1: Number("Infinity") === Number.POSITIVE_INFINITY'); -} - -// CHECK#2 -if (Number("Infinity") !== 10e10000) { - throw new Test262Error('#2: Number("Infinity") === 10e10000'); -} - -// CHECK#3 -if (Number("Infinity") !== 10E10000) { - throw new Test262Error('#3: Number("Infinity") === 10E10000'); -} - -// CHECK#4 -if (Number("Infinity") !== Number("10e10000")) { - throw new Test262Error('#4: Number("Infinity") === Number("10e10000")'); -} +assert.sameValue( + Number("Infinity"), + 10e10000, + 'Number("Infinity") must return the same value returned by Number("10e10000")' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A6_T2.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A6_T2.js index 0dbee6c00ece..68c3bf1dd09b 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A6_T2.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A6_T2.js @@ -16,24 +16,28 @@ function dynaString(s1, s2) { } -// CHECK#1 -if (Number(dynaString("Infi", "nity")) !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#1: Number("Infi"+"nity") === Number.POSITIVE_INFINITY'); -} +assert.sameValue( + Number(dynaString("Infi", "nity")), + Number.POSITIVE_INFINITY, + 'Number(dynaString("Infi", "nity")) returns Number.POSITIVE_INFINITY' +); -// CHECK#2 -if (Number(dynaString("Infi", "nity")) !== 10e10000) { - throw new Test262Error('#2: Number("Infi"+"nity") === 10e10000'); -} +assert.sameValue( + Number(dynaString("Infi", "nity")), + 10e10000, + 'Number(dynaString("Infi", "nity")) must return 10e10000' +); -// CHECK#3 -if (Number(dynaString("Infi", "nity")) !== 10E10000) { - throw new Test262Error('#3: Number("Infi"+"nity") === 10E10000'); -} +assert.sameValue( + Number(dynaString("Infi", "nity")), + 10E10000, + 'Number(dynaString("Infi", "nity")) must return 10E10000' +); -// CHECK#4 -if (Number(dynaString("Infi", "nity")) !== Number("10e10000")) { - throw new Test262Error('#4: Number("Infi"+"nity") === Number("10e10000")'); -} +assert.sameValue( + Number(dynaString("Infi", "nity")), + Number("10e10000"), + 'Number(dynaString("Infi", "nity")) must return the same value returned by Number("10e10000")' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A7.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A7.js index 507a21f2ee8f..84428ab914fc 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A7.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A7.js @@ -9,10 +9,10 @@ info: | es5id: 9.3.1_A7 description: Compare Number('1234.5678') with Number('1234')+(+('5678')*1e-4) ---*/ - -// CHECK#1 -if (Number("1234.5678") !== Number("1234") + (+("5678") * 1e-4)) { - throw new Test262Error('#1: Number("1234.5678") === Number("1234")+(+("5678")*1e-4)'); -} +assert.sameValue( + Number("1234.5678"), + 1234.5678, + 'Number("1234.5678") must return Number("1234") + (+("5678") * 1e-4)' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A8.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A8.js index e6945d73f317..f4b6b2dcae33 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A8.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A8.js @@ -10,15 +10,7 @@ description: > Compare Number('1234e5') and Number('1234.e5') with Number('1234')*1e5 ---*/ - -// CHECK#1 -if (Number("1234e5") !== Number("1234") * 1e5) { - throw new Test262Error('#1: Number("1234e5") === Number("1234")*1e5'); -} - -// CHECK#2 -if (Number("1234.e5") !== +("1234") * 1e5) { - throw new Test262Error('#2: Number("1234.e5") === +("1234")*1e5'); -} +assert.sameValue(Number("1234e5"), 123400000, 'Number("1234e5") must return 123400000'); +assert.sameValue(Number("1234.e5"), 123400000, 'Number("1234.e5") must return 123400000'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3.1_A9.js b/js/src/tests/test262/built-ins/Number/S9.3.1_A9.js index de05e69eb218..da31d060334e 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3.1_A9.js +++ b/js/src/tests/test262/built-ins/Number/S9.3.1_A9.js @@ -13,15 +13,16 @@ description: > (Number('1234')+(Number('5678')*1e-4))*1e9, and +('1234.5678e-9') with (Number('1234')+(Number('5678')*1e-4))*1e-9 ---*/ +assert.sameValue( + (Number("1234") + (Number("5678") * 1e-4)) * 1e9, + 1234.5678e9, + 'Number("1234.5678e9") must return (Number("1234") + (Number("5678") * 1e-4)) * 1e9' +); -// CHECK#1 -if (Number("1234.5678e9") !== (Number("1234") + (Number("5678") * 1e-4)) * 1e9) { - throw new Test262Error('#1: Number("1234.5678e9") === (Number("1234")+(Number("5678")*1e-4))*1e9'); -} - -// CHECK#2 -if (+("1234.5678e-9") !== (Number("1234") + (Number("5678") * 1e-4)) * 1e-9) { - throw new Test262Error('#2: +("1234.5678e-9") === (Number("1234")+(Number("5678")*1e-4))*1e-9'); -} +assert.sameValue( + (Number("1234") + (Number("5678") * 1e-4)) * 1e-9, + 1234.5678e-9, + 'The value of `+("1234.5678e-9")` is expected to be (Number("1234") + (Number("5678") * 1e-4)) * 1e-9' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3_A2_T1.js b/js/src/tests/test262/built-ins/Number/S9.3_A2_T1.js index 245407461791..c8617f836d57 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3_A2_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3_A2_T1.js @@ -6,14 +6,6 @@ info: Result of number conversion from null value is +0 es5id: 9.3_A2_T1 description: null convert to Number by explicit transformation ---*/ - -// CHECK #1 -if (Number(null) !== 0) { - throw new Test262Error('#1.1: Number(null) === 0. Actual: ' + (Number(null))); -} else { - if (1 / Number(null) !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#1.2: Number(null) === +0. Actual: -0'); - } -} +assert.sameValue(Number(null), 0, 'Number(null) must return 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3_A3_T1.js b/js/src/tests/test262/built-ins/Number/S9.3_A3_T1.js index b68dff82331c..0debe6b2d738 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3_A3_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3_A3_T1.js @@ -8,19 +8,7 @@ info: | es5id: 9.3_A3_T1 description: False and true convert to Number by explicit transformation ---*/ - -// CHECK#1 -if (Number(false) !== +0) { - throw new Test262Error('#1.1: Number(false) === 0. Actual: ' + (Number(false))); -} else { - if (1 / Number(false) !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#1.2: Number(false) === +0. Actual: -0'); - } -} - -// CHECK#2 -if (Number(true) !== 1) { - throw new Test262Error('#2: Number(true) === 1. Actual: ' + (Number(true))); -} +assert.sameValue(Number(false), +0, 'Number(false) must return +0'); +assert.sameValue(Number(true), 1, 'Number(true) must return 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3_A4.1_T1.js b/js/src/tests/test262/built-ins/Number/S9.3_A4.1_T1.js index 9fe9b4697809..38479ba1828b 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3_A4.1_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3_A4.1_T1.js @@ -10,25 +10,9 @@ description: > Some numbers including Number.MAX_VALUE and Number.MIN_VALUE are converted to Number with explicit transformation ---*/ - -// CHECK#1 -if (Number(13) !== 13) { - throw new Test262Error('#1: Number(13) === 13. Actual: ' + (Number(13))); -} - -// CHECK#2 -if (Number(-13) !== -13) { - throw new Test262Error('#2: Number(-13) === -13. Actual: ' + (Number(-13))); -} - -// CHECK#3 -if (Number(1.3) !== 1.3) { - throw new Test262Error('#3: Number(1.3) === 1.3. Actual: ' + (Number(1.3))); -} - -// CHECK#4 -if (Number(-1.3) !== -1.3) { - throw new Test262Error('#4: Number(-1.3) === -1.3. Actual: ' + (Number(-1.3))); -} +assert.sameValue(Number(13), 13, 'Number(13) must return 13'); +assert.sameValue(Number(-13), -13, 'Number(-13) must return -13'); +assert.sameValue(Number(1.3), 1.3, 'Number(1.3) must return 1.3'); +assert.sameValue(Number(-1.3), -1.3, 'Number(-1.3) must return -1.3'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3_A4.2_T1.js b/js/src/tests/test262/built-ins/Number/S9.3_A4.2_T1.js index e44404c857fa..fcd7b5520341 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3_A4.2_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3_A4.2_T1.js @@ -13,44 +13,24 @@ description: > ---*/ // CHECK#1 -assert.sameValue(Number(NaN), NaN, "NaN"); +assert.sameValue(Number(NaN), NaN, 'Number(true) returns NaN'); -// CHECK#2 -if (Number(+0) !== +0) { - throw new Test262Error('#2.1: Number(+0) === 0. Actual: ' + (Number(+0))); -} else { - if (1 / Number(+0) !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#2.2: Number(+0) === +0. Actual: -0'); - } -} +assert.sameValue(Number(+0), +0, 'Number(+0) must return +0'); +assert.sameValue(Number(-0), -0, 'Number(-0) must return -0'); -// CHECK#3 -if (Number(-0) !== -0) { - throw new Test262Error('#3.1: Number(-0) === 0. Actual: ' + (Number(-0))); -} else { - if (1 / Number(-0) !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#3.2: Number(-0) === -0. Actual: +0'); - } -} +assert.sameValue( + Number(Number.POSITIVE_INFINITY), + Number.POSITIVE_INFINITY, + 'Number(Number.POSITIVE_INFINITY) returns Number.POSITIVE_INFINITY' +); -// CHECK#4 -if (Number(Number.POSITIVE_INFINITY) !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#4: Number(+Infinity) === +Infinity. Actual: ' + (Number(+Infinity))); -} +assert.sameValue( + Number(Number.NEGATIVE_INFINITY), + Number.NEGATIVE_INFINITY, + 'Number(Number.NEGATIVE_INFINITY) returns Number.NEGATIVE_INFINITY' +); -// CHECK#5 -if (Number(Number.NEGATIVE_INFINITY) !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#5: Number(-Infinity) === -Infinity. Actual: ' + (Number(-Infinity))); -} - -// CHECK#6 -if (Number(Number.MAX_VALUE) !== Number.MAX_VALUE) { - throw new Test262Error('#6: Number(Number.MAX_VALUE) === Number.MAX_VALUE. Actual: ' + (Number(Number.MAX_VALUE))); -} - -// CHECK#7 -if (Number(Number.MIN_VALUE) !== Number.MIN_VALUE) { - throw new Test262Error('#7: Number(Number.MIN_VALUE) === Number.MIN_VALUE. Actual: ' + (Number(Number.MIN_VALUE))); -} +assert.sameValue(Number(Number.MAX_VALUE), Number.MAX_VALUE, 'Number(Number.MAX_VALUE) returns Number.MAX_VALUE'); +assert.sameValue(Number(Number.MIN_VALUE), Number.MIN_VALUE, 'Number(Number.MIN_VALUE) returns Number.MIN_VALUE'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/S9.3_A5_T1.js b/js/src/tests/test262/built-ins/Number/S9.3_A5_T1.js index 8a6dc4b45fcc..c9f8dc311c5a 100644 --- a/js/src/tests/test262/built-ins/Number/S9.3_A5_T1.js +++ b/js/src/tests/test262/built-ins/Number/S9.3_A5_T1.js @@ -11,62 +11,24 @@ description: > Number(null), new Number(void 0) and others convert to Number by explicit transformation ---*/ - -// CHECK#1 -if (Number(new Number()) !== 0) { - throw new Test262Error('#1: Number(new Number()) === 0. Actual: ' + (Number(new Number()))); -} - -// CHECK#2 -if (Number(new Number(0)) !== 0) { - throw new Test262Error('#2: Number(new Number(0)) === 0. Actual: ' + (Number(new Number(0)))); -} +assert.sameValue(Number(new Number()), 0, 'Number(new Number()) must return 0'); +assert.sameValue(Number(new Number(0)), 0, 'Number(new Number(0)) must return 0'); // CHECK#3 -assert.sameValue(Number(new Number(NaN)), NaN, "Number(new Number(NaN)"); +assert.sameValue(Number(new Number(NaN)), NaN, 'Number(new Number(NaN)) returns NaN'); -// CHECK#4 -if (Number(new Number(null)) !== 0) { - throw new Test262Error('#4.1: Number(new Number(null)) === 0. Actual: ' + (Number(new Number(null)))); -} else { - if (1 / Number(new Number(null)) !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#4.2: Number(new Number(null)) === +0. Actual: -0'); - } -} +assert.sameValue(Number(new Number(null)), 0, 'Number(new Number(null)) must return 0'); // CHECK#5 -assert.sameValue(Number(new Number(void 0)), NaN, "Number(new Number(void 0)"); +assert.sameValue(Number(new Number(void 0)), NaN, 'Number(new Number(void 0)) returns NaN'); -// CHECK#6 -if (Number(new Number(true)) !== 1) { - throw new Test262Error('#6: Number(new Number(true)) === 1. Actual: ' + (Number(new Number(true)))); -} - -// CHECK#7 -if (Number(new Number(false)) !== +0) { - throw new Test262Error('#7.1: Number(new Number(false)) === 0. Actual: ' + (Number(new Number(false)))); -} else { - if (1 / Number(new Number(false)) !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#7.2: Number(new Number(false)) === +0. Actual: -0'); - } -} - -// CHECK#8 -if (Number(new Boolean(true)) !== 1) { - throw new Test262Error('#8: Number(new Boolean(true)) === 1. Actual: ' + (Number(new Boolean(true)))); -} - -// CHECK#9 -if (Number(new Boolean(false)) !== +0) { - throw new Test262Error('#9.1: Number(new Boolean(false)) === 0. Actual: ' + (Number(new Boolean(false)))); -} else { - if (1 / Number(new Boolean(false)) !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#9.2: Number(new Boolean(false)) === +0. Actual: -0'); - } -} +assert.sameValue(Number(new Number(true)), 1, 'Number(new Number(true)) must return 1'); +assert.sameValue(Number(new Number(false)), +0, 'Number(new Number(false)) must return +0'); +assert.sameValue(Number(new Boolean(true)), 1, 'Number(new Boolean(true)) must return 1'); +assert.sameValue(Number(new Boolean(false)), +0, 'Number(new Boolean(false)) must return +0'); // CHECK#10 -assert.sameValue(Number(new Array(2, 4, 8, 16, 32)), NaN, "Number(new Array(2,4,8,16,32))"); +assert.sameValue(Number(new Array(2, 4, 8, 16, 32)), NaN, 'Number(new Array(2, 4, 8, 16, 32)) returns NaN'); // CHECK#11 var myobj1 = { @@ -81,7 +43,7 @@ var myobj1 = { } }; -assert.sameValue(Number(myobj1), NaN, "Number(myobj1)"); +assert.sameValue(Number(myobj1), NaN, 'Number("{ToNumber: function() {return 12345;}, toString: function() {return "67890";}, valueOf: function() {return "[object MyObj]";}}) returns NaN'); // CHECK#12 var myobj2 = { @@ -96,9 +58,11 @@ var myobj2 = { } }; -if (Number(myobj2) !== 9876543210) { - throw new Test262Error("#12: Number(myobj2) calls ToPrimitive with hint Number. Exptected: 9876543210. Actual: " + (Number(myobj2))); -} +assert.sameValue( + Number(myobj2), + 9876543210, + 'Number("{ToNumber: function() {return 12345;}, toString: function() {return "67890";}, valueOf: function() {return "9876543210";}}) must return 9876543210' +); // CHECK#13 @@ -111,7 +75,7 @@ var myobj3 = { } }; -assert.sameValue(Number(myobj3), NaN, "Number(myobj3)"); +assert.sameValue(Number(myobj3), NaN, 'Number("{ToNumber: function() {return 12345;}, toString: function() {return "[object MyObj]";}}) returns NaN'); // CHECK#14 var myobj4 = { @@ -123,9 +87,11 @@ var myobj4 = { } }; -if (Number(myobj4) !== 67890) { - throw new Test262Error("#14: Number(myobj4) calls ToPrimitive with hint Number. Exptected: 67890. Actual: " + (Number(myobj4))); -} +assert.sameValue( + Number(myobj4), + 67890, + 'Number("{ToNumber: function() {return 12345;}, toString: function() {return "67890";}}) must return 67890' +); // CHECK#15 var myobj5 = { @@ -134,6 +100,6 @@ var myobj5 = { } }; -assert.sameValue(Number(myobj5), NaN, "Number(myobj5)"); +assert.sameValue(Number(myobj5), NaN, 'Number({ToNumber: function() {return 12345;}}) returns NaN'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A2_T1.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A2_T1.js index 1b36fc7e6e2e..9ce9c44993c8 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A2_T1.js @@ -8,16 +8,18 @@ description: > Checking type of Number.prototype property - test based on deleting Number.prototype.toString ---*/ - -//CHECK#1 -if (typeof Number.prototype !== "object") { - throw new Test262Error('#1: typeof Number.prototype === "object"'); -} +assert.sameValue( + typeof Number.prototype, + "object", + 'The value of `typeof Number.prototype` is expected to be "object"' +); delete Number.prototype.toString; -if (Number.prototype.toString() !== "[object Number]") { - throw new Test262Error('#3: The [[Class]] property of the Number prototype object is set to "Number"'); -} +assert.sameValue( + Number.prototype.toString(), + "[object Number]", + 'Number.prototype.toString() must return "[object Number]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A2_T2.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A2_T2.js index 05d7f346540a..5a866328c6f0 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A2_T2.js @@ -8,16 +8,18 @@ description: > Checking type of Number.prototype property - test based on overwriting of Number.prototype.toString ---*/ - -//CHECK#1 -if (typeof Number.prototype !== "object") { - throw new Test262Error('#1: typeof Number.prototype === "object"'); -} +assert.sameValue( + typeof Number.prototype, + "object", + 'The value of `typeof Number.prototype` is expected to be "object"' +); Number.prototype.toString = Object.prototype.toString; -if (Number.prototype.toString() !== "[object Number]") { - throw new Test262Error('#3: The [[Class]] property of the Number prototype object is set to "Number"'); -} +assert.sameValue( + Number.prototype.toString(), + "[object Number]", + 'Number.prototype.toString() must return "[object Number]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A3.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A3.js index 4075b04bf5e4..27619d998361 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A3.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.3.1_A3.js @@ -6,12 +6,6 @@ info: Number.prototype value is +0 es5id: 15.7.3.1_A3 description: Checking value of Number.prototype property ---*/ - -//CHECK#1 -if (Number.prototype != 0) { - throw new Test262Error('#2: Number.prototype == +0'); -} else if (1 / Number.prototype != Number.POSITIVE_INFINITY) { - throw new Test262Error('#2: Number.prototype == +0'); -} +assert(Number.prototype == 0, 'The value of Number.prototype is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A1.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A1.js index c1ec79c7ac6c..f7454823712d 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A1.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A1.js @@ -8,23 +8,20 @@ info: | es5id: 15.7.4_A1 description: Checking type and value of Number.prototype property ---*/ +assert.sameValue( + typeof Number.prototype, + "object", + 'The value of `typeof Number.prototype` is expected to be "object"' +); -//CHECK#1 -if (typeof Number.prototype !== "object") { - throw new Test262Error('#1: typeof Number.prototype === "object"'); -} - -//CHECK#2 -if (Number.prototype != 0) { - throw new Test262Error('#2: Number.prototype == +0'); -} else if (1 / Number.prototype != Number.POSITIVE_INFINITY) { - throw new Test262Error('#2: Number.prototype == +0'); -} +assert(Number.prototype == 0, 'The value of Number.prototype is expected to be 0'); delete Number.prototype.toString; -if (Number.prototype.toString() !== "[object Number]") { - throw new Test262Error('#3: The [[Class]] property of the Number prototype object is set to "Number"'); -} +assert.sameValue( + Number.prototype.toString(), + "[object Number]", + 'Number.prototype.toString() must return "[object Number]"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A2.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A2.js index e38fc7ee82be..f0636b0f949a 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A2.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A2.js @@ -8,10 +8,9 @@ info: | es5id: 15.7.4_A2 description: Checking Object.prototype.isPrototypeOf(Number.prototype) ---*/ - -//CHECK#1 -if (!Object.prototype.isPrototypeOf(Number.prototype)) { - throw new Test262Error('#1: Object prototype object is the prototype of Number prototype object'); -} +assert( + Object.prototype.isPrototypeOf(Number.prototype), + 'Object.prototype.isPrototypeOf(Number.prototype) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.1.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.1.js index ea2587c0516f..40104551bd84 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.1.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.1.js @@ -6,10 +6,10 @@ info: The Number prototype object has the property constructor es5id: 15.7.4_A3.1 description: The test uses hasOwnProperty() method ---*/ - -//CHECK#1 -if (Number.prototype.hasOwnProperty("constructor") !== true) { - throw new Test262Error('#1: The Number prototype object has the property constructor'); -} +assert.sameValue( + Number.prototype.hasOwnProperty("constructor"), + true, + 'Number.prototype.hasOwnProperty("constructor") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.2.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.2.js index c96a998a7e83..df9d69b88b4e 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.2.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.2.js @@ -6,10 +6,10 @@ info: The Number prototype object has the property toString es5id: 15.7.4_A3.2 description: The test uses hasOwnProperty() method ---*/ - -//CHECK#1 -if (Number.prototype.hasOwnProperty("toString") !== true) { - throw new Test262Error('#1: The Number prototype object has the property toString'); -} +assert.sameValue( + Number.prototype.hasOwnProperty("toString"), + true, + 'Number.prototype.hasOwnProperty("toString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.3.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.3.js index b2f4be16fc35..3df204dac0f5 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.3.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.3.js @@ -6,10 +6,10 @@ info: The Number prototype object has the property toLocaleString es5id: 15.7.4_A3.3 description: The test uses hasOwnProperty() method ---*/ - -//CHECK#1 -if (Number.prototype.hasOwnProperty("toLocaleString") !== true) { - throw new Test262Error('#1: The Number prototype object has the property toLocaleString'); -} +assert.sameValue( + Number.prototype.hasOwnProperty("toLocaleString"), + true, + 'Number.prototype.hasOwnProperty("toLocaleString") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.4.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.4.js index 7de34402307e..68b4e1b3182b 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.4.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.4.js @@ -6,10 +6,10 @@ info: The Number prototype object has the property valueOf es5id: 15.7.4_A3.4 description: The test uses hasOwnProperty() method ---*/ - -//CHECK#1 -if (Number.prototype.hasOwnProperty("valueOf") !== true) { - throw new Test262Error('#1: The Number prototype object has the property valueOf'); -} +assert.sameValue( + Number.prototype.hasOwnProperty("valueOf"), + true, + 'Number.prototype.hasOwnProperty("valueOf") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.5.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.5.js index b2dee43f495d..06331dba9599 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.5.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.5.js @@ -6,10 +6,10 @@ info: The Number prototype object has the property toFixed es5id: 15.7.4_A3.5 description: The test uses hasOwnProperty() method ---*/ - -//CHECK#1 -if (Number.prototype.hasOwnProperty("toFixed") !== true) { - throw new Test262Error('#1: The Number prototype object has the property toFixed'); -} +assert.sameValue( + Number.prototype.hasOwnProperty("toFixed"), + true, + 'Number.prototype.hasOwnProperty("toFixed") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.6.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.6.js index a2ad4e732e66..ae91098e19ff 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.6.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.6.js @@ -6,10 +6,10 @@ info: The Number prototype object has the property toExponential es5id: 15.7.4_A3.6 description: The test uses hasOwnProperty() method ---*/ - -//CHECK#1 -if (Number.prototype.hasOwnProperty("toExponential") !== true) { - throw new Test262Error('#1: The Number prototype object has the property toExponential'); -} +assert.sameValue( + Number.prototype.hasOwnProperty("toExponential"), + true, + 'Number.prototype.hasOwnProperty("toExponential") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.7.js b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.7.js index 3846e58cf119..31dbd09de357 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.7.js +++ b/js/src/tests/test262/built-ins/Number/prototype/S15.7.4_A3.7.js @@ -6,10 +6,10 @@ info: The Number prototype object has the property toPrecision es5id: 15.7.4_A3.7 description: The test uses hasOwnProperty() method ---*/ - -//CHECK#1 -if (Number.prototype.hasOwnProperty("toPrecision") !== true) { - throw new Test262Error('#1: The Number prototype object has the property toPrecision'); -} +assert.sameValue( + Number.prototype.hasOwnProperty("toPrecision"), + true, + 'Number.prototype.hasOwnProperty("toPrecision") must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T01.js b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T01.js index 58afe70bca44..153d63b923a4 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T01.js @@ -8,63 +8,24 @@ info: | es5id: 15.7.4.5_A1.1_T01 description: calling on Number prototype object ---*/ +assert.sameValue(Number.prototype.toFixed(), "0", 'Number.prototype.toFixed() must return "0"'); +assert.sameValue(Number.prototype.toFixed(0), "0", 'Number.prototype.toFixed(0) must return "0"'); +assert.sameValue(Number.prototype.toFixed(1), "0.0", 'Number.prototype.toFixed(1) must return "0.0"'); +assert.sameValue(Number.prototype.toFixed(1.1), "0.0", 'Number.prototype.toFixed(1.1) must return "0.0"'); +assert.sameValue(Number.prototype.toFixed(0.9), "0", 'Number.prototype.toFixed(0.9) must return "0"'); +assert.sameValue(Number.prototype.toFixed("1"), "0.0", 'Number.prototype.toFixed("1") must return "0.0"'); +assert.sameValue(Number.prototype.toFixed("1.1"), "0.0", 'Number.prototype.toFixed("1.1") must return "0.0"'); +assert.sameValue(Number.prototype.toFixed("0.9"), "0", 'Number.prototype.toFixed("0.9") must return "0"'); +assert.sameValue(Number.prototype.toFixed(Number.NaN), "0", 'Number.prototype.toFixed(Number.NaN) must return "0"'); -//CHECK#1 -if (Number.prototype.toFixed() !== "0") { - throw new Test262Error('#1: Number.prototype.toFixed() === "0"'); -} +assert.sameValue( + Number.prototype.toFixed("some string"), + "0", + 'Number.prototype.toFixed("some string") must return "0"' +); -//CHECK#2 -if (Number.prototype.toFixed(0) !== "0") { - throw new Test262Error('#2: Number.prototype.toFixed(0) === "0"'); -} - -//CHECK#3 -if (Number.prototype.toFixed(1) !== "0.0") { - throw new Test262Error('#3: Number.prototype.toFixed(1) === "0.0"'); -} - -//CHECK#4 -if (Number.prototype.toFixed(1.1) !== "0.0") { - throw new Test262Error('#4: Number.prototype.toFixed(1.1) === "0.0"'); -} - -//CHECK#5 -if (Number.prototype.toFixed(0.9) !== "0") { - throw new Test262Error('#5: Number.prototype.toFixed(0.9) === "0"'); -} - - -//CHECK#6 -if (Number.prototype.toFixed("1") !== "0.0") { - throw new Test262Error('#6: Number.prototype.toFixed("1") === "0.0"'); -} - -//CHECK#7 -if (Number.prototype.toFixed("1.1") !== "0.0") { - throw new Test262Error('#7: Number.prototype.toFixed("1.1") === "0.0"'); -} - -//CHECK#8 -if (Number.prototype.toFixed("0.9") !== "0") { - throw new Test262Error('#8: Number.prototype.toFixed("0.9") === "0"'); -} - -//CHECK#9 -if (Number.prototype.toFixed(Number.NaN) !== "0") { - throw new Test262Error('#9: Number.prototype.toFixed(Number.NaN) === "0"'); -} - -//CHECK#10 -if (Number.prototype.toFixed("some string") !== "0") { - throw new Test262Error('#9: Number.prototype.toFixed("some string") === "0"'); -} - -//CHECK#11 try { - if (Number.prototype.toFixed(-0.1) !== "0") { - throw new Test262Error('#10: Number.prototype.toFixed(-0.1) === "0"'); - } + assert.sameValue(Number.prototype.toFixed(-0.1), "0", 'Number.prototype.toFixed(-0.1) must return "0"'); } catch (e) { throw new Test262Error('#10: Number.prototype.toFixed(-0.1) should not throw ' + e); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T02.js b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T02.js index 3b870fa5989b..a1dbd88b8b7d 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T02.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T02.js @@ -8,62 +8,24 @@ info: | es5id: 15.7.4.5_A1.1_T02 description: calling on Number object ---*/ +assert.sameValue((new Number(1)).toFixed(), "1", '(new Number(1)).toFixed() must return "1"'); +assert.sameValue((new Number(1)).toFixed(0), "1", '(new Number(1)).toFixed(0) must return "1"'); +assert.sameValue((new Number(1)).toFixed(1), "1.0", '(new Number(1)).toFixed(1) must return "1.0"'); +assert.sameValue((new Number(1)).toFixed(1.1), "1.0", '(new Number(1)).toFixed(1.1) must return "1.0"'); +assert.sameValue((new Number(1)).toFixed(0.9), "1", '(new Number(1)).toFixed(0.9) must return "1"'); +assert.sameValue((new Number(1)).toFixed("1"), "1.0", '(new Number(1)).toFixed("1") must return "1.0"'); +assert.sameValue((new Number(1)).toFixed("1.1"), "1.0", '(new Number(1)).toFixed("1.1") must return "1.0"'); +assert.sameValue((new Number(1)).toFixed("0.9"), "1", '(new Number(1)).toFixed("0.9") must return "1"'); +assert.sameValue((new Number(1)).toFixed(Number.NaN), "1", '(new Number(1)).toFixed(Number.NaN) must return "1"'); -//CHECK#1 -if ((new Number(1)).toFixed() !== "1") { - throw new Test262Error('#1: (new Number(1)).prototype.toFixed() === "1"'); -} +assert.sameValue( + (new Number(1)).toFixed("some string"), + "1", + '(new Number(1)).toFixed("some string") must return "1"' +); -//CHECK#2 -if ((new Number(1)).toFixed(0) !== "1") { - throw new Test262Error('#2: (new Number(1)).prototype.toFixed(0) === "1"'); -} - -//CHECK#3 -if ((new Number(1)).toFixed(1) !== "1.0") { - throw new Test262Error('#3: (new Number(1)).prototype.toFixed(1) === "1.0"'); -} - -//CHECK#4 -if ((new Number(1)).toFixed(1.1) !== "1.0") { - throw new Test262Error('#4: (new Number(1)).toFixed(1.1) === "1.0"'); -} - -//CHECK#5 -if ((new Number(1)).toFixed(0.9) !== "1") { - throw new Test262Error('#5: (new Number(1)).toFixed(0.9) === "1"'); -} - -//CHECK#6 -if ((new Number(1)).toFixed("1") !== "1.0") { - throw new Test262Error('#6: (new Number(1)).toFixed("1") === "1.0"'); -} - -//CHECK#7 -if ((new Number(1)).toFixed("1.1") !== "1.0") { - throw new Test262Error('#7: (new Number(1)).toFixed("1.1") === "1.0"'); -} - -//CHECK#8 -if ((new Number(1)).toFixed("0.9") !== "1") { - throw new Test262Error('#8: (new Number(1)).toFixed("0.9") === "1"'); -} - -//CHECK#9 -if ((new Number(1)).toFixed(Number.NaN) !== "1") { - throw new Test262Error('#9: (new Number(1)).toFixed(Number.NaN) === "1"'); -} - -//CHECK#10 -if ((new Number(1)).toFixed("some string") !== "1") { - throw new Test262Error('#9: (new Number(1)).toFixed("some string") === "1"'); -} - -//CHECK#10 try { - if ((new Number(1)).toFixed(-0.1) !== "1") { - throw new Test262Error('#10: (new Number(1)).toFixed(-0.1) === "1"'); - } + assert.sameValue((new Number(1)).toFixed(-0.1), "1", '(new Number(1)).toFixed(-0.1) must return "1"'); } catch (e) { throw new Test262Error('#10: (new Number(1)).toFixed(-0.1) should not throw ' + e); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.3_T01.js b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.3_T01.js index 169eb3ec0230..70468a816ae5 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.3_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.3_T01.js @@ -6,66 +6,33 @@ info: "Step 4: If this number value is NaN, return the string \"NaN\"" es5id: 15.7.4.5_A1.3_T01 description: NaN is computed by new Number("string") ---*/ +assert.sameValue((new Number("a")).toFixed(), "NaN", '(new Number("a")).toFixed() must return "NaN"'); +assert.sameValue((new Number("a")).toFixed(0), "NaN", '(new Number("a")).toFixed(0) must return "NaN"'); +assert.sameValue((new Number("a")).toFixed(1), "NaN", '(new Number("a")).toFixed(1) must return "NaN"'); +assert.sameValue((new Number("a")).toFixed(1.1), "NaN", '(new Number("a")).toFixed(1.1) must return "NaN"'); +assert.sameValue((new Number("a")).toFixed(0.9), "NaN", '(new Number("a")).toFixed(0.9) must return "NaN"'); +assert.sameValue((new Number("a")).toFixed("1"), "NaN", '(new Number("a")).toFixed("1") must return "NaN"'); +assert.sameValue((new Number("a")).toFixed("1.1"), "NaN", '(new Number("a")).toFixed("1.1") must return "NaN"'); +assert.sameValue((new Number("a")).toFixed("0.9"), "NaN", '(new Number("a")).toFixed("0.9") must return "NaN"'); -//CHECK#1 -if ((new Number("a")).toFixed() !== "NaN") { - throw new Test262Error('#1: (new Number("a")).prototype.toFixed() === "NaN"'); -} +assert.sameValue( + (new Number("a")).toFixed(Number.NaN), + "NaN", + '(new Number("a")).toFixed(Number.NaN) must return "NaN"' +); -//CHECK#2 -if ((new Number("a")).toFixed(0) !== "NaN") { - throw new Test262Error('#2: (new Number("a")).prototype.toFixed(0) === "NaN"'); -} +assert.sameValue( + (new Number("a")).toFixed("some string"), + "NaN", + '(new Number("a")).toFixed("some string") must return "NaN"' +); -//CHECK#3 -if ((new Number("a")).toFixed(1) !== "NaN") { - throw new Test262Error('#3: (new Number("a")).prototype.toFixed(1) === "NaN"'); -} - -//CHECK#4 -if ((new Number("a")).toFixed(1.1) !== "NaN") { - throw new Test262Error('#4: (new Number("a")).toFixed(1.1) === "NaN"'); -} - -//CHECK#5 -if ((new Number("a")).toFixed(0.9) !== "NaN") { - throw new Test262Error('#5: (new Number("a")).toFixed(0.9) === "NaN"'); -} - -//CHECK#6 -if ((new Number("a")).toFixed("1") !== "NaN") { - throw new Test262Error('#6: (new Number("a")).toFixed("1") === "NaN"'); -} - -//CHECK#7 -if ((new Number("a")).toFixed("1.1") !== "NaN") { - throw new Test262Error('#7: (new Number("a")).toFixed("1.1") === "NaN"'); -} - -//CHECK#8 -if ((new Number("a")).toFixed("0.9") !== "NaN") { - throw new Test262Error('#8: (new Number("a")).toFixed("0.9") === "NaN"'); -} - -//CHECK#9 -if ((new Number("a")).toFixed(Number.NaN) !== "NaN") { - throw new Test262Error('#9: (new Number("a")).toFixed(Number.NaN) === "NaN"'); -} - -//CHECK#10 -if ((new Number("a")).toFixed("some string") !== "NaN") { - throw new Test262Error('#9: (new Number("a")).toFixed("some string") === "NaN"'); -} - -//CHECK#10 try { s = (new Number("a")).toFixed(Number.POSITIVE_INFINITY); throw new Test262Error('#10: (new Number("a")).toFixed(Number.POSITIVE_INFINITY) should throw RangeError, not return NaN'); } catch (e) { - if (!(e instanceof RangeError)) { - throw new Test262Error('#10: (new Number("a")).toFixed(Number.POSITIVE_INFINITY) should throw RangeError, not ' + e); - } + assert(e instanceof RangeError, 'The result of evaluating (e instanceof RangeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.3_T02.js b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.3_T02.js index fccd9b9983f5..31cc85182c60 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.3_T02.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.3_T02.js @@ -6,66 +6,23 @@ info: "Step 4: If this number value is NaN, return the string \"NaN\"" es5id: 15.7.4.5_A1.3_T02 description: direct usage of NaN ---*/ +assert.sameValue(Number.NaN.toFixed(), "NaN", 'Number.NaN.toFixed() must return "NaN"'); +assert.sameValue(Number.NaN.toFixed(0), "NaN", 'Number.NaN.toFixed(0) must return "NaN"'); +assert.sameValue(Number.NaN.toFixed(1), "NaN", 'Number.NaN.toFixed(1) must return "NaN"'); +assert.sameValue(Number.NaN.toFixed(1.1), "NaN", 'Number.NaN.toFixed(1.1) must return "NaN"'); +assert.sameValue(Number.NaN.toFixed(0.9), "NaN", 'Number.NaN.toFixed(0.9) must return "NaN"'); +assert.sameValue(Number.NaN.toFixed("1"), "NaN", 'Number.NaN.toFixed("1") must return "NaN"'); +assert.sameValue(Number.NaN.toFixed("1.1"), "NaN", 'Number.NaN.toFixed("1.1") must return "NaN"'); +assert.sameValue(Number.NaN.toFixed("0.9"), "NaN", 'Number.NaN.toFixed("0.9") must return "NaN"'); +assert.sameValue(Number.NaN.toFixed(Number.NaN), "NaN", 'Number.NaN.toFixed(Number.NaN) must return "NaN"'); +assert.sameValue(Number.NaN.toFixed("some string"), "NaN", 'Number.NaN.toFixed("some string") must return "NaN"'); -//CHECK#1 -if (Number.NaN.toFixed() !== "NaN") { - throw new Test262Error('#1: Number.NaN.prototype.toFixed() === "NaN"'); -} - -//CHECK#2 -if (Number.NaN.toFixed(0) !== "NaN") { - throw new Test262Error('#2: Number.NaN.prototype.toFixed(0) === "NaN"'); -} - -//CHECK#3 -if (Number.NaN.toFixed(1) !== "NaN") { - throw new Test262Error('#3: Number.NaN.prototype.toFixed(1) === "NaN"'); -} - -//CHECK#4 -if (Number.NaN.toFixed(1.1) !== "NaN") { - throw new Test262Error('#4: Number.NaN.toFixed(1.1) === "NaN"'); -} - -//CHECK#5 -if (Number.NaN.toFixed(0.9) !== "NaN") { - throw new Test262Error('#5: Number.NaN.toFixed(0.9) === "NaN"'); -} - -//CHECK#6 -if (Number.NaN.toFixed("1") !== "NaN") { - throw new Test262Error('#6: Number.NaN.toFixed("1") === "NaN"'); -} - -//CHECK#7 -if (Number.NaN.toFixed("1.1") !== "NaN") { - throw new Test262Error('#7: Number.NaN.toFixed("1.1") === "NaN"'); -} - -//CHECK#8 -if (Number.NaN.toFixed("0.9") !== "NaN") { - throw new Test262Error('#8: Number.NaN.toFixed("0.9") === "NaN"'); -} - -//CHECK#9 -if (Number.NaN.toFixed(Number.NaN) !== "NaN") { - throw new Test262Error('#9: Number.NaN.toFixed(Number.NaN) === "NaN"'); -} - -//CHECK#10 -if (Number.NaN.toFixed("some string") !== "NaN") { - throw new Test262Error('#9: Number.NaN.toFixed("some string") === "NaN"'); -} - -//CHECK#10 try { s = Number.NaN.toFixed(Number.POSITIVE_INFINITY); throw new Test262Error('#10: Number.NaN.toFixed(Number.POSITIVE_INFINITY) should throw RangeError, not return NaN'); } catch (e) { - if (!(e instanceof RangeError)) { - throw new Test262Error('#10: Number.NaN.toFixed(Number.POSITIVE_INFINITY) should throw RangeError, not ' + e); - } + assert(e instanceof RangeError, 'The result of evaluating (e instanceof RangeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.4_T01.js b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.4_T01.js index fb84061e5487..c5e9de87a7b9 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.4_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A1.4_T01.js @@ -6,66 +6,72 @@ info: "Step 9: If x >= 10^21, let m = ToString(x)" es5id: 15.7.4.5_A1.4_T01 description: x is 10^21 ---*/ +assert.sameValue( + (new Number(1e21)).toFixed(), + String(1e21), + '(new Number(1e21)).toFixed() must return the same value returned by String(1e21)' +); -//CHECK#1 -if ((new Number(1e21)).toFixed() !== String(1e21)) { - throw new Test262Error('#1: (new Number(1e21)).prototype.toFixed() === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed(0), + String(1e21), + '(new Number(1e21)).toFixed(0) must return the same value returned by String(1e21)' +); -//CHECK#2 -if ((new Number(1e21)).toFixed(0) !== String(1e21)) { - throw new Test262Error('#2: (new Number(1e21)).prototype.toFixed(0) === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed(1), + String(1e21), + '(new Number(1e21)).toFixed(1) must return the same value returned by String(1e21)' +); -//CHECK#3 -if ((new Number(1e21)).toFixed(1) !== String(1e21)) { - throw new Test262Error('#3: (new Number(1e21)).prototype.toFixed(1) === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed(1.1), + String(1e21), + '(new Number(1e21)).toFixed(1.1) must return the same value returned by String(1e21)' +); -//CHECK#4 -if ((new Number(1e21)).toFixed(1.1) !== String(1e21)) { - throw new Test262Error('#4: (new Number(1e21)).toFixed(1.1) === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed(0.9), + String(1e21), + '(new Number(1e21)).toFixed(0.9) must return the same value returned by String(1e21)' +); -//CHECK#5 -if ((new Number(1e21)).toFixed(0.9) !== String(1e21)) { - throw new Test262Error('#5: (new Number(1e21)).toFixed(0.9) === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed("1"), + String(1e21), + '(new Number(1e21)).toFixed("1") must return the same value returned by String(1e21)' +); -//CHECK#6 -if ((new Number(1e21)).toFixed("1") !== String(1e21)) { - throw new Test262Error('#6: (new Number(1e21)).toFixed("1") === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed("1.1"), + String(1e21), + '(new Number(1e21)).toFixed("1.1") must return the same value returned by String(1e21)' +); -//CHECK#7 -if ((new Number(1e21)).toFixed("1.1") !== String(1e21)) { - throw new Test262Error('#7: (new Number(1e21)).toFixed("1.1") === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed("0.9"), + String(1e21), + '(new Number(1e21)).toFixed("0.9") must return the same value returned by String(1e21)' +); -//CHECK#8 -if ((new Number(1e21)).toFixed("0.9") !== String(1e21)) { - throw new Test262Error('#8: (new Number(1e21)).toFixed("0.9") === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed(Number.NaN), + String(1e21), + '(new Number(1e21)).toFixed(Number.NaN) must return the same value returned by String(1e21)' +); -//CHECK#9 -if ((new Number(1e21)).toFixed(Number.NaN) !== String(1e21)) { - throw new Test262Error('#9: (new Number(1e21)).toFixed(Number.NaN) === String(1e21)'); -} +assert.sameValue( + (new Number(1e21)).toFixed("some string"), + String(1e21), + '(new Number(1e21)).toFixed("some string") must return the same value returned by String(1e21)' +); -//CHECK#10 -if ((new Number(1e21)).toFixed("some string") !== String(1e21)) { - throw new Test262Error('#9: (new Number(1e21)).toFixed("some string") === String(1e21)'); -} - -//CHECK#10 try { s = (new Number(1e21)).toFixed(Number.POSITIVE_INFINITY); throw new Test262Error('#10: (new Number(1e21)).toFixed(Number.POSITIVE_INFINITY) should throw RangeError, not return NaN'); } catch (e) { - if (!(e instanceof RangeError)) { - throw new Test262Error('#10: (new Number(1e21)).toFixed(Number.POSITIVE_INFINITY) should throw RangeError, not ' + e); - } + assert(e instanceof RangeError, 'The result of evaluating (e instanceof RangeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A2_T01.js b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A2_T01.js index 594b74e5d6d6..2d7ef86f1d83 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A2_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toFixed/S15.7.4.5_A2_T01.js @@ -6,15 +6,16 @@ info: The length property of the toFixed method is 1 es5id: 15.7.4.5_A2_T01 description: Checking Number prototype itself ---*/ +assert.sameValue( + Number.prototype.toFixed.hasOwnProperty("length"), + true, + 'Number.prototype.toFixed.hasOwnProperty("length") must return true' +); -//CHECK#1 -if (Number.prototype.toFixed.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: The length property of the toFixed method is 1'); -} - -//CHECK#2 -if (Number.prototype.toFixed.length !== 1) { - throw new Test262Error('#2: The length property of the toFixed method is 1'); -} +assert.sameValue( + Number.prototype.toFixed.length, + 1, + 'The value of Number.prototype.toFixed.length is expected to be 1' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T01.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T01.js index 403e545b3e8c..09d10b50e8a2 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T01.js @@ -9,45 +9,23 @@ info: | es5id: 15.7.4.2_A1_T01 description: undefined radix ---*/ +assert.sameValue(Number.prototype.toString(), "0", 'Number.prototype.toString() must return "0"'); +assert.sameValue((new Number()).toString(), "0", '(new Number()).toString() must return "0"'); +assert.sameValue((new Number(0)).toString(), "0", '(new Number(0)).toString() must return "0"'); +assert.sameValue((new Number(-1)).toString(), "-1", '(new Number(-1)).toString() must return "-1"'); +assert.sameValue((new Number(1)).toString(), "1", '(new Number(1)).toString() must return "1"'); +assert.sameValue((new Number(Number.NaN)).toString(), "NaN", '(new Number(Number.NaN)).toString() must return "NaN"'); -//CHECK#1 -if (Number.prototype.toString() !== "0") { - throw new Test262Error('#1: Number.prototype.toString() === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString() must return "Infinity"' +); -//CHECK#2 -if ((new Number()).toString() !== "0") { - throw new Test262Error('#2: (new Number()).toString() === "0"'); -} - -//CHECK#3 -if ((new Number(0)).toString() !== "0") { - throw new Test262Error('#3: (new Number(0)).toString() === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString() !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString() === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString() !== "1") { - throw new Test262Error('#5: (new Number(1)).toString() === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString() !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString() === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString() !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString() === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString() !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString() === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString() must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T02.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T02.js index b03b54d7d03d..1d7e7b6693cb 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T02.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T02.js @@ -9,45 +9,28 @@ info: | es5id: 15.7.4.2_A1_T02 description: radix is 10 ---*/ +assert.sameValue(Number.prototype.toString(10), "0", 'Number.prototype.toString(10) must return "0"'); +assert.sameValue((new Number()).toString(10), "0", '(new Number()).toString(10) must return "0"'); +assert.sameValue((new Number(0)).toString(10), "0", '(new Number(0)).toString(10) must return "0"'); +assert.sameValue((new Number(-1)).toString(10), "-1", '(new Number(-1)).toString(10) must return "-1"'); +assert.sameValue((new Number(1)).toString(10), "1", '(new Number(1)).toString(10) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(10) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(10) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(10), + "NaN", + '(new Number(Number.NaN)).toString(10) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(10) !== "0") { - throw new Test262Error('#2: (new Number()).toString(10) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(10), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(10) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(10) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(10) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(10) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(10) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(10) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(10) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(10) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(10) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(10) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(10) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(10) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(10) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(10), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(10) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T03.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T03.js index 8f5c6529b48b..68820bd38278 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T03.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A1_T03.js @@ -9,45 +9,28 @@ info: | es5id: 15.7.4.2_A1_T03 description: radix is undefined value ---*/ +assert.sameValue(Number.prototype.toString(undefined), "0", 'Number.prototype.toString(undefined) must return "0"'); +assert.sameValue((new Number()).toString(undefined), "0", '(new Number()).toString(undefined) must return "0"'); +assert.sameValue((new Number(0)).toString(undefined), "0", '(new Number(0)).toString(undefined) must return "0"'); +assert.sameValue((new Number(-1)).toString(undefined), "-1", '(new Number(-1)).toString(undefined) must return "-1"'); +assert.sameValue((new Number(1)).toString(undefined), "1", '(new Number(1)).toString(undefined) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(undefined) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(undefined) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(undefined), + "NaN", + '(new Number(Number.NaN)).toString(undefined) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(undefined) !== "0") { - throw new Test262Error('#2: (new Number()).toString(undefined) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(undefined), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(undefined) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(undefined) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(undefined) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(undefined) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(undefined) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(undefined) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(undefined) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(undefined) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(undefined) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(undefined) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(undefined) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(undefined) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(undefined) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(undefined), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(undefined) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T01.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T01.js index dd74f21baa29..85dff6174dcd 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T01.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T01 description: radix is 2 ---*/ +assert.sameValue(Number.prototype.toString(2), "0", 'Number.prototype.toString(2) must return "0"'); +assert.sameValue((new Number()).toString(2), "0", '(new Number()).toString(2) must return "0"'); +assert.sameValue((new Number(0)).toString(2), "0", '(new Number(0)).toString(2) must return "0"'); +assert.sameValue((new Number(-1)).toString(2), "-1", '(new Number(-1)).toString(2) must return "-1"'); +assert.sameValue((new Number(1)).toString(2), "1", '(new Number(1)).toString(2) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(2) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(2) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(2), + "NaN", + '(new Number(Number.NaN)).toString(2) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(2) !== "0") { - throw new Test262Error('#2: (new Number()).toString(2) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(2), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(2) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(2) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(2) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(2) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(2) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(2) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(2) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(2) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(2) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(2) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(2) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(2) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(2) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(2), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(2) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T02.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T02.js index 52ae859999fa..11f498aa1e36 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T02.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T02.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T02 description: radix is 3 ---*/ +assert.sameValue(Number.prototype.toString(3), "0", 'Number.prototype.toString(3) must return "0"'); +assert.sameValue((new Number()).toString(3), "0", '(new Number()).toString(3) must return "0"'); +assert.sameValue((new Number(0)).toString(3), "0", '(new Number(0)).toString(3) must return "0"'); +assert.sameValue((new Number(-1)).toString(3), "-1", '(new Number(-1)).toString(3) must return "-1"'); +assert.sameValue((new Number(1)).toString(3), "1", '(new Number(1)).toString(3) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(3) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(3) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(3), + "NaN", + '(new Number(Number.NaN)).toString(3) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(3) !== "0") { - throw new Test262Error('#2: (new Number()).toString(3) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(3), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(3) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(3) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(3) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(3) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(3) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(3) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(3) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(3) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(3) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(3) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(3) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(3) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(3) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(3), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(3) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T03.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T03.js index 98015fe899fa..d928cfe2566d 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T03.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T03.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T03 description: radix is 4 ---*/ +assert.sameValue(Number.prototype.toString(4), "0", 'Number.prototype.toString(4) must return "0"'); +assert.sameValue((new Number()).toString(4), "0", '(new Number()).toString(4) must return "0"'); +assert.sameValue((new Number(0)).toString(4), "0", '(new Number(0)).toString(4) must return "0"'); +assert.sameValue((new Number(-1)).toString(4), "-1", '(new Number(-1)).toString(4) must return "-1"'); +assert.sameValue((new Number(1)).toString(4), "1", '(new Number(1)).toString(4) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(4) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(4) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(4), + "NaN", + '(new Number(Number.NaN)).toString(4) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(4) !== "0") { - throw new Test262Error('#2: (new Number()).toString(4) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(4), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(4) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(4) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(4) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(4) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(4) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(4) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(4) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(4) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(4) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(4) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(4) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(4) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(4) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(4), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(4) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T04.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T04.js index e5ef19cedd77..f5d29c361576 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T04.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T04.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T04 description: radix is 5 ---*/ +assert.sameValue(Number.prototype.toString(5), "0", 'Number.prototype.toString(5) must return "0"'); +assert.sameValue((new Number()).toString(5), "0", '(new Number()).toString(5) must return "0"'); +assert.sameValue((new Number(0)).toString(5), "0", '(new Number(0)).toString(5) must return "0"'); +assert.sameValue((new Number(-1)).toString(5), "-1", '(new Number(-1)).toString(5) must return "-1"'); +assert.sameValue((new Number(1)).toString(5), "1", '(new Number(1)).toString(5) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(5) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(5) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(5), + "NaN", + '(new Number(Number.NaN)).toString(5) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(5) !== "0") { - throw new Test262Error('#2: (new Number()).toString(5) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(5), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(5) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(5) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(5) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(5) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(5) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(5) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(5) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(5) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(5) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(5) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(5) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(5) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(5) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(5), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(5) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T05.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T05.js index 53ec56020af6..dad8b716943d 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T05.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T05.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T05 description: radix is 6 ---*/ +assert.sameValue(Number.prototype.toString(6), "0", 'Number.prototype.toString(6) must return "0"'); +assert.sameValue((new Number()).toString(6), "0", '(new Number()).toString(6) must return "0"'); +assert.sameValue((new Number(0)).toString(6), "0", '(new Number(0)).toString(6) must return "0"'); +assert.sameValue((new Number(-1)).toString(6), "-1", '(new Number(-1)).toString(6) must return "-1"'); +assert.sameValue((new Number(1)).toString(6), "1", '(new Number(1)).toString(6) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(6) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(6) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(6), + "NaN", + '(new Number(Number.NaN)).toString(6) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(6) !== "0") { - throw new Test262Error('#2: (new Number()).toString(6) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(6), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(6) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(6) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(6) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(6) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(6) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(6) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(6) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(6) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(6) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(6) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(6) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(6) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(6) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(6), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(6) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T06.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T06.js index 4eece7b7d3c2..0eed1bd91864 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T06.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T06.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T06 description: radix is 7 ---*/ +assert.sameValue(Number.prototype.toString(7), "0", 'Number.prototype.toString(7) must return "0"'); +assert.sameValue((new Number()).toString(7), "0", '(new Number()).toString(7) must return "0"'); +assert.sameValue((new Number(0)).toString(7), "0", '(new Number(0)).toString(7) must return "0"'); +assert.sameValue((new Number(-1)).toString(7), "-1", '(new Number(-1)).toString(7) must return "-1"'); +assert.sameValue((new Number(1)).toString(7), "1", '(new Number(1)).toString(7) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(7) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(7) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(7), + "NaN", + '(new Number(Number.NaN)).toString(7) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(7) !== "0") { - throw new Test262Error('#2: (new Number()).toString(7) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(7), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(7) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(7) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(7) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(7) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(7) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(7) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(7) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(7) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(7) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(7) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(7) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(7) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(7) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(7), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(7) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T07.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T07.js index 6bfcffa75dc4..95a98e7edd4b 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T07.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T07.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T07 description: radix is 8 ---*/ +assert.sameValue(Number.prototype.toString(8), "0", 'Number.prototype.toString(8) must return "0"'); +assert.sameValue((new Number()).toString(8), "0", '(new Number()).toString(8) must return "0"'); +assert.sameValue((new Number(0)).toString(8), "0", '(new Number(0)).toString(8) must return "0"'); +assert.sameValue((new Number(-1)).toString(8), "-1", '(new Number(-1)).toString(8) must return "-1"'); +assert.sameValue((new Number(1)).toString(8), "1", '(new Number(1)).toString(8) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(8) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(8) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(8), + "NaN", + '(new Number(Number.NaN)).toString(8) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(8) !== "0") { - throw new Test262Error('#2: (new Number()).toString(8) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(8), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(8) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(8) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(8) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(8) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(8) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(8) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(8) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(8) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(8) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(8) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(8) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(8) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(8) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(8), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(8) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T08.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T08.js index 37332961a9a1..c19c015f01e0 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T08.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T08.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T08 description: radix is 9 ---*/ +assert.sameValue(Number.prototype.toString(9), "0", 'Number.prototype.toString(9) must return "0"'); +assert.sameValue((new Number()).toString(9), "0", '(new Number()).toString(9) must return "0"'); +assert.sameValue((new Number(0)).toString(9), "0", '(new Number(0)).toString(9) must return "0"'); +assert.sameValue((new Number(-1)).toString(9), "-1", '(new Number(-1)).toString(9) must return "-1"'); +assert.sameValue((new Number(1)).toString(9), "1", '(new Number(1)).toString(9) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(9) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(9) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(9), + "NaN", + '(new Number(Number.NaN)).toString(9) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(9) !== "0") { - throw new Test262Error('#2: (new Number()).toString(9) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(9), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(9) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(9) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(9) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(9) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(9) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(9) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(9) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(9) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(9) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(9) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(9) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(9) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(9) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(9), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(9) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T09.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T09.js index 58fe2d6be0c7..139c6c40b349 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T09.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T09.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T09 description: radix is 11 ---*/ +assert.sameValue(Number.prototype.toString(11), "0", 'Number.prototype.toString(11) must return "0"'); +assert.sameValue((new Number()).toString(11), "0", '(new Number()).toString(11) must return "0"'); +assert.sameValue((new Number(0)).toString(11), "0", '(new Number(0)).toString(11) must return "0"'); +assert.sameValue((new Number(-1)).toString(11), "-1", '(new Number(-1)).toString(11) must return "-1"'); +assert.sameValue((new Number(1)).toString(11), "1", '(new Number(1)).toString(11) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(11) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(11) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(11), + "NaN", + '(new Number(Number.NaN)).toString(11) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(11) !== "0") { - throw new Test262Error('#2: (new Number()).toString(11) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(11), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(11) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(11) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(11) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(11) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(11) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(11) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(11) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(11) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(11) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(11) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(11) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(11) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(11) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(11), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(11) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T10.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T10.js index e2b8e5924f47..8cd2862ac48d 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T10.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T10.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T10 description: radix is 12 ---*/ +assert.sameValue(Number.prototype.toString(12), "0", 'Number.prototype.toString(12) must return "0"'); +assert.sameValue((new Number()).toString(12), "0", '(new Number()).toString(12) must return "0"'); +assert.sameValue((new Number(0)).toString(12), "0", '(new Number(0)).toString(12) must return "0"'); +assert.sameValue((new Number(-1)).toString(12), "-1", '(new Number(-1)).toString(12) must return "-1"'); +assert.sameValue((new Number(1)).toString(12), "1", '(new Number(1)).toString(12) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(12) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(12) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(12), + "NaN", + '(new Number(Number.NaN)).toString(12) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(12) !== "0") { - throw new Test262Error('#2: (new Number()).toString(12) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(12), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(12) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(12) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(12) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(12) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(12) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(12) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(12) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(12) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(12) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(12) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(12) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(12) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(12) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(12), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(12) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T11.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T11.js index f425d7c56335..2e6279cf9764 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T11.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T11.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T11 description: radix is 13 ---*/ +assert.sameValue(Number.prototype.toString(13), "0", 'Number.prototype.toString(13) must return "0"'); +assert.sameValue((new Number()).toString(13), "0", '(new Number()).toString(13) must return "0"'); +assert.sameValue((new Number(0)).toString(13), "0", '(new Number(0)).toString(13) must return "0"'); +assert.sameValue((new Number(-1)).toString(13), "-1", '(new Number(-1)).toString(13) must return "-1"'); +assert.sameValue((new Number(1)).toString(13), "1", '(new Number(1)).toString(13) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(13) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(13) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(13), + "NaN", + '(new Number(Number.NaN)).toString(13) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(13) !== "0") { - throw new Test262Error('#2: (new Number()).toString(13) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(13), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(13) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(13) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(13) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(13) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(13) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(13) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(13) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(13) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(13) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(13) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(13) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(13) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(13) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(13), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(13) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T12.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T12.js index 62ff69e8b4fe..ef1ac373a1e5 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T12.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T12.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T12 description: radix is 14 ---*/ +assert.sameValue(Number.prototype.toString(14), "0", 'Number.prototype.toString(14) must return "0"'); +assert.sameValue((new Number()).toString(14), "0", '(new Number()).toString(14) must return "0"'); +assert.sameValue((new Number(0)).toString(14), "0", '(new Number(0)).toString(14) must return "0"'); +assert.sameValue((new Number(-1)).toString(14), "-1", '(new Number(-1)).toString(14) must return "-1"'); +assert.sameValue((new Number(1)).toString(14), "1", '(new Number(1)).toString(14) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(14) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(14) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(14), + "NaN", + '(new Number(Number.NaN)).toString(14) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(14) !== "0") { - throw new Test262Error('#2: (new Number()).toString(14) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(14), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(14) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(14) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(14) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(14) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(14) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(14) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(14) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(14) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(14) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(14) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(14) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(14) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(14) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(14), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(14) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T13.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T13.js index e1fb7462cc60..a424274e285e 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T13.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T13.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T13 description: radix is 15 ---*/ +assert.sameValue(Number.prototype.toString(15), "0", 'Number.prototype.toString(15) must return "0"'); +assert.sameValue((new Number()).toString(15), "0", '(new Number()).toString(15) must return "0"'); +assert.sameValue((new Number(0)).toString(15), "0", '(new Number(0)).toString(15) must return "0"'); +assert.sameValue((new Number(-1)).toString(15), "-1", '(new Number(-1)).toString(15) must return "-1"'); +assert.sameValue((new Number(1)).toString(15), "1", '(new Number(1)).toString(15) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(15) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(15) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(15), + "NaN", + '(new Number(Number.NaN)).toString(15) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(15) !== "0") { - throw new Test262Error('#2: (new Number()).toString(15) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(15), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(15) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(15) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(15) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(15) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(15) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(15) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(15) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(15) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(15) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(15) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(15) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(15) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(15) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(15), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(15) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T14.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T14.js index 6b213cafd7f5..2f65b2b23c6c 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T14.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T14.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T14 description: radix is 16 ---*/ +assert.sameValue(Number.prototype.toString(16), "0", 'Number.prototype.toString(16) must return "0"'); +assert.sameValue((new Number()).toString(16), "0", '(new Number()).toString(16) must return "0"'); +assert.sameValue((new Number(0)).toString(16), "0", '(new Number(0)).toString(16) must return "0"'); +assert.sameValue((new Number(-1)).toString(16), "-1", '(new Number(-1)).toString(16) must return "-1"'); +assert.sameValue((new Number(1)).toString(16), "1", '(new Number(1)).toString(16) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(16) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(16) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(16), + "NaN", + '(new Number(Number.NaN)).toString(16) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(16) !== "0") { - throw new Test262Error('#2: (new Number()).toString(16) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(16), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(16) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(16) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(16) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(16) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(16) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(16) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(16) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(16) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(16) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(16) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(16) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(16) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(16) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(16), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(16) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T15.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T15.js index 17e9f1e57e1c..ea4c92bf8519 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T15.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T15.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T15 description: radix is 17 ---*/ +assert.sameValue(Number.prototype.toString(17), "0", 'Number.prototype.toString(17) must return "0"'); +assert.sameValue((new Number()).toString(17), "0", '(new Number()).toString(17) must return "0"'); +assert.sameValue((new Number(0)).toString(17), "0", '(new Number(0)).toString(17) must return "0"'); +assert.sameValue((new Number(-1)).toString(17), "-1", '(new Number(-1)).toString(17) must return "-1"'); +assert.sameValue((new Number(1)).toString(17), "1", '(new Number(1)).toString(17) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(17) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(17) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(17), + "NaN", + '(new Number(Number.NaN)).toString(17) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(17) !== "0") { - throw new Test262Error('#2: (new Number()).toString(17) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(17), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(17) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(17) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(17) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(17) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(17) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(17) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(17) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(17) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(17) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(17) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(17) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(17) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(17) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(17), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(17) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T16.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T16.js index b302f9587ee7..293b161a25d1 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T16.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T16.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T16 description: radix is 18 ---*/ +assert.sameValue(Number.prototype.toString(18), "0", 'Number.prototype.toString(18) must return "0"'); +assert.sameValue((new Number()).toString(18), "0", '(new Number()).toString(18) must return "0"'); +assert.sameValue((new Number(0)).toString(18), "0", '(new Number(0)).toString(18) must return "0"'); +assert.sameValue((new Number(-1)).toString(18), "-1", '(new Number(-1)).toString(18) must return "-1"'); +assert.sameValue((new Number(1)).toString(18), "1", '(new Number(1)).toString(18) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(18) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(18) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(18), + "NaN", + '(new Number(Number.NaN)).toString(18) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(18) !== "0") { - throw new Test262Error('#2: (new Number()).toString(18) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(18), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(18) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(18) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(18) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(18) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(18) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(18) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(18) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(18) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(18) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(18) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(18) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(18) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(18) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(18), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(18) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T17.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T17.js index cbb408233027..8abf41383ed6 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T17.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T17.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T17 description: radix is 19 ---*/ +assert.sameValue(Number.prototype.toString(19), "0", 'Number.prototype.toString(19) must return "0"'); +assert.sameValue((new Number()).toString(19), "0", '(new Number()).toString(19) must return "0"'); +assert.sameValue((new Number(0)).toString(19), "0", '(new Number(0)).toString(19) must return "0"'); +assert.sameValue((new Number(-1)).toString(19), "-1", '(new Number(-1)).toString(19) must return "-1"'); +assert.sameValue((new Number(1)).toString(19), "1", '(new Number(1)).toString(19) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(19) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(19) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(19), + "NaN", + '(new Number(Number.NaN)).toString(19) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(19) !== "0") { - throw new Test262Error('#2: (new Number()).toString(19) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(19), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(19) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(19) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(19) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(19) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(19) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(19) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(19) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(19) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(19) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(19) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(19) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(19) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(19) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(19), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(19) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T18.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T18.js index 124e3b37c6c7..d6802a9329a8 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T18.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T18.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T18 description: radix is 20 ---*/ +assert.sameValue(Number.prototype.toString(20), "0", 'Number.prototype.toString(20) must return "0"'); +assert.sameValue((new Number()).toString(20), "0", '(new Number()).toString(20) must return "0"'); +assert.sameValue((new Number(0)).toString(20), "0", '(new Number(0)).toString(20) must return "0"'); +assert.sameValue((new Number(-1)).toString(20), "-1", '(new Number(-1)).toString(20) must return "-1"'); +assert.sameValue((new Number(1)).toString(20), "1", '(new Number(1)).toString(20) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(20) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(20) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(20), + "NaN", + '(new Number(Number.NaN)).toString(20) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(20) !== "0") { - throw new Test262Error('#2: (new Number()).toString(20) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(20), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(20) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(20) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(20) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(20) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(20) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(20) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(20) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(20) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(20) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(20) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(20) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(20) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(20) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(20), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(20) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T19.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T19.js index 990ea22fb1f1..a4a4bf68fdfb 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T19.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T19.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T19 description: radix is 21 ---*/ +assert.sameValue(Number.prototype.toString(21), "0", 'Number.prototype.toString(21) must return "0"'); +assert.sameValue((new Number()).toString(21), "0", '(new Number()).toString(21) must return "0"'); +assert.sameValue((new Number(0)).toString(21), "0", '(new Number(0)).toString(21) must return "0"'); +assert.sameValue((new Number(-1)).toString(21), "-1", '(new Number(-1)).toString(21) must return "-1"'); +assert.sameValue((new Number(1)).toString(21), "1", '(new Number(1)).toString(21) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(21) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(21) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(21), + "NaN", + '(new Number(Number.NaN)).toString(21) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(21) !== "0") { - throw new Test262Error('#2: (new Number()).toString(21) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(21), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(21) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(21) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(21) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(21) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(21) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(21) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(21) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(21) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(21) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(21) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(21) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(21) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(21) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(21), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(21) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T20.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T20.js index 03d547a14f2d..995190f0fb00 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T20.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T20.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T20 description: radix is 22 ---*/ +assert.sameValue(Number.prototype.toString(22), "0", 'Number.prototype.toString(22) must return "0"'); +assert.sameValue((new Number()).toString(22), "0", '(new Number()).toString(22) must return "0"'); +assert.sameValue((new Number(0)).toString(22), "0", '(new Number(0)).toString(22) must return "0"'); +assert.sameValue((new Number(-1)).toString(22), "-1", '(new Number(-1)).toString(22) must return "-1"'); +assert.sameValue((new Number(1)).toString(22), "1", '(new Number(1)).toString(22) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(22) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(22) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(22), + "NaN", + '(new Number(Number.NaN)).toString(22) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(22) !== "0") { - throw new Test262Error('#2: (new Number()).toString(22) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(22), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(22) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(22) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(22) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(22) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(22) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(22) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(22) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(22) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(22) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(22) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(22) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(22) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(22) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(22), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(22) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T21.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T21.js index f25256697040..6519b6806524 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T21.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T21.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T21 description: radix is 23 ---*/ +assert.sameValue(Number.prototype.toString(23), "0", 'Number.prototype.toString(23) must return "0"'); +assert.sameValue((new Number()).toString(23), "0", '(new Number()).toString(23) must return "0"'); +assert.sameValue((new Number(0)).toString(23), "0", '(new Number(0)).toString(23) must return "0"'); +assert.sameValue((new Number(-1)).toString(23), "-1", '(new Number(-1)).toString(23) must return "-1"'); +assert.sameValue((new Number(1)).toString(23), "1", '(new Number(1)).toString(23) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(23) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(23) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(23), + "NaN", + '(new Number(Number.NaN)).toString(23) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(23) !== "0") { - throw new Test262Error('#2: (new Number()).toString(23) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(23), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(23) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(23) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(23) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(23) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(23) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(23) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(23) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(23) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(23) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(23) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(23) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(23) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(23) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(23), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(23) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T22.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T22.js index 67fbc701e431..1aa40777a212 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T22.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T22.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T22 description: radix is 24 ---*/ +assert.sameValue(Number.prototype.toString(24), "0", 'Number.prototype.toString(24) must return "0"'); +assert.sameValue((new Number()).toString(24), "0", '(new Number()).toString(24) must return "0"'); +assert.sameValue((new Number(0)).toString(24), "0", '(new Number(0)).toString(24) must return "0"'); +assert.sameValue((new Number(-1)).toString(24), "-1", '(new Number(-1)).toString(24) must return "-1"'); +assert.sameValue((new Number(1)).toString(24), "1", '(new Number(1)).toString(24) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(24) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(24) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(24), + "NaN", + '(new Number(Number.NaN)).toString(24) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(24) !== "0") { - throw new Test262Error('#2: (new Number()).toString(24) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(24), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(24) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(24) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(24) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(24) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(24) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(24) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(24) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(24) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(24) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(24) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(24) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(24) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(24) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(24), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(24) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T23.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T23.js index cad6658f76b6..0ce411e3d79e 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T23.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T23.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T23 description: radix is 25 ---*/ +assert.sameValue(Number.prototype.toString(25), "0", 'Number.prototype.toString(25) must return "0"'); +assert.sameValue((new Number()).toString(25), "0", '(new Number()).toString(25) must return "0"'); +assert.sameValue((new Number(0)).toString(25), "0", '(new Number(0)).toString(25) must return "0"'); +assert.sameValue((new Number(-1)).toString(25), "-1", '(new Number(-1)).toString(25) must return "-1"'); +assert.sameValue((new Number(1)).toString(25), "1", '(new Number(1)).toString(25) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(25) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(25) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(25), + "NaN", + '(new Number(Number.NaN)).toString(25) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(25) !== "0") { - throw new Test262Error('#2: (new Number()).toString(25) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(25), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(25) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(25) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(25) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(25) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(25) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(25) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(25) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(25) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(25) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(25) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(25) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(25) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(25) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(25), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(25) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T24.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T24.js index 379b7f208a9f..55f666850d63 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T24.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T24.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T24 description: radix is 26 ---*/ +assert.sameValue(Number.prototype.toString(26), "0", 'Number.prototype.toString(26) must return "0"'); +assert.sameValue((new Number()).toString(26), "0", '(new Number()).toString(26) must return "0"'); +assert.sameValue((new Number(0)).toString(26), "0", '(new Number(0)).toString(26) must return "0"'); +assert.sameValue((new Number(-1)).toString(26), "-1", '(new Number(-1)).toString(26) must return "-1"'); +assert.sameValue((new Number(1)).toString(26), "1", '(new Number(1)).toString(26) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(26) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(26) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(26), + "NaN", + '(new Number(Number.NaN)).toString(26) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(26) !== "0") { - throw new Test262Error('#2: (new Number()).toString(26) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(26), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(26) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(26) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(26) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(26) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(26) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(26) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(26) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(26) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(26) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(26) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(26) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(26) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(26) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(26), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(26) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T25.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T25.js index 0069faca2e76..4930fce27c1b 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T25.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T25.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T25 description: radix is 27 ---*/ +assert.sameValue(Number.prototype.toString(27), "0", 'Number.prototype.toString(27) must return "0"'); +assert.sameValue((new Number()).toString(27), "0", '(new Number()).toString(27) must return "0"'); +assert.sameValue((new Number(0)).toString(27), "0", '(new Number(0)).toString(27) must return "0"'); +assert.sameValue((new Number(-1)).toString(27), "-1", '(new Number(-1)).toString(27) must return "-1"'); +assert.sameValue((new Number(1)).toString(27), "1", '(new Number(1)).toString(27) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(27) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(27) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(27), + "NaN", + '(new Number(Number.NaN)).toString(27) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(27) !== "0") { - throw new Test262Error('#2: (new Number()).toString(27) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(27), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(27) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(27) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(27) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(27) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(27) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(27) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(27) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(27) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(27) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(27) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(27) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(27) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(27) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(27), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(27) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T26.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T26.js index 14aa9baa34c4..c59ab5d6a1c3 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T26.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T26.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T26 description: radix is 28 ---*/ +assert.sameValue(Number.prototype.toString(28), "0", 'Number.prototype.toString(28) must return "0"'); +assert.sameValue((new Number()).toString(28), "0", '(new Number()).toString(28) must return "0"'); +assert.sameValue((new Number(0)).toString(28), "0", '(new Number(0)).toString(28) must return "0"'); +assert.sameValue((new Number(-1)).toString(28), "-1", '(new Number(-1)).toString(28) must return "-1"'); +assert.sameValue((new Number(1)).toString(28), "1", '(new Number(1)).toString(28) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(28) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(28) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(28), + "NaN", + '(new Number(Number.NaN)).toString(28) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(28) !== "0") { - throw new Test262Error('#2: (new Number()).toString(28) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(28), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(28) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(28) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(28) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(28) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(28) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(28) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(28) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(28) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(28) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(28) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(28) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(28) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(28) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(28), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(28) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T27.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T27.js index b7321be48801..cb6064d05988 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T27.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T27.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T27 description: radix is 29 ---*/ +assert.sameValue(Number.prototype.toString(29), "0", 'Number.prototype.toString(29) must return "0"'); +assert.sameValue((new Number()).toString(29), "0", '(new Number()).toString(29) must return "0"'); +assert.sameValue((new Number(0)).toString(29), "0", '(new Number(0)).toString(29) must return "0"'); +assert.sameValue((new Number(-1)).toString(29), "-1", '(new Number(-1)).toString(29) must return "-1"'); +assert.sameValue((new Number(1)).toString(29), "1", '(new Number(1)).toString(29) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(29) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(29) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(29), + "NaN", + '(new Number(Number.NaN)).toString(29) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(29) !== "0") { - throw new Test262Error('#2: (new Number()).toString(29) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(29), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(29) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(29) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(29) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(29) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(29) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(29) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(29) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(29) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(29) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(29) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(29) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(29) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(29) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(29), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(29) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T28.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T28.js index dd534aa0eb0f..5151f803ce54 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T28.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T28.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T28 description: radix is 30 ---*/ +assert.sameValue(Number.prototype.toString(30), "0", 'Number.prototype.toString(30) must return "0"'); +assert.sameValue((new Number()).toString(30), "0", '(new Number()).toString(30) must return "0"'); +assert.sameValue((new Number(0)).toString(30), "0", '(new Number(0)).toString(30) must return "0"'); +assert.sameValue((new Number(-1)).toString(30), "-1", '(new Number(-1)).toString(30) must return "-1"'); +assert.sameValue((new Number(1)).toString(30), "1", '(new Number(1)).toString(30) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(30) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(30) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(30), + "NaN", + '(new Number(Number.NaN)).toString(30) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(30) !== "0") { - throw new Test262Error('#2: (new Number()).toString(30) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(30), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(30) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(30) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(30) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(30) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(30) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(30) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(30) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(30) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(30) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(30) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(30) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(30) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(30) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(30), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(30) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T29.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T29.js index 4edd836fa0b1..41ae187ccea0 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T29.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T29.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T29 description: radix is 31 ---*/ +assert.sameValue(Number.prototype.toString(31), "0", 'Number.prototype.toString(31) must return "0"'); +assert.sameValue((new Number()).toString(31), "0", '(new Number()).toString(31) must return "0"'); +assert.sameValue((new Number(0)).toString(31), "0", '(new Number(0)).toString(31) must return "0"'); +assert.sameValue((new Number(-1)).toString(31), "-1", '(new Number(-1)).toString(31) must return "-1"'); +assert.sameValue((new Number(1)).toString(31), "1", '(new Number(1)).toString(31) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(31) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(31) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(31), + "NaN", + '(new Number(Number.NaN)).toString(31) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(31) !== "0") { - throw new Test262Error('#2: (new Number()).toString(31) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(31), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(31) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(31) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(31) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(31) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(31) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(31) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(31) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(31) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(31) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(31) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(31) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(31) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(31) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(31), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(31) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T30.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T30.js index 74a1aa31410b..a0b322c94a61 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T30.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T30.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T30 description: radix is 32 ---*/ +assert.sameValue(Number.prototype.toString(32), "0", 'Number.prototype.toString(32) must return "0"'); +assert.sameValue((new Number()).toString(32), "0", '(new Number()).toString(32) must return "0"'); +assert.sameValue((new Number(0)).toString(32), "0", '(new Number(0)).toString(32) must return "0"'); +assert.sameValue((new Number(-1)).toString(32), "-1", '(new Number(-1)).toString(32) must return "-1"'); +assert.sameValue((new Number(1)).toString(32), "1", '(new Number(1)).toString(32) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(32) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(32) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(32), + "NaN", + '(new Number(Number.NaN)).toString(32) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(32) !== "0") { - throw new Test262Error('#2: (new Number()).toString(32) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(32), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(32) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(32) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(32) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(32) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(32) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(32) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(32) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(32) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(32) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(32) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(32) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(32) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(32) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(32), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(32) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T31.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T31.js index e9404578b430..43ed5864b0a8 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T31.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T31.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T31 description: radix is 33 ---*/ +assert.sameValue(Number.prototype.toString(33), "0", 'Number.prototype.toString(33) must return "0"'); +assert.sameValue((new Number()).toString(33), "0", '(new Number()).toString(33) must return "0"'); +assert.sameValue((new Number(0)).toString(33), "0", '(new Number(0)).toString(33) must return "0"'); +assert.sameValue((new Number(-1)).toString(33), "-1", '(new Number(-1)).toString(33) must return "-1"'); +assert.sameValue((new Number(1)).toString(33), "1", '(new Number(1)).toString(33) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(33) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(33) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(33), + "NaN", + '(new Number(Number.NaN)).toString(33) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(33) !== "0") { - throw new Test262Error('#2: (new Number()).toString(33) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(33), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(33) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(33) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(33) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(33) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(33) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(33) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(33) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(33) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(33) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(33) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(33) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(33) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(33) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(33), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(33) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T32.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T32.js index 34b3c66c1db4..ffb7cabf2b74 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T32.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T32.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T32 description: radix is 34 ---*/ +assert.sameValue(Number.prototype.toString(34), "0", 'Number.prototype.toString(34) must return "0"'); +assert.sameValue((new Number()).toString(34), "0", '(new Number()).toString(34) must return "0"'); +assert.sameValue((new Number(0)).toString(34), "0", '(new Number(0)).toString(34) must return "0"'); +assert.sameValue((new Number(-1)).toString(34), "-1", '(new Number(-1)).toString(34) must return "-1"'); +assert.sameValue((new Number(1)).toString(34), "1", '(new Number(1)).toString(34) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(34) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(34) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(34), + "NaN", + '(new Number(Number.NaN)).toString(34) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(34) !== "0") { - throw new Test262Error('#2: (new Number()).toString(34) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(34), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(34) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(34) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(34) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(34) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(34) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(34) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(34) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(34) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(34) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(34) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(34) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(34) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(34) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(34), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(34) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T33.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T33.js index 0e5cbb8e4dc1..89e3f740bbb6 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T33.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T33.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T33 description: radix is 35 ---*/ +assert.sameValue(Number.prototype.toString(35), "0", 'Number.prototype.toString(35) must return "0"'); +assert.sameValue((new Number()).toString(35), "0", '(new Number()).toString(35) must return "0"'); +assert.sameValue((new Number(0)).toString(35), "0", '(new Number(0)).toString(35) must return "0"'); +assert.sameValue((new Number(-1)).toString(35), "-1", '(new Number(-1)).toString(35) must return "-1"'); +assert.sameValue((new Number(1)).toString(35), "1", '(new Number(1)).toString(35) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(35) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(35) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(35), + "NaN", + '(new Number(Number.NaN)).toString(35) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(35) !== "0") { - throw new Test262Error('#2: (new Number()).toString(35) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(35), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(35) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(35) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(35) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(35) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(35) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(35) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(35) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(35) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(35) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(35) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(35) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(35) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(35) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(35), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(35) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T34.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T34.js index 3733df819ec1..d80367d1ae3e 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T34.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A2_T34.js @@ -8,45 +8,28 @@ info: | es5id: 15.7.4.2_A2_T34 description: radix is 36 ---*/ +assert.sameValue(Number.prototype.toString(36), "0", 'Number.prototype.toString(36) must return "0"'); +assert.sameValue((new Number()).toString(36), "0", '(new Number()).toString(36) must return "0"'); +assert.sameValue((new Number(0)).toString(36), "0", '(new Number(0)).toString(36) must return "0"'); +assert.sameValue((new Number(-1)).toString(36), "-1", '(new Number(-1)).toString(36) must return "-1"'); +assert.sameValue((new Number(1)).toString(36), "1", '(new Number(1)).toString(36) must return "1"'); -//CHECK#1 -if (Number.prototype.toString(36) !== "0") { - throw new Test262Error('#1: Number.prototype.toString(36) === "0"'); -} +assert.sameValue( + (new Number(Number.NaN)).toString(36), + "NaN", + '(new Number(Number.NaN)).toString(36) must return "NaN"' +); -//CHECK#2 -if ((new Number()).toString(36) !== "0") { - throw new Test262Error('#2: (new Number()).toString(36) === "0"'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).toString(36), + "Infinity", + '(new Number(Number.POSITIVE_INFINITY)).toString(36) must return "Infinity"' +); -//CHECK#3 -if ((new Number(0)).toString(36) !== "0") { - throw new Test262Error('#3: (new Number(0)).toString(36) === "0"'); -} - -//CHECK#4 -if ((new Number(-1)).toString(36) !== "-1") { - throw new Test262Error('#4: (new Number(-1)).toString(36) === "-1"'); -} - -//CHECK#5 -if ((new Number(1)).toString(36) !== "1") { - throw new Test262Error('#5: (new Number(1)).toString(36) === "1"'); -} - -//CHECK#6 -if ((new Number(Number.NaN)).toString(36) !== "NaN") { - throw new Test262Error('#6: (new Number(Number.NaN)).toString(36) === "NaN"'); -} - -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).toString(36) !== "Infinity") { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(36) === "Infinity"'); -} - -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).toString(36) !== "-Infinity") { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(36) === "-Infinity"'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).toString(36), + "-Infinity", + '(new Number(Number.NEGATIVE_INFINITY)).toString(36) must return "-Infinity"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T01.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T01.js index a9d93a4ae66a..665dd2256372 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T01.js @@ -7,56 +7,48 @@ es5id: 15.7.4.2_A3_T01 description: radix is 1 ---*/ -//CHECK#1 try { var n = Number.prototype.toString(1); throw new Test262Error('#1: Number.prototype.toString(1) should throw an Error'); } catch (e) {} -//CHECK#2 try { var n = (new Number()).toString(1); throw new Test262Error('#2: (new Number()).toString(1) should throw an Error'); } catch (e) {} -//CHECK#3 try { var n = (new Number(0)).toString(1); throw new Test262Error('#3: (new Number(0)).toString(1) should throw an Error'); } catch (e) {} -//CHECK#4 try { var n = (new Number(-1)).toString(1); throw new Test262Error('#4: (new Number(-1)).toString(1) should throw an Error'); } catch (e) {} -//CHECK#5 try { var n = (new Number(1)).toString(1); throw new Test262Error('#5: (new Number(1)).toString(1) should throw an Error'); } catch (e) {} -//CHECK#6 try { var n = (new Number(Number.NaN)).toString(1); throw new Test262Error('#6: (new Number(Number.NaN)).toString(1) should throw an Error'); } catch (e) {} -//CHECK#7 try { var n = (new Number(Number.POSITIVE_INFINITY)).toString(1); throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(1) should throw an Error'); } catch (e) {} -//CHECK#8 try { var n = (new Number(Number.NEGATIVE_INFINITY)).toString(1); throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(1) should throw an Error'); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T02.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T02.js index 3a0971ed7ffb..f283f03013a2 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T02.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T02.js @@ -7,56 +7,48 @@ es5id: 15.7.4.2_A3_T02 description: radix is 37 ---*/ -//CHECK#1 try { var n = Number.prototype.toString(37); throw new Test262Error('#1: Number.prototype.toString(37) should throw an Error'); } catch (e) {} -//CHECK#2 try { var n = (new Number()).toString(37); throw new Test262Error('#2: (new Number()).toString(37) should throw an Error'); } catch (e) {} -//CHECK#3 try { var n = (new Number(0)).toString(37); throw new Test262Error('#3: (new Number(0)).toString(37) should throw an Error'); } catch (e) {} -//CHECK#4 try { var n = (new Number(-1)).toString(37); throw new Test262Error('#4: (new Number(-1)).toString(37) should throw an Error'); } catch (e) {} -//CHECK#5 try { var n = (new Number(1)).toString(37); throw new Test262Error('#5: (new Number(1)).toString(37) should throw an Error'); } catch (e) {} -//CHECK#6 try { var n = (new Number(Number.NaN)).toString(37); throw new Test262Error('#6: (new Number(Number.NaN)).toString(37) should throw an Error'); } catch (e) {} -//CHECK#7 try { var n = (new Number(Number.POSITIVE_INFINITY)).toString(37); throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(37) should throw an Error'); } catch (e) {} -//CHECK#8 try { var n = (new Number(Number.NEGATIVE_INFINITY)).toString(37); throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(37) should throw an Error'); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T03.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T03.js index ffab4de1365f..7da1bd7e60ef 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T03.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T03.js @@ -7,56 +7,48 @@ es5id: 15.7.4.2_A3_T03 description: radix is null value ---*/ -//CHECK#1 try { var n = Number.prototype.toString(null); throw new Test262Error('#1: Number.prototype.toString(null) should throw an Error'); } catch (e) {} -//CHECK#2 try { var n = (new Number()).toString(null); throw new Test262Error('#2: (new Number()).toString(null) should throw an Error'); } catch (e) {} -//CHECK#3 try { var n = (new Number(0)).toString(null); throw new Test262Error('#3: (new Number(0)).toString(null) should throw an Error'); } catch (e) {} -//CHECK#4 try { var n = (new Number(-1)).toString(null); throw new Test262Error('#4: (new Number(-1)).toString(null) should throw an Error'); } catch (e) {} -//CHECK#5 try { var n = (new Number(1)).toString(null); throw new Test262Error('#5: (new Number(1)).toString(null) should throw an Error'); } catch (e) {} -//CHECK#6 try { var n = (new Number(Number.NaN)).toString(null); throw new Test262Error('#6: (new Number(Number.NaN)).toString(null) should throw an Error'); } catch (e) {} -//CHECK#7 try { var n = (new Number(Number.POSITIVE_INFINITY)).toString(null); throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(null) should throw an Error'); } catch (e) {} -//CHECK#8 try { var n = (new Number(Number.NEGATIVE_INFINITY)).toString(null); throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(null) should throw an Error'); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T04.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T04.js index 63080b578938..d88823a15252 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T04.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A3_T04.js @@ -7,56 +7,48 @@ es5id: 15.7.4.2_A3_T04 description: radix is 0 ---*/ -//CHECK#1 try { var n = Number.prototype.toString(0); throw new Test262Error('#1: Number.prototype.toString(0) should throw an Error'); } catch (e) {} -//CHECK#2 try { var n = (new Number()).toString(0); throw new Test262Error('#2: (new Number()).toString(0) should throw an Error'); } catch (e) {} -//CHECK#3 try { var n = (new Number(0)).toString(0); throw new Test262Error('#3: (new Number(0)).toString(0) should throw an Error'); } catch (e) {} -//CHECK#4 try { var n = (new Number(-1)).toString(0); throw new Test262Error('#4: (new Number(-1)).toString(0) should throw an Error'); } catch (e) {} -//CHECK#5 try { var n = (new Number(1)).toString(0); throw new Test262Error('#5: (new Number(1)).toString(0) should throw an Error'); } catch (e) {} -//CHECK#6 try { var n = (new Number(Number.NaN)).toString(0); throw new Test262Error('#6: (new Number(Number.NaN)).toString(0) should throw an Error'); } catch (e) {} -//CHECK#7 try { var n = (new Number(Number.POSITIVE_INFINITY)).toString(0); throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).toString(0) should throw an Error'); } catch (e) {} -//CHECK#8 try { var n = (new Number(Number.NEGATIVE_INFINITY)).toString(0); throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).toString(0) should throw an Error'); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T01.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T01.js index 0267bbd7e3f4..bdbbf070bc3a 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T01.js @@ -10,7 +10,6 @@ es5id: 15.7.4.2_A4_T01 description: transferring to the String objects ---*/ -//CHECK#1 try { var s1 = new String(); s1.toString = Number.prototype.toString; @@ -18,12 +17,9 @@ try { throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = new String(); s2.myToString = Number.prototype.toString; @@ -31,9 +27,7 @@ try { throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T02.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T02.js index 910ad3a911df..3ecdb8123267 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T02.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T02.js @@ -10,7 +10,6 @@ es5id: 15.7.4.2_A4_T02 description: transferring to the Boolean objects ---*/ -//CHECK#1 try { var s1 = new Boolean(); s1.toString = Number.prototype.toString; @@ -18,12 +17,9 @@ try { throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = new Boolean(); s2.myToString = Number.prototype.toString; @@ -31,9 +27,7 @@ try { throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T03.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T03.js index f3cfd89fb143..d1c96dd6b3ce 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T03.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T03.js @@ -10,7 +10,6 @@ es5id: 15.7.4.2_A4_T03 description: transferring to the Date objects ---*/ -//CHECK#1 try { var s1 = new Date(); s1.toString = Number.prototype.toString; @@ -18,12 +17,9 @@ try { throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = new Date(); s2.myToString = Number.prototype.toString; @@ -31,9 +27,7 @@ try { throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T04.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T04.js index 3c9c7f68f919..028c78e8a219 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T04.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T04.js @@ -10,7 +10,6 @@ es5id: 15.7.4.2_A4_T04 description: transferring to the Object objects ---*/ -//CHECK#1 try { var s1 = new Object(); s1.toString = Number.prototype.toString; @@ -18,12 +17,9 @@ try { throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = new Object(); s2.myToString = Number.prototype.toString; @@ -31,9 +27,7 @@ try { throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T05.js b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T05.js index 25f9bb6fb2cd..14fa638ed102 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T05.js +++ b/js/src/tests/test262/built-ins/Number/prototype/toString/S15.7.4.2_A4_T05.js @@ -10,7 +10,6 @@ es5id: 15.7.4.2_A4_T05 description: transferring to the other objects ---*/ -//CHECK#1 try { var s1 = { x: 1 @@ -20,12 +19,9 @@ try { throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = { x: 1 @@ -35,9 +31,7 @@ try { throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.toString on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T01.js b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T01.js index 5d14a6b4fb2d..22f0607f0d0e 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T01.js @@ -6,47 +6,28 @@ info: Number.prototype.valueOf() returns this number value es5id: 15.7.4.4_A1_T01 description: Call without argument ---*/ +assert.sameValue(Number.prototype.valueOf(), 0, 'Number.prototype.valueOf() must return 0'); +assert.sameValue((new Number()).valueOf(), 0, '(new Number()).valueOf() must return 0'); +assert.sameValue((new Number(0)).valueOf(), 0, '(new Number(0)).valueOf() must return 0'); +assert.sameValue((new Number(-1)).valueOf(), -1, '(new Number(-1)).valueOf() must return -1'); +assert.sameValue((new Number(1)).valueOf(), 1, '(new Number(1)).valueOf() must return 1'); -//CHECK#1 -if (Number.prototype.valueOf() !== 0) { - throw new Test262Error('#1: Number.prototype.valueOf() === 0'); -} - -//CHECK#2 -if ((new Number()).valueOf() !== 0) { - throw new Test262Error('#2: (new Number()).valueOf() === 0'); -} - -//CHECK#3 -if ((new Number(0)).valueOf() !== 0) { - throw new Test262Error('#3: (new Number(0)).valueOf() === 0'); -} - -//CHECK#4 -if ((new Number(-1)).valueOf() !== -1) { - throw new Test262Error('#4: (new Number(-1)).valueOf() === -1'); -} - -//CHECK#5 -if ((new Number(1)).valueOf() !== 1) { - throw new Test262Error('#5: (new Number(1)).valueOf() === 1'); -} - -//CHECK#6 assert.sameValue( new Number(NaN).valueOf(), NaN, - "NaN" + 'new Number(NaN).valueOf() returns NaN' ); -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).valueOf() !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).valueOf() === Infinity'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).valueOf(), + Number.POSITIVE_INFINITY, + '(new Number(Number.POSITIVE_INFINITY)).valueOf() returns Number.POSITIVE_INFINITY' +); -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).valueOf() !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).valueOf() === -Infinity'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).valueOf(), + Number.NEGATIVE_INFINITY, + '(new Number(Number.NEGATIVE_INFINITY)).valueOf() returns Number.NEGATIVE_INFINITY' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T02.js b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T02.js index a06e25725508..0b5df3987c3c 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T02.js +++ b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T02.js @@ -6,47 +6,28 @@ info: Number.prototype.valueOf() returns this number value es5id: 15.7.4.4_A1_T02 description: calling with argument ---*/ +assert.sameValue(Number.prototype.valueOf("argument"), 0, 'Number.prototype.valueOf("argument") must return 0'); +assert.sameValue((new Number()).valueOf("argument"), 0, '(new Number()).valueOf("argument") must return 0'); +assert.sameValue((new Number(0)).valueOf("argument"), 0, '(new Number(0)).valueOf("argument") must return 0'); +assert.sameValue((new Number(-1)).valueOf("argument"), -1, '(new Number(-1)).valueOf("argument") must return -1'); +assert.sameValue((new Number(1)).valueOf("argument"), 1, '(new Number(1)).valueOf("argument") must return 1'); -//CHECK#1 -if (Number.prototype.valueOf("argument") !== 0) { - throw new Test262Error('#1: Number.prototype.valueOf("argument") === 0'); -} - -//CHECK#2 -if ((new Number()).valueOf("argument") !== 0) { - throw new Test262Error('#2: (new Number()).valueOf("argument") === 0'); -} - -//CHECK#3 -if ((new Number(0)).valueOf("argument") !== 0) { - throw new Test262Error('#3: (new Number(0)).valueOf("argument") === 0'); -} - -//CHECK#4 -if ((new Number(-1)).valueOf("argument") !== -1) { - throw new Test262Error('#4: (new Number(-1)).valueOf("argument") === -1'); -} - -//CHECK#5 -if ((new Number(1)).valueOf("argument") !== 1) { - throw new Test262Error('#5: (new Number(1)).valueOf("argument") === 1'); -} - -//CHECK#6 assert.sameValue( new Number(NaN).valueOf("argument"), NaN, - "NaN" + 'new Number(NaN).valueOf("argument") returns NaN' ); -//CHECK#7 -if ((new Number(Number.POSITIVE_INFINITY)).valueOf("argument") !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#7: (new Number(Number.POSITIVE_INFINITY)).valueOf("argument") === Infinity'); -} +assert.sameValue( + (new Number(Number.POSITIVE_INFINITY)).valueOf("argument"), + Number.POSITIVE_INFINITY, + '(new Number(Number.POSITIVE_INFINITY)).valueOf("argument") returns Number.POSITIVE_INFINITY' +); -//CHECK#8 -if ((new Number(Number.NEGATIVE_INFINITY)).valueOf("argument") !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#8: (new Number(Number.NEGATIVE_INFINITY)).valueOf("argument") === -Infinity'); -} +assert.sameValue( + (new Number(Number.NEGATIVE_INFINITY)).valueOf("argument"), + Number.NEGATIVE_INFINITY, + '(new Number(Number.NEGATIVE_INFINITY)).valueOf("argument") returns Number.NEGATIVE_INFINITY' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T01.js b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T01.js index 1547f2618168..15d7fa57b7c1 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T01.js +++ b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T01.js @@ -10,7 +10,6 @@ es5id: 15.7.4.4_A2_T01 description: transferring to the String objects ---*/ -//CHECK#1 try { var s1 = new String(); s1.valueOf = Number.prototype.valueOf; @@ -18,12 +17,9 @@ try { throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = new String(); s2.myValueOf = Number.prototype.valueOf; @@ -31,9 +27,7 @@ try { throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T02.js b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T02.js index 799664f43598..94c443f74d13 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T02.js +++ b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T02.js @@ -10,7 +10,6 @@ es5id: 15.7.4.4_A2_T02 description: transferring to the Boolean objects ---*/ -//CHECK#1 try { var s1 = new Boolean(); s1.valueOf = Number.prototype.valueOf; @@ -18,12 +17,9 @@ try { throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = new Boolean(); s2.myValueOf = Number.prototype.valueOf; @@ -31,9 +27,7 @@ try { throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T03.js b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T03.js index b10a5b0a5ac3..3363f17cd879 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T03.js +++ b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T03.js @@ -10,7 +10,6 @@ es5id: 15.7.4.4_A2_T03 description: transferring to the Date objects ---*/ -//CHECK#1 try { var s1 = new Date(); s1.valueOf = Number.prototype.valueOf; @@ -18,12 +17,9 @@ try { throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = new Date(); s2.myValueOf = Number.prototype.valueOf; @@ -31,9 +27,7 @@ try { throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T04.js b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T04.js index a3b8da5d0641..3eee5d784b6a 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T04.js +++ b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T04.js @@ -10,7 +10,6 @@ es5id: 15.7.4.4_A2_T04 description: transferring to the Object objects ---*/ -//CHECK#1 try { var s1 = new Object(); s1.valueOf = Number.prototype.valueOf; @@ -18,12 +17,9 @@ try { throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = new Object(); s2.myValueOf = Number.prototype.valueOf; @@ -31,9 +27,7 @@ try { throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T05.js b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T05.js index 005a0633271c..504b834cb7c6 100644 --- a/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T05.js +++ b/js/src/tests/test262/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T05.js @@ -10,7 +10,6 @@ es5id: 15.7.4.4_A2_T05 description: transferring to the other objects ---*/ -//CHECK#1 try { var s1 = { x: 1 @@ -20,12 +19,9 @@ try { throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#1: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 try { var s2 = { x: 1 @@ -35,9 +31,7 @@ try { throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError'); } catch (e) { - if (!(e instanceof TypeError)) { - throw new Test262Error('#2: Number.prototype.valueOf on not a Number object should throw TypeError, not ' + e); - } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T1.js index 4a68e580c890..1e158a9f5411 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T1.js @@ -13,24 +13,30 @@ var __obj = Object(null); var n__obj = new Object(null); -if (__obj.toString() !== n__obj.toString()) { - throw new Test262Error('#1'); -} +assert.sameValue( + __obj.toString(), + n__obj.toString(), + '__obj.toString() must return the same value returned by n__obj.toString()' +); -if (__obj.constructor !== n__obj.constructor) { - throw new Test262Error('#2'); -} +assert.sameValue( + __obj.constructor, + n__obj.constructor, + 'The value of __obj.constructor is expected to equal the value of n__obj.constructor' +); -if (__obj.prototype !== n__obj.prototype) { - throw new Test262Error('#3'); -} +assert.sameValue( + __obj.prototype, + n__obj.prototype, + 'The value of __obj.prototype is expected to equal the value of n__obj.prototype' +); -if (__obj.toLocaleString() !== n__obj.toLocaleString()) { - throw new Test262Error('#4'); -} +assert.sameValue( + __obj.toLocaleString(), + n__obj.toLocaleString(), + '__obj.toLocaleString() must return the same value returned by n__obj.toLocaleString()' +); -if (typeof __obj !== typeof n__obj) { - throw new Test262Error('#5'); -} +assert.sameValue(typeof __obj, typeof n__obj, 'The value of `typeof __obj` is expected to be typeof n__obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T2.js index 14b1154a3772..a3733f515c7b 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T2.js @@ -16,24 +16,30 @@ var __obj = Object(void 0); var n__obj = new Object(void 0); -if (__obj.toString() !== n__obj.toString()) { - throw new Test262Error('#1'); -} +assert.sameValue( + __obj.toString(), + n__obj.toString(), + '__obj.toString() must return the same value returned by n__obj.toString()' +); -if (__obj.constructor !== n__obj.constructor) { - throw new Test262Error('#2'); -} +assert.sameValue( + __obj.constructor, + n__obj.constructor, + 'The value of __obj.constructor is expected to equal the value of n__obj.constructor' +); -if (__obj.prototype !== n__obj.prototype) { - throw new Test262Error('#3'); -} +assert.sameValue( + __obj.prototype, + n__obj.prototype, + 'The value of __obj.prototype is expected to equal the value of n__obj.prototype' +); -if (__obj.toLocaleString() !== n__obj.toLocaleString()) { - throw new Test262Error('#4'); -} +assert.sameValue( + __obj.toLocaleString(), + n__obj.toLocaleString(), + '__obj.toLocaleString() must return the same value returned by n__obj.toLocaleString()' +); -if (typeof __obj !== typeof n__obj) { - throw new Test262Error('#5'); -} +assert.sameValue(typeof __obj, typeof n__obj, 'The value of `typeof __obj` is expected to be typeof n__obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T3.js index 1ac131fc08d6..6a658e1848e7 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T3.js @@ -13,24 +13,30 @@ var __obj = Object(); var n__obj = new Object(); -if (__obj.toString() !== n__obj.toString()) { - throw new Test262Error('#1'); -} +assert.sameValue( + __obj.toString(), + n__obj.toString(), + '__obj.toString() must return the same value returned by n__obj.toString()' +); -if (__obj.constructor !== n__obj.constructor) { - throw new Test262Error('#2'); -} +assert.sameValue( + __obj.constructor, + n__obj.constructor, + 'The value of __obj.constructor is expected to equal the value of n__obj.constructor' +); -if (__obj.prototype !== n__obj.prototype) { - throw new Test262Error('#3'); -} +assert.sameValue( + __obj.prototype, + n__obj.prototype, + 'The value of __obj.prototype is expected to equal the value of n__obj.prototype' +); -if (__obj.toLocaleString() !== n__obj.toLocaleString()) { - throw new Test262Error('#4'); -} +assert.sameValue( + __obj.toLocaleString(), + n__obj.toLocaleString(), + '__obj.toLocaleString() must return the same value returned by n__obj.toLocaleString()' +); -if (typeof __obj !== typeof n__obj) { - throw new Test262Error('#5'); -} +assert.sameValue(typeof __obj, typeof n__obj, 'The value of `typeof __obj` is expected to be typeof n__obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T4.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T4.js index 9bb348c47c06..9be54489f68e 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T4.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T4.js @@ -13,24 +13,30 @@ var __obj = Object(undefined); var n__obj = new Object(undefined); -if (__obj.toString() !== n__obj.toString()) { - throw new Test262Error('#1'); -} +assert.sameValue( + __obj.toString(), + n__obj.toString(), + '__obj.toString() must return the same value returned by n__obj.toString()' +); -if (__obj.constructor !== n__obj.constructor) { - throw new Test262Error('#2'); -} +assert.sameValue( + __obj.constructor, + n__obj.constructor, + 'The value of __obj.constructor is expected to equal the value of n__obj.constructor' +); -if (__obj.prototype !== n__obj.prototype) { - throw new Test262Error('#3'); -} +assert.sameValue( + __obj.prototype, + n__obj.prototype, + 'The value of __obj.prototype is expected to equal the value of n__obj.prototype' +); -if (__obj.toLocaleString() !== n__obj.toLocaleString()) { - throw new Test262Error('#4'); -} +assert.sameValue( + __obj.toLocaleString(), + n__obj.toLocaleString(), + '__obj.toLocaleString() must return the same value returned by n__obj.toLocaleString()' +); -if (typeof __obj !== typeof n__obj) { - throw new Test262Error('#5'); -} +assert.sameValue(typeof __obj, typeof n__obj, 'The value of `typeof __obj` is expected to be typeof n__obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T5.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T5.js index 8eb8b7c5dbe0..5bb54930ac3c 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T5.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A1_T5.js @@ -13,25 +13,31 @@ var __obj = Object(x); var n__obj = new Object(x); -if (__obj.toString() !== n__obj.toString()) { - throw new Test262Error('#1'); -} +assert.sameValue( + __obj.toString(), + n__obj.toString(), + '__obj.toString() must return the same value returned by n__obj.toString()' +); -if (__obj.constructor !== n__obj.constructor) { - throw new Test262Error('#2'); -} +assert.sameValue( + __obj.constructor, + n__obj.constructor, + 'The value of __obj.constructor is expected to equal the value of n__obj.constructor' +); -if (__obj.prototype !== n__obj.prototype) { - throw new Test262Error('#3'); -} +assert.sameValue( + __obj.prototype, + n__obj.prototype, + 'The value of __obj.prototype is expected to equal the value of n__obj.prototype' +); -if (__obj.toLocaleString() !== n__obj.toLocaleString()) { - throw new Test262Error('#4'); -} +assert.sameValue( + __obj.toLocaleString(), + n__obj.toLocaleString(), + '__obj.toLocaleString() must return the same value returned by n__obj.toLocaleString()' +); -if (typeof __obj !== typeof n__obj) { - throw new Test262Error('#5'); -} +assert.sameValue(typeof __obj, typeof n__obj, 'The value of `typeof __obj` is expected to be typeof n__obj'); var x; diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T1.js index 96d2fe3e980d..6cc3f59c79e1 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T1.js @@ -11,26 +11,13 @@ description: Calling Object function with boolean argument value var bool = true; -if (typeof bool !== 'boolean') { - throw new Test262Error('#1: bool should be boolean primitive'); -} +assert.sameValue(typeof bool, 'boolean', 'The value of `typeof bool` is expected to be "boolean"'); var obj = Object(bool); -if (obj.constructor !== Boolean) { - throw new Test262Error('#2: Object(true) returns ToObject(true)'); -} - -if (typeof obj !== "object") { - throw new Test262Error('#3: Object(true) returns ToObject(true)'); -} - -if (!obj) { - throw new Test262Error('#4: Object(true) returns ToObject(true)'); -} - -if (obj === true) { - throw new Test262Error('#5: Object(true) returns ToObject(true)'); -} +assert.sameValue(obj.constructor, Boolean, 'The value of obj.constructor is expected to equal the value of Boolean'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert(!!obj, 'The value of !!obj is expected to be true'); +assert.notSameValue(obj, true, 'The value of obj is not true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T10.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T10.js index 496ee9c003d3..a37953c1014c 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T10.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T10.js @@ -11,18 +11,13 @@ description: Calling Object function with array of numbers as argument value var arr = [1, 2, 3]; -//CHECK#1 -if (typeof arr !== 'object') { - throw new Test262Error('#1: arr = [1,2,3] is NOT an object'); -} +assert.sameValue(typeof arr, 'object', 'The value of `typeof arr` is expected to be "object"'); var n_obj = Object(arr); arr.push(4); -//CHECK#2 -if ((n_obj !== arr) || (n_obj[3] !== 4)) { - throw new Test262Error('#2: Object([1,2,3]) returns ToObject([1,2,3])'); -} +assert.sameValue(n_obj, arr, 'The value of n_obj is expected to equal the value of arr'); +assert.sameValue(n_obj[3], 4, 'The value of n_obj[3] is expected to be 4'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T11.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T11.js index d05037814ad3..a3e7fdd4dd73 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T11.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T11.js @@ -8,24 +8,19 @@ info: | es5id: 15.2.1.1_A2_T11 description: Calling Object function with function declaration as argument value ---*/ - -//CHECK#1 -if (typeof func !== 'undefined') { - throw new Test262Error('#1: function expression can\'t be declarated'); -} +assert.sameValue(typeof func, 'undefined', 'The value of `typeof func` is expected to be "undefined"'); var n_obj = Object(function func() { return 1; }); -//CHECK#2 -if ((n_obj.constructor !== Function) || (n_obj() !== 1)) { - throw new Test262Error('#2: Object(function func(){return 1;}) returns function'); -} +assert.sameValue( + n_obj.constructor, + Function, + 'The value of n_obj.constructor is expected to equal the value of Function' +); +assert.sameValue(n_obj(), 1, 'n_obj() must return 1') +assert.sameValue(typeof func, 'undefined', 'The value of `typeof func` is expected to be "undefined"'); -//CHECK#3 -if (typeof func !== 'undefined') { - throw new Test262Error('#3: function expression can\'t be declarated'); -} reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T12.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T12.js index 9a4a27b037ba..2fbd10b1e162 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T12.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T12.js @@ -13,20 +13,9 @@ var obj = Object(1.1 * ([].length + { q: 1 }["q"])); -//CHECK#2 -if (typeof obj !== "object") { - throw new Test262Error('#2: Object(expression) returns ToObject(expression)'); -} - -//CHECK#3 -if (obj.constructor !== Number) { - throw new Test262Error('#3: Object(expression) returns ToObject(expression)'); -} - -//CHECK#4 -if ((obj != 1.1) || (obj === 1.1)) { - throw new Test262Error('#4: Object(expression) returns ToObject(expression)'); -} -// +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert.sameValue(obj.constructor, Number, 'The value of obj.constructor is expected to equal the value of Number'); +assert(obj == 1.1, 'The result of evaluating (obj == 1.1) is expected to be true'); +assert.notSameValue(obj, 1.1, 'The value of obj is not 1.1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T13.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T13.js index e24b591fcfa4..549c4e54deca 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T13.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T13.js @@ -11,24 +11,9 @@ description: Calling Object function with boolean expression as argument value var obj = Object((1 === 1) && (!false)); -//CHECK#1 -if (obj.constructor !== Boolean) { - throw new Test262Error('#1: Object(expression) returns ToObject(expression)'); -} - -//CHECK#1.1 -if (typeof obj !== "object") { - throw new Test262Error('#1.1: Object(expression) returns ToObject(expression)'); -} - -//CHECK#2 -if (!(obj)) { - throw new Test262Error('#2: Object(expression) returns ToObject(expression)'); -} - -//CHECK#3 -if (obj === true) { - throw new Test262Error('#3: Object(expression) returns ToObject(expression)'); -} +assert.sameValue(obj.constructor, Boolean, 'The value of obj.constructor is expected to equal the value of Boolean'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert(!!obj, 'The value of !!obj is expected to be true'); +assert.notSameValue(obj, true, 'The value of obj is not true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T14.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T14.js index 34802e67e7b1..034a21f361fb 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T14.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T14.js @@ -13,19 +13,9 @@ description: > var obj = Object("" + 1); -//CHECK#2 -if (obj.constructor !== String) { - throw new Test262Error('#2: Object(expression) returns ToObject(expression)'); -} - -//CHECK#3 -if (typeof obj !== "object") { - throw new Test262Error('#3: Object(expression) returns ToObject(expression)'); -} - -//CHECK#4 -if ((obj != "1") || (obj === "1")) { - throw new Test262Error('#4: Object(expression) returns ToObject(expression)'); -} +assert.sameValue(obj.constructor, String, 'The value of obj.constructor is expected to equal the value of String'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert(obj == "1", 'The result of evaluating (obj == "1") is expected to be true'); +assert.notSameValue(obj, "1", 'The value of obj is not "1"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T2.js index c00e5e2a620b..9d71aa778442 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T2.js @@ -11,27 +11,14 @@ description: Calling Object function with number argument value var num = 1.1; -// CHECK#1 -if (typeof num !== 'number') { - throw new Test262Error('#1: num = 1.1 should be Number primitive'); -} +assert.sameValue(typeof num, 'number', 'The value of `typeof num` is expected to be "number"'); var obj = Object(num); -//CHECK#2 -if (typeof obj !== "object") { - throw new Test262Error('#2: Object(1.1) returns ToObject(1.1)'); -} +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert.sameValue(obj.constructor, Number, 'The value of obj.constructor is expected to equal the value of Number'); -//CHECK#3 -if (obj.constructor !== Number) { - throw new Test262Error('#3: Object(1.1) returns ToObject(1.1)'); -} - -//CHECK#4 -if ((obj != 1.1) || (obj === 1.1)) { - throw new Test262Error('#4: Object(1.1) returns ToObject(1.1)'); -} -// +assert(obj == 1.1, 'The result of evaluating (obj == 1.1) is expected to be true'); +assert.notSameValue(obj, 1.1, 'The value of obj is not 1.1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T3.js index e11c00cb8074..e9cc2cc998a7 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T3.js @@ -11,26 +11,13 @@ description: Calling Object function with string argument value var str = 'Luke Skywalker'; -// CHECK#1 -if (typeof str !== 'string') { - throw new Test262Error('#1: "Luke Skywalker" should be a String primitive'); -} +assert.sameValue(typeof str, 'string', 'The value of `typeof str` is expected to be "string"'); var obj = Object(str); -//CHECK#2 -if (obj.constructor !== String) { - throw new Test262Error('#2: Object("Luke Skywalker") returns ToObject("Luke Skywalker")'); -} - -//CHECK#3 -if (typeof obj !== "object") { - throw new Test262Error('#3: Object("Luke Skywalker") returns ToObject("Luke Skywalker")'); -} - -//CHECK#4 -if ((obj != "Luke Skywalker") || (obj === "Luke Skywalker")) { - throw new Test262Error('#4: Object("Luke Skywalker") returns ToObject("Luke Skywalker")'); -} +assert.sameValue(obj.constructor, String, 'The value of obj.constructor is expected to equal the value of String'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert(obj == "Luke Skywalker", 'The result of evaluating (obj == "Luke Skywalker") is expected to be true'); +assert.notSameValue(obj, "Luke Skywalker", 'The value of obj is not "Luke Skywalker"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T4.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T4.js index ebd6228bb93d..0f9bb6c1207a 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T4.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T4.js @@ -13,16 +13,11 @@ var obj = { flag: true }; -//CHECK#1 -if (typeof(obj) !== 'object') { - throw new Test262Error('#1: obj = {flag:true} should be an Object'); -} +assert.sameValue(typeof(obj), 'object', 'The value of `typeof(obj)` is expected to be "object"'); var n_obj = Object(obj); -//CHECK#2 -if ((n_obj !== obj) || (!(n_obj['flag']))) { - throw new Test262Error('#2: Object({flag:true}) returns ToObject({flag:true})'); -} +assert.sameValue(n_obj, obj, 'The value of n_obj is expected to equal the value of obj'); +assert(!!n_obj['flag'], 'The value of !!n_obj["flag"] is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T5.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T5.js index 23add604e744..d06be6c43533 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T5.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T5.js @@ -11,22 +11,11 @@ description: Calling Object function with NaN argument value var num = NaN; -// CHECK#1 -if (typeof num !== 'number') { - throw new Test262Error('#1: num = NaN should have number type'); -} +assert.sameValue(typeof num, 'number', 'The value of `typeof num` is expected to be "number"'); var obj = Object(num); -//CHECK#2 -if (obj.constructor !== Number) { - throw new Test262Error('#2: Object(NaN) returns ToObject(NaN)'); -} - -//CHECK#3 -if (typeof obj !== "object") { - throw new Test262Error('#2: Object(NaN) returns ToObject(NaN)'); -} -// +assert.sameValue(obj.constructor, Number, 'The value of obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T6.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T6.js index eecbadf06677..62f3b3f1ebeb 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T6.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T6.js @@ -11,26 +11,13 @@ description: Calling Object function with Infinity argument value var num = Infinity; -// CHECK#1 -if (typeof num !== 'number') { - throw new Test262Error('#1: num = Infinity should be a Number primitive'); -} +assert.sameValue(typeof num, 'number', 'The value of `typeof num` is expected to be "number"'); var obj = Object(num); -//CHECK#2 -if (obj.constructor !== Number) { - throw new Test262Error('#2: Object(Infinity) returns ToObject(Infinity)'); -} - -//CHECK#3 -if (typeof obj !== "object") { - throw new Test262Error('#3: Object(Infinity) returns ToObject(Infinity)'); -} - -//CHECK#4 -if ((obj != Infinity) || (obj === Infinity)) { - throw new Test262Error('#4: Object(Infinity) returns ToObject(Infinity)'); -} +assert.sameValue(obj.constructor, Number, 'The value of obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert(obj == Infinity, 'The result of evaluating (obj == Infinity) is expected to be true'); +assert.notSameValue(obj, Infinity, 'The value of obj is expected to not equal ``Infinity``'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T7.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T7.js index 976b398b8ac1..72310316ab25 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T7.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T7.js @@ -11,26 +11,13 @@ description: Calling Object function with empty string argument value var str = ''; -// CHECK#1 -if (typeof(str) !== 'string') { - throw new Test262Error('#1: "" is NOT a String'); -} +assert.sameValue(typeof(str), 'string', 'The value of `typeof(str)` is expected to be "string"'); var obj = Object(str); -//CHECK#2 -if (obj.constructor !== String) { - throw new Test262Error('#2: Object("") returns ToObject("")'); -} - -//CHECK#3 -if (typeof obj !== "object") { - throw new Test262Error('#3: Object("") returns ToObject("")'); -} - -//CHECK#4 -if ((obj != "") || (obj === "")) { - throw new Test262Error('#4: Object("") returns ToObject("")'); -} +assert.sameValue(obj.constructor, String, 'The value of obj.constructor is expected to equal the value of String'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert(obj == "", 'The result of evaluating (obj == "") is expected to be true'); +assert.notSameValue(obj, "", 'The value of obj is not ""'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T8.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T8.js index e47a7772be98..dc2c0df58385 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T8.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T8.js @@ -13,16 +13,11 @@ var func = function() { return 1; }; -//CHECK#1 -if (typeof func !== 'function') { - throw new Test262Error('#1: func = function(){return 1;} is NOT an function'); -} +assert.sameValue(typeof func, 'function', 'The value of `typeof func` is expected to be "function"'); var n_obj = Object(func); -//CHECK#2 -if ((n_obj !== func) || (n_obj() !== 1)) { - throw new Test262Error('#2: Object(function) returns function'); -} +assert.sameValue(n_obj, func, 'The value of n_obj is expected to equal the value of func'); +assert.sameValue(n_obj(), 1, 'n_obj() must return 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T9.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T9.js index b9a02786a0e3..374606d9f968 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T9.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A2_T9.js @@ -10,21 +10,15 @@ description: > Calling Object function with function argument value. The function is declared ---*/ - -//CHECK#1 -if (typeof func !== 'function') { - throw new Test262Error('#1: func = function(){return 1;} is NOT an function'); +function func() { + return 1; } +assert.sameValue(typeof func, 'function', 'The value of `typeof func` is expected to be "function"'); + var n_obj = Object(func); -//CHECK#2 -if ((n_obj !== func) || (n_obj() !== 1)) { - throw new Test262Error('#2: Object(function) returns function'); -} - -function func() { - return 1; -}; +assert.sameValue(n_obj, func, 'The value of n_obj is expected to equal the value of func'); +assert.sameValue(n_obj(), 1, 'n_obj() must return 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T1.js index 008d88fe0c67..d28f44cad072 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T1.js @@ -11,19 +11,11 @@ description: Creating an object with "Object(1,2,3)" var obj = Object(1, 2, 3); -//CHECK#1 -if (obj.constructor !== Number) { - throw new Test262Error('#1: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} +assert.sameValue(obj.constructor, Number, 'The value of obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); -//CHECK#2 -if (typeof obj !== "object") { - throw new Test262Error('#2: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} +assert(obj == 1, 'The result of evaluating (obj == 1) is expected to be true'); +assert.notSameValue(obj, 1, 'The value of obj is not 1'); -//CHECK#3 -if ((obj != 1) || (obj === 1)) { - throw new Test262Error('3#: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T2.js index 50bb54a9c2a5..478cd3f9b3e9 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T2.js @@ -11,14 +11,7 @@ description: Creating an object with "Object(null,2,3)" var obj = Object(null, 2, 3); -//CHECK#1 -if (obj.constructor !== Object) { - throw new Test262Error('#1: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} - -//CHECK#2 -if (typeof obj !== "object") { - throw new Test262Error('#2: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} +assert.sameValue(obj.constructor, Object, 'The value of obj.constructor is expected to equal the value of Object'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T3.js index 11c94fac9bf4..28099a7e6818 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.1.1_A3_T3.js @@ -11,19 +11,11 @@ description: Creating an object with "Object((null,2,3),1,2)" var obj = Object((null, 2, 3), 1, 2); -//CHECK#1 -if (obj.constructor !== Number) { - throw new Test262Error('#1: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} +assert.sameValue(obj.constructor, Number, 'The value of obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); -//CHECK#2 -if (typeof obj !== "object") { - throw new Test262Error('#2: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} +assert(obj == 3, 'The result of evaluating (obj == 3) is expected to be true'); +assert.notSameValue(obj, 3, 'The value of obj is not 3'); -//CHECK#3 -if ((obj != 3) || (obj === 3)) { - throw new Test262Error('3#: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T1.js index 9ff608bcaa83..bc38af1a0b32 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T1.js @@ -16,30 +16,21 @@ description: Creating new Object() and checking its properties var obj = new Object(); -// CHECK#0 -if (obj === undefined) { - throw new Test262Error('#0: new Object() return the newly created native object.'); -} +assert.notSameValue(obj, undefined, 'The value of obj is expected to not equal ``undefined``'); +assert.sameValue(obj.constructor, Object, 'The value of obj.constructor is expected to equal the value of Object'); -// CHECK#1 -if (obj.constructor !== Object) { - throw new Test262Error('#1: new Object() create a new native ECMAScript object'); -} +assert( + !!Object.prototype.isPrototypeOf(obj), + 'The value of !!Object.prototype.isPrototypeOf(obj) is expected to be true' +); -// CHECK#2 -if (!(Object.prototype.isPrototypeOf(obj))) { - throw new Test262Error('#2: when new Object() calls the [[Prototype]] property of the newly constructed object is set to the Object prototype object.'); -} - -// CHECK#3 var to_string_result = '[object ' + 'Object' + ']'; -if (obj.toString() !== to_string_result) { - throw new Test262Error('#3: when new Object() calls the [[Class]] property of the newly constructed object is set to "Object".'); -} +assert.sameValue(obj.toString(), to_string_result, 'obj.toString() returns to_string_result'); -// CHECK#4 -if (obj.valueOf().toString() !== to_string_result.toString()) { - throw new Test262Error('#4: when new Object() calls the newly constructed object has no [[Value]] property.'); -} +assert.sameValue( + obj.valueOf().toString(), + to_string_result.toString(), + 'obj.valueOf().toString() must return the same value returned by to_string_result.toString()' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T2.js index 3e93d5285723..a97791e32e18 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T2.js @@ -17,30 +17,21 @@ description: Creating new Object(void 0) and checking its properties //var foo = void 0; var obj = new Object(void 0); -// CHECK#0 -if (obj === undefined) { - throw new Test262Error('#0: new Object(undefined) return the newly created native object.'); -} +assert.notSameValue(obj, undefined, 'The value of obj is expected to not equal ``undefined``'); +assert.sameValue(obj.constructor, Object, 'The value of obj.constructor is expected to equal the value of Object'); -// CHECK#1 -if (obj.constructor !== Object) { - throw new Test262Error('#1: new Object(undefined) create a new native ECMAScript object'); -} +assert( + !!Object.prototype.isPrototypeOf(obj), + 'The value of !!Object.prototype.isPrototypeOf(obj) is expected to be true' +); -// CHECK#2 -if (!(Object.prototype.isPrototypeOf(obj))) { - throw new Test262Error('#2: when new Object(undefined) calls the [[Prototype]] property of the newly constructed object is set to the Object prototype object.'); -} - -// CHECK#3 var to_string_result = '[object ' + 'Object' + ']'; -if (obj.toString() !== to_string_result) { - throw new Test262Error('#3: when new Object(undefined) calls the [[Class]] property of the newly constructed object is set to "Object".'); -} +assert.sameValue(obj.toString(), to_string_result, 'obj.toString() returns to_string_result'); -// CHECK#4 -if (obj.valueOf().toString() !== to_string_result.toString()) { - throw new Test262Error('#4: when new Object(undefined) calls the newly constructed object has no [[Value]] property.'); -} +assert.sameValue( + obj.valueOf().toString(), + to_string_result.toString(), + 'obj.valueOf().toString() must return the same value returned by to_string_result.toString()' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T3.js index 0b94780f925f..d6fb4d495aeb 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T3.js @@ -16,30 +16,21 @@ description: Creating new Object(null) and checking its properties var obj = new Object(null); -// CHECK#0 -if (obj === undefined) { - throw new Test262Error('#0: new Object(null) return the newly created native object.'); -} +assert.notSameValue(obj, undefined, 'The value of obj is expected to not equal ``undefined``'); +assert.sameValue(obj.constructor, Object, 'The value of obj.constructor is expected to equal the value of Object'); -// CHECK#1 -if (obj.constructor !== Object) { - throw new Test262Error('#1: new Object(null) create a new native ECMAScript object'); -} +assert( + !!Object.prototype.isPrototypeOf(obj), + 'The value of !!Object.prototype.isPrototypeOf(obj) is expected to be true' +); -// CHECK#2 -if (!(Object.prototype.isPrototypeOf(obj))) { - throw new Test262Error('#2: when new Object(null) calls the [[Prototype]] property of the newly constructed object is set to the Object prototype object.'); -} - -// CHECK#3 var to_string_result = '[object ' + 'Object' + ']'; -if (obj.toString() !== to_string_result) { - throw new Test262Error('#3: when new Object(null) calls the [[Class]] property of the newly constructed object is set to "Object".'); -} +assert.sameValue(obj.toString(), to_string_result, 'obj.toString() returns to_string_result'); -// CHECK#4 -if (obj.valueOf().toString() !== to_string_result.toString()) { - throw new Test262Error('#4: when new Object(null) calls the newly constructed object has no [[Value]] property.'); -} +assert.sameValue( + obj.valueOf().toString(), + to_string_result.toString(), + 'obj.valueOf().toString() must return the same value returned by to_string_result.toString()' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T4.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T4.js index 51a515c2f8aa..1818c8816419 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T4.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T4.js @@ -16,30 +16,21 @@ description: Creating new Object(undefined) and checking its properties var obj = new Object(undefined); -// CHECK#0 -if (obj === undefined) { - throw new Test262Error('#0: new Object(undefined) return the newly created native object.'); -} +assert.notSameValue(obj, undefined, 'The value of obj is expected to not equal ``undefined``'); +assert.sameValue(obj.constructor, Object, 'The value of obj.constructor is expected to equal the value of Object'); -// CHECK#1 -if (obj.constructor !== Object) { - throw new Test262Error('#1: new Object(undefined) create a new native ECMAScript object'); -} +assert( + !!Object.prototype.isPrototypeOf(obj), + 'The value of !!Object.prototype.isPrototypeOf(obj) is expected to be true' +); -// CHECK#2 -if (!(Object.prototype.isPrototypeOf(obj))) { - throw new Test262Error('#2: when new Object(undefined) calls the [[Prototype]] property of the newly constructed object is set to the Object prototype object.'); -} - -// CHECK#3 var to_string_result = '[object ' + 'Object' + ']'; -if (obj.toString() !== to_string_result) { - throw new Test262Error('#3: when new Object(undefined) calls the [[Class]] property of the newly constructed object is set to "Object".'); -} +assert.sameValue(obj.toString(), to_string_result, 'obj.toString() returns to_string_result'); -// CHECK#4 -if (obj.valueOf().toString() !== to_string_result.toString()) { - throw new Test262Error('#4: when new Object(undefined) calls the newly constructed object has no [[Value]] property.'); -} +assert.sameValue( + obj.valueOf().toString(), + to_string_result.toString(), + 'obj.valueOf().toString() must return the same value returned by to_string_result.toString()' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T5.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T5.js index 3317b37349c1..a0ca5c6cb8db 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T5.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A1_T5.js @@ -18,31 +18,22 @@ description: > var obj = new Object(x); -// CHECK#0 -if (obj === undefined) { - throw new Test262Error('#0: new Object(undefined) return the newly created native object.'); -} +assert.notSameValue(obj, undefined, 'The value of obj is expected to not equal ``undefined``'); +assert.sameValue(obj.constructor, Object, 'The value of obj.constructor is expected to equal the value of Object'); -// CHECK#1 -if (obj.constructor !== Object) { - throw new Test262Error('#1: new Object(undefined) create a new native ECMAScript object'); -} +assert( + !!Object.prototype.isPrototypeOf(obj), + 'The value of !!Object.prototype.isPrototypeOf(obj) is expected to be true' +); -// CHECK#2 -if (!(Object.prototype.isPrototypeOf(obj))) { - throw new Test262Error('#2: when new Object(undefined) calls the [[Prototype]] property of the newly constructed object is set to the Object prototype object.'); -} - -// CHECK#3 var to_string_result = '[object ' + 'Object' + ']'; -if (obj.toString() !== to_string_result) { - throw new Test262Error('#3: when new Object(undefined) calls the [[Class]] property of the newly constructed object is set to "Object".'); -} +assert.sameValue(obj.toString(), to_string_result, 'obj.toString() returns to_string_result'); -// CHECK#4 -if (obj.valueOf().toString() !== to_string_result.toString()) { - throw new Test262Error('#4: when new Object(undefined) calls the newly constructed object has no [[Value]] property.'); -} +assert.sameValue( + obj.valueOf().toString(), + to_string_result.toString(), + 'obj.valueOf().toString() must return the same value returned by to_string_result.toString()' +); var x; diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T1.js index 2f6412068707..85eaa078b478 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T1.js @@ -15,14 +15,7 @@ var obj = { var n_obj = new Object(obj); -//CHECK#1 -if (n_obj !== obj) { - throw new Test262Error('#1: When the Object constructor is called and if the value is an Object simply value returns.'); -} - -//CHECK#2 -if (n_obj['prop'] !== 1) { - throw new Test262Error('#2: When the Object constructor is called and if the value is an Object simply value returns.'); -} +assert.sameValue(n_obj, obj, 'The value of n_obj is expected to equal the value of obj'); +assert.sameValue(n_obj['prop'], 1, 'The value of n_obj["prop"] is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T2.js index f0b8f40f33d4..d1628d2ff69f 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T2.js @@ -15,15 +15,7 @@ var func = function() { var n_obj = new Object(func); -//CHECK#1 -if (n_obj !== func) { - throw new Test262Error('#1: When the Object constructor is called and if the value is an Object simply value returns'); -} - -//CHECK#2 -if (n_obj() !== 1) { - throw new Test262Error('When the Object constructor is called and if the value is an Object simply value returns'); -} -// +assert.sameValue(n_obj, func, 'The value of n_obj is expected to equal the value of func'); +assert.sameValue(n_obj(), 1, 'n_obj() must return 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T3.js index 8349ecb3e677..a570252dbb7c 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T3.js @@ -15,14 +15,7 @@ var n_obj = new Object(arr); arr.push(4); -//CHECK#1 -if (n_obj !== arr) { - throw new Test262Error('#1: When the Object constructor is called and if the value is an Object simply value returns.'); -} - -//CHECK#2 -if (n_obj[3] !== 4) { - throw new Test262Error('#2: When the Object constructor is called and if the value is an Object simply value returns.'); -} +assert.sameValue(n_obj, arr, 'The value of n_obj is expected to equal the value of arr'); +assert.sameValue(n_obj[3], 4, 'The value of n_obj[3] is expected to be 4'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T5.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T5.js index 108c60c87591..b46e79e97b14 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T5.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T5.js @@ -13,14 +13,8 @@ var obj = new Date(1978, 3); var n_obj = new Object(obj); -//CHECK#1 -if (n_obj !== obj) { - throw new Test262Error('#1: When the Object constructor is called and if the value is an Object simply value returns.'); -} - -//CHECK#2 -if ((n_obj.getFullYear() !== 1978) || (n_obj.getMonth() !== 3)) { - throw new Test262Error('#2: When the Object constructor is called and if the value is an Object simply value returns.'); -} +assert.sameValue(n_obj, obj, 'The value of n_obj is expected to equal the value of obj'); +assert.sameValue(n_obj.getFullYear(), 1978, 'n_obj.getFullYear() must return 1978'); +assert.sameValue(n_obj.getMonth(), 3, 'n_obj.getMonth() must return 3'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T6.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T6.js index 09ce33258e4c..31512f3dd3c6 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T6.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T6.js @@ -11,18 +11,11 @@ description: The value is a declared function var n_obj = new Object(func); -//CHECK#1 -if (n_obj !== func) { - throw new Test262Error('#1: When the Object constructor is called and if the value is an Object simply value returns'); -} - -//CHECK#2 -if (n_obj() !== 1) { - throw new Test262Error('When the Object constructor is called and if the value is an Object simply value returns'); -} +assert.sameValue(n_obj, func, 'The value of n_obj is expected to equal the value of func'); +assert.sameValue(n_obj(), 1, 'n_obj() must return 1'); function func() { return 1; -}; +} reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T7.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T7.js index 668b9a2ba28a..0b41b080de39 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T7.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A2_T7.js @@ -8,29 +8,19 @@ info: | es5id: 15.2.2.1_A2_T7 description: The value is a function declaration ---*/ - -//CHECK#0 -if (typeof func !== 'undefined') { - throw new Test262Error('#0: function expression can\'t be declarated'); -} +assert.sameValue(typeof func, 'undefined', 'The value of `typeof func` is expected to be "undefined"'); var n_obj = new Object(function func() { return 1; }); -//CHECK#1 -if (n_obj.constructor !== Function) { - throw new Test262Error('#1: When the Object constructor is called and if the value is an Object simply value returns'); -} +assert.sameValue( + n_obj.constructor, + Function, + 'The value of n_obj.constructor is expected to equal the value of Function' +); -//CHECK#2 -if (n_obj() !== 1) { - throw new Test262Error('#2: When the Object constructor is called and if the value is an Object simply value returns'); -} - -//CHECK#3 -if (typeof func !== 'undefined') { - throw new Test262Error('#3: function expression can\'t be declarated'); -} +assert.sameValue(n_obj(), 1, 'n_obj() must return 1'); +assert.sameValue(typeof func, 'undefined', 'The value of `typeof func` is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T1.js index 5a28791e6bdb..a3f680a7c267 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T1.js @@ -11,32 +11,14 @@ description: Argument value is a nonempty string var str = 'Obi-Wan Kenobi'; -//CHECK#1 -if (typeof str !== 'string') { - throw new Test262Error('#1: "Obi-Wan Kenobi" is NOT a String'); -} +assert.sameValue(typeof str, 'string', 'The value of `typeof str` is expected to be "string"'); var n_obj = new Object(str); -//CHECK#2 -if (n_obj.constructor !== String) { - throw new Test262Error('#2: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#4 -if (n_obj != str) { - throw new Test262Error('#4: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#5 -if (n_obj === str) { - throw new Test262Error('#5: When the Object constructor is called with String argument return ToObject(string)'); -} +assert.sameValue(n_obj.constructor, String, 'The value of n_obj.constructor is expected to equal the value of String'); +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == str, 'The result of evaluating (n_obj == str) is expected to be true'); +assert.notSameValue(n_obj, str, 'The value of n_obj is expected to not equal the value of `str`'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T2.js index 21e7ba34277c..bd0a207cbcfe 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T2.js @@ -11,31 +11,13 @@ description: Argument value is an empty string var str = ''; -//CHECK#1 -if (typeof str !== 'string') { - throw new Test262Error('#1: "" is NOT a String'); -} +assert.sameValue(typeof str, 'string', 'The value of `typeof str` is expected to be "string"'); var n_obj = new Object(str); -//CHECK#2 -if (n_obj.constructor !== String) { - throw new Test262Error('#2: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#4 -if (n_obj != str) { - throw new Test262Error('#4: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#5 -if (n_obj === str) { - throw new Test262Error('#5: When the Object constructor is called with String argument return ToObject(string)'); -} +assert.sameValue(n_obj.constructor, String, 'The value of n_obj.constructor is expected to equal the value of String'); +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == str, 'The result of evaluating (n_obj == str) is expected to be true'); +assert.notSameValue(n_obj, str, 'The value of n_obj is expected to not equal the value of `str`'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T3.js index 68d67b0a7105..3aaf9fda5996 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A3_T3.js @@ -11,24 +11,9 @@ description: Argument value is sum of empty string and number var n_obj = new Object("" + 1); -//CHECK#2 -if (n_obj.constructor !== String) { - throw new Test262Error('#2: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#4 -if (n_obj != "1") { - throw new Test262Error('#4: When the Object constructor is called with String argument return ToObject(string)'); -} - -//CHECK#5 -if (n_obj === "1") { - throw new Test262Error('#5: When the Object constructor is called with String argument return ToObject(string)'); -} +assert.sameValue(n_obj.constructor, String, 'The value of n_obj.constructor is expected to equal the value of String'); +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == "1", 'The result of evaluating (n_obj == "1") is expected to be true'); +assert.notSameValue(n_obj, "1", 'The value of n_obj is not "1"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T1.js index 3a5481b4770e..85b1fde9215b 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T1.js @@ -11,31 +11,18 @@ description: Argument value is "true" var bool = true; -//CHECK#1 -if (typeof bool !== 'boolean') { - throw new Test262Error('#1: true is NOT a boolean'); -} +assert.sameValue(typeof bool, 'boolean', 'The value of `typeof bool` is expected to be "boolean"'); var n_obj = new Object(bool); -//CHECK#2 -if (n_obj.constructor !== Boolean) { - throw new Test262Error('#2: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} +assert.sameValue( + n_obj.constructor, + Boolean, + 'The value of n_obj.constructor is expected to equal the value of Boolean' +); -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} - -//CHECK#4 -if (n_obj != bool) { - throw new Test262Error('#4: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} - -//CHECK#5 -if (n_obj === bool) { - throw new Test262Error('#5: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == bool, 'The result of evaluating (n_obj == bool) is expected to be true'); +assert.notSameValue(n_obj, bool, 'The value of n_obj is expected to not equal the value of `bool`'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T2.js index 5b91daa0a98f..33006506e906 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T2.js @@ -11,31 +11,18 @@ description: Argument value is "false" var bool = false; -//CHECK#1 -if (typeof bool !== 'boolean') { - throw new Test262Error('#1: false is NOT a boolean'); -} +assert.sameValue(typeof bool, 'boolean', 'The value of `typeof bool` is expected to be "boolean"'); var n_obj = new Object(bool); -//CHECK#2 -if (n_obj.constructor !== Boolean) { - throw new Test262Error('#2: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} +assert.sameValue( + n_obj.constructor, + Boolean, + 'The value of n_obj.constructor is expected to equal the value of Boolean' +); -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} - -//CHECK#4 -if (n_obj != bool) { - throw new Test262Error('#4: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} - -//CHECK#5 -if (n_obj === bool) { - throw new Test262Error('#5: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == bool, 'The result of evaluating (n_obj == bool) is expected to be true'); +assert.notSameValue(n_obj, bool, 'The value of n_obj is expected to not equal the value of `bool`'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T3.js index d209a188c1c0..8163612b6434 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A4_T3.js @@ -11,24 +11,14 @@ description: Argument value is boolean expression var n_obj = new Object((1 === 1) && !(false)); -//CHECK#2 -if (n_obj.constructor !== Boolean) { - throw new Test262Error('#2: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} +assert.sameValue( + n_obj.constructor, + Boolean, + 'The value of n_obj.constructor is expected to equal the value of Boolean' +); -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} - -//CHECK#4 -if (n_obj != true) { - throw new Test262Error('#4: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} - -//CHECK#5 -if (n_obj === true) { - throw new Test262Error('#5: When the Object constructor is called with Boolean argument return ToObject(boolean)'); -} +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == true, 'The result of evaluating (n_obj == true) is expected to be true'); +assert.notSameValue(n_obj, true, 'The value of n_obj is not true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T1.js index 917f655c2949..0c1693d0fae4 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T1.js @@ -11,31 +11,13 @@ description: Argument value is any number var num = 1.0; -//CHECK#1 -if (typeof num !== 'number') { - throw new Test262Error('#1: 1.0 is NOT a number'); -} +assert.sameValue(typeof num, 'number', 'The value of `typeof num` is expected to be "number"'); var n_obj = new Object(num); -//CHECK#2 -if (n_obj.constructor !== Number) { - throw new Test262Error('#2: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#4 -if (n_obj != num) { - throw new Test262Error('#4: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#5 -if (n_obj === num) { - throw new Test262Error('#5: When the Object constructor is called with Number argument return ToObject(number)'); -} +assert.sameValue(n_obj.constructor, Number, 'The value of n_obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == num, 'The result of evaluating (n_obj == num) is expected to be true'); +assert.notSameValue(n_obj, num, 'The value of n_obj is expected to not equal the value of `num`'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T2.js index 329a238fa81c..6641b1445895 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T2.js @@ -11,21 +11,11 @@ description: Argument value is NaN var num = NaN; -//CHECK#1 -if (typeof num !== 'number') { - throw new Test262Error('#1: NaN is NOT a number'); -} +assert.sameValue(typeof num, 'number', 'The value of `typeof num` is expected to be "number"'); var n_obj = new Object(num); -//CHECK#2 -if (n_obj.constructor !== Number) { - throw new Test262Error('#2: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with Number argument return ToObject(number)'); -} +assert.sameValue(n_obj.constructor, Number, 'The value of n_obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T3.js index 79a32a5ad49a..8da44336bdcf 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T3.js @@ -11,31 +11,13 @@ description: Argument value is Infinity var num = Infinity; -//CHECK#1 -if (typeof num !== 'number') { - throw new Test262Error('#1: Infinity is NOT a number'); -} +assert.sameValue(typeof num, 'number', 'The value of `typeof num` is expected to be "number"'); var n_obj = new Object(num); -//CHECK#2 -if (n_obj.constructor !== Number) { - throw new Test262Error('#2: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#4 -if (n_obj != num) { - throw new Test262Error('#4: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#5 -if (n_obj === num) { - throw new Test262Error('#5: When the Object constructor is called with Number argument return ToObject(number)'); -} +assert.sameValue(n_obj.constructor, Number, 'The value of n_obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == num, 'The result of evaluating (n_obj == num) is expected to be true'); +assert.notSameValue(n_obj, num, 'The value of n_obj is expected to not equal the value of `num`'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T4.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T4.js index 81e61d2aff77..96121103bc3e 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T4.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A5_T4.js @@ -13,24 +13,9 @@ var n_obj = new Object(2 * ([].length + { q: 1 }["q"])); -//CHECK#2 -if (n_obj.constructor !== Number) { - throw new Test262Error('#2: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#3 -if (typeof n_obj !== 'object') { - throw new Test262Error('#3: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#4 -if (n_obj != 2) { - throw new Test262Error('#4: When the Object constructor is called with Number argument return ToObject(number)'); -} - -//CHECK#5 -if (n_obj === 2) { - throw new Test262Error('#5: When the Object constructor is called with Number argument return ToObject(number)'); -} +assert.sameValue(n_obj.constructor, Number, 'The value of n_obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof n_obj, 'object', 'The value of `typeof n_obj` is expected to be "object"'); +assert(n_obj == 2, 'The result of evaluating (n_obj == 2) is expected to be true'); +assert.notSameValue(n_obj, 2, 'The value of n_obj is not 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T1.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T1.js index 55c4b63ddb42..3a4ed97de17e 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T1.js @@ -11,19 +11,10 @@ description: Creating an object with "new Object(1,2,3)" var obj = new Object(1, 2, 3); -//CHECK#1 -if (obj.constructor !== Number) { - throw new Test262Error('#1: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} +assert.sameValue(obj.constructor, Number, 'The value of obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert(obj == 1, 'The result of evaluating (obj == 1) is expected to be true'); +assert.notSameValue(obj, 1, 'The value of obj is not 1'); -//CHECK#2 -if (typeof obj !== "object") { - throw new Test262Error('#2: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} - -//CHECK#3 -if ((obj != 1) || (obj === 1)) { - throw new Test262Error('3#: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T2.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T2.js index 4013f1a5d371..f4392011073c 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T2.js @@ -11,14 +11,7 @@ description: Creating an object with "new Object(null,2,3)" var obj = new Object(null, 2, 3); -//CHECK#1 -if (obj.constructor !== Object) { - throw new Test262Error('#1: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} - -//CHECK#2 -if (typeof obj !== "object") { - throw new Test262Error('#2: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} +assert.sameValue(obj.constructor, Object, 'The value of obj.constructor is expected to equal the value of Object'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T3.js b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T3.js index 16ef3f510197..41a1c7e2990a 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.2.1_A6_T3.js @@ -11,19 +11,9 @@ description: Creating an object with "new Object((null,2,3),2,3)" var obj = new Object((null, 2, 3), 1, 2); -//CHECK#1 -if (obj.constructor !== Number) { - throw new Test262Error('#1: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} - -//CHECK#2 -if (typeof obj !== "object") { - throw new Test262Error('#2: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} - -//CHECK#3 -if ((obj != 3) || (obj === 3)) { - throw new Test262Error('3#: Since Object as a function calling is the same as function calling list of arguments can appears in braces;'); -} +assert.sameValue(obj.constructor, Number, 'The value of obj.constructor is expected to equal the value of Number'); +assert.sameValue(typeof obj, "object", 'The value of `typeof obj` is expected to be "object"'); +assert(obj == 3, 'The result of evaluating (obj == 3) is expected to be true'); +assert.notSameValue(obj, 3, 'The value of obj is not 3'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.3_A1.js b/js/src/tests/test262/built-ins/Object/S15.2.3_A1.js index 3bc946ae5511..f553b2a0d961 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.3_A1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.3_A1.js @@ -6,9 +6,9 @@ info: The Object constructor has the property "prototype" es5id: 15.2.3_A1 description: Checking existence of the property "prototype" ---*/ - -if (!Object.hasOwnProperty("prototype")) { - throw new Test262Error('#1: The Object constructor has the property "prototype"'); -} +assert( + !!Object.hasOwnProperty("prototype"), + 'The value of !!Object.hasOwnProperty("prototype") is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.3_A2.js b/js/src/tests/test262/built-ins/Object/S15.2.3_A2.js index 6a0bf9bec3d7..bd599bccece1 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.3_A2.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.3_A2.js @@ -8,10 +8,9 @@ info: | es5id: 15.2.3_A2 description: Checking Function.prototype.isPrototypeOf(Object) ---*/ - -// CHECK# -if (!(Function.prototype.isPrototypeOf(Object))) { - throw new Test262Error('#1: the value of the internal [[Prototype]] property of the Object constructor is the Function prototype object.'); -} +assert( + !!Function.prototype.isPrototypeOf(Object), + 'The value of !!Function.prototype.isPrototypeOf(Object) is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2.3_A3.js b/js/src/tests/test262/built-ins/Object/S15.2.3_A3.js index b4b0f69b1a1a..68f5620efdd0 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2.3_A3.js +++ b/js/src/tests/test262/built-ins/Object/S15.2.3_A3.js @@ -6,15 +6,11 @@ info: Object constructor has length property whose value is 1 es5id: 15.2.3_A3 description: Checking Object.length ---*/ +assert( + !!Object.hasOwnProperty("length"), + 'The value of !!Object.hasOwnProperty("length") is expected to be true' +); -//CHECK#1 -if (!Object.hasOwnProperty("length")) { - throw new Test262Error('#1: The Object constructor has the property "length"'); -} - -//CHECK#2 -if (Object.length !== 1) { - throw new Test262Error('#2: Object.length property value should be 1'); -} +assert.sameValue(Object.length, 1, 'The value of Object.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S15.2_A1.js b/js/src/tests/test262/built-ins/Object/S15.2_A1.js index db7bdb514c2f..83271fdafb00 100644 --- a/js/src/tests/test262/built-ins/Object/S15.2_A1.js +++ b/js/src/tests/test262/built-ins/Object/S15.2_A1.js @@ -11,8 +11,6 @@ var obj = Object; var thisobj = this.Object; -if (obj !== thisobj) { - throw new Test262Error('Object is the property of global'); -} +assert.sameValue(obj, thisobj, 'The value of obj is expected to equal the value of thisobj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S9.9_A3.js b/js/src/tests/test262/built-ins/Object/S9.9_A3.js index 2fc4a2c1e9bc..fe5b431133e1 100644 --- a/js/src/tests/test262/built-ins/Object/S9.9_A3.js +++ b/js/src/tests/test262/built-ins/Object/S9.9_A3.js @@ -8,35 +8,22 @@ info: | es5id: 9.9_A3 description: Trying to convert from Boolean to Object ---*/ +assert.sameValue(Object(true).valueOf(), true, 'Object(true).valueOf() must return true'); +assert.sameValue(typeof Object(true), "object", 'The value of `typeof Object(true)` is expected to be "object"'); -// CHECK#1 -if (Object(true).valueOf() !== true) { - throw new Test262Error('#1: Object(true).valueOf() === true. Actual: ' + (Object(true).valueOf())); -} +assert.sameValue( + Object(true).constructor.prototype, + Boolean.prototype, + 'The value of Object(true).constructor.prototype is expected to equal the value of Boolean.prototype' +); -// CHECK#2 -if (typeof Object(true) !== "object") { - throw new Test262Error('#2: typeof Object(true) === "object". Actual: ' + (typeof Object(true))); -} +assert.sameValue(Object(false).valueOf(), false, 'Object(false).valueOf() must return false'); +assert.sameValue(typeof Object(false), "object", 'The value of `typeof Object(false)` is expected to be "object"'); -// CHECK#3 -if (Object(true).constructor.prototype !== Boolean.prototype) { - throw new Test262Error('#3: Object(true).constructor.prototype === Boolean.prototype. Actual: ' + (Object(true).constructor.prototype)); -} - -// CHECK#4 -if (Object(false).valueOf() !== false) { - throw new Test262Error('#4: Object(false).valueOf() === false. Actual: ' + (Object(false).valueOf())); -} - -// CHECK#5 -if (typeof Object(false) !== "object") { - throw new Test262Error('#5: typeof Object(false) === "object". Actual: ' + (typeof Object(false))); -} - -// CHECK#6 -if (Object(false).constructor.prototype !== Boolean.prototype) { - throw new Test262Error('#6: Object(false).constructor.prototype === Boolean.prototype. Actual: ' + (Object(false).constructor.prototype)); -} +assert.sameValue( + Object(false).constructor.prototype, + Boolean.prototype, + 'The value of Object(false).constructor.prototype is expected to equal the value of Boolean.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S9.9_A4.js b/js/src/tests/test262/built-ins/Object/S9.9_A4.js index 35a11b79de17..495c21b43a88 100644 --- a/js/src/tests/test262/built-ins/Object/S9.9_A4.js +++ b/js/src/tests/test262/built-ins/Object/S9.9_A4.js @@ -8,170 +8,144 @@ info: | es5id: 9.9_A4 description: Converting from various numbers to Object ---*/ +assert.sameValue(Object(0).valueOf(), 0, 'Object(0).valueOf() must return 0'); +assert.sameValue(typeof Object(0), "object", 'The value of `typeof Object(0)` is expected to be "object"'); -// CHECK#1 -if (Object(0).valueOf() !== 0) { - throw new Test262Error('#1: Object(0).valueOf() === 0. Actual: ' + (Object(0).valueOf())); -} +assert.sameValue( + Object(0).constructor.prototype, + Number.prototype, + 'The value of Object(0).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#2 -if (typeof Object(0) !== "object") { - throw new Test262Error('#2: typeof Object(0) === "object". Actual: ' + (typeof Object(0))); -} +assert.sameValue(Object(-0).valueOf(), -0, 'Object(-0).valueOf() must return -0'); +assert.sameValue(typeof Object(-0), "object", 'The value of `typeof Object(-0)` is expected to be "object"'); -// CHECK#3 -if (Object(0).constructor.prototype !== Number.prototype) { - throw new Test262Error('#3: Object(0).constructor.prototype === Number.prototype. Actual: ' + (Object(0).constructor.prototype)); -} +assert.sameValue( + Object(-0).constructor.prototype, + Number.prototype, + 'The value of Object(-0).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#4 -if (Object(-0).valueOf() !== -0) { - throw new Test262Error('#4.1: Object(-0).valueOf() === 0. Actual: ' + (Object(-0).valueOf())); -} else if (1 / Object(-0).valueOf() !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#4.2: Object(-0).valueOf() === -0. Actual: +0'); -} +assert.sameValue(Object(1).valueOf(), 1, 'Object(1).valueOf() must return 1'); +assert.sameValue(typeof Object(1), "object", 'The value of `typeof Object(1)` is expected to be "object"'); -// CHECK#5 -if (typeof Object(-0) !== "object") { - throw new Test262Error('#5: typeof Object(-0) === "object". Actual: ' + (typeof Object(-0))); -} +assert.sameValue( + Object(1).constructor.prototype, + Number.prototype, + 'The value of Object(1).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#6 -if (Object(-0).constructor.prototype !== Number.prototype) { - throw new Test262Error('#6: Object(-0).constructor.prototype === Number.prototype. Actual: ' + (Object(-0).constructor.prototype)); -} +assert.sameValue(Object(-1).valueOf(), -1, 'Object(-1).valueOf() must return -1'); +assert.sameValue(typeof Object(-1), "object", 'The value of `typeof Object(-1)` is expected to be "object"'); -// CHECK#7 -if (Object(1).valueOf() !== 1) { - throw new Test262Error('#7: Object(1).valueOf() === 1. Actual: ' + (Object(1).valueOf())); -} +assert.sameValue( + Object(-1).constructor.prototype, + Number.prototype, + 'The value of Object(-1).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#8 -if (typeof Object(1) !== "object") { - throw new Test262Error('#8: typeof Object(1) === "object". Actual: ' + (typeof Object(1))); -} +assert.sameValue( + Object(Number.MIN_VALUE).valueOf(), + Number.MIN_VALUE, + 'Object(Number.MIN_VALUE).valueOf() returns Number.MIN_VALUE' +); -// CHECK#9 -if (Object(1).constructor.prototype !== Number.prototype) { - throw new Test262Error('#9: Object(1).constructor.prototype === Number.prototype. Actual: ' + (Object(1).constructor.prototype)); -} +assert.sameValue( + typeof Object(Number.MIN_VALUE), + "object", + 'The value of `typeof Object(Number.MIN_VALUE)` is expected to be "object"' +); -// CHECK#10 -if (Object(-1).valueOf() !== -1) { - throw new Test262Error('#10: Object(-1).valueOf() === -1. Actual: ' + (Object(-1).valueOf())); -} +assert.sameValue( + Object(Number.MIN_VALUE).constructor.prototype, + Number.prototype, + 'The value of Object(Number.MIN_VALUE).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#11 -if (typeof Object(-1) !== "object") { - throw new Test262Error('#11: typeof Object(-1) === "object". Actual: ' + (typeof Object(-1))); -} +assert.sameValue( + Object(Number.MAX_VALUE).valueOf(), + Number.MAX_VALUE, + 'Object(Number.MAX_VALUE).valueOf() returns Number.MAX_VALUE' +); -// CHECK#12 -if (Object(-1).constructor.prototype !== Number.prototype) { - throw new Test262Error('#12: Object(-1).constructor.prototype === Number.prototype. Actual: ' + (Object(-1).constructor.prototype)); -} +assert.sameValue( + typeof Object(Number.MAX_VALUE), + "object", + 'The value of `typeof Object(Number.MAX_VALUE)` is expected to be "object"' +); -// CHECK#13 -if (Object(Number.MIN_VALUE).valueOf() !== Number.MIN_VALUE) { - throw new Test262Error('#13: Object(Number.MIN_VALUE).valueOf() === Number.MIN_VALUE. Actual: ' + (Object(Number.MIN_VALUE).valueOf())); -} +assert.sameValue( + Object(Number.MAX_VALUE).constructor.prototype, + Number.prototype, + 'The value of Object(Number.MAX_VALUE).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#14 -if (typeof Object(Number.MIN_VALUE) !== "object") { - throw new Test262Error('#14: typeof Object(Number.MIN_VALUE) === "object". Actual: ' + (typeof Object(Number.MIN_VALUE))); -} +assert.sameValue( + Object(Number.POSITIVE_INFINITY).valueOf(), + Number.POSITIVE_INFINITY, + 'Object(Number.POSITIVE_INFINITY).valueOf() returns Number.POSITIVE_INFINITY' +); -// CHECK#15 -if (Object(Number.MIN_VALUE).constructor.prototype !== Number.prototype) { - throw new Test262Error('#15: Object(Number.MIN_VALUE).constructor.prototype === Number.prototype. Actual: ' + (Object(Number.MIN_VALUE).constructor.prototype)); -} +assert.sameValue( + typeof Object(Number.POSITIVE_INFINITY), + "object", + 'The value of `typeof Object(Number.POSITIVE_INFINITY)` is expected to be "object"' +); -// CHECK#16 -if (Object(Number.MAX_VALUE).valueOf() !== Number.MAX_VALUE) { - throw new Test262Error('#16: Object(Number.MAX_VALUE).valueOf() === Number.MAX_VALUE. Actual: ' + (Object(Number.MAX_VALUE).valueOf())); -} +assert.sameValue( + Object(Number.POSITIVE_INFINITY).constructor.prototype, + Number.prototype, + 'The value of Object(Number.POSITIVE_INFINITY).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#17 -if (typeof Object(Number.MAX_VALUE) !== "object") { - throw new Test262Error('#17: typeof Object(Number.MAX_VALUE) === "object". Actual: ' + (typeof Object(Number.MAX_VALUE))); -} +assert.sameValue( + Object(Number.NEGATIVE_INFINITY).valueOf(), + Number.NEGATIVE_INFINITY, + 'Object(Number.NEGATIVE_INFINITY).valueOf() returns Number.NEGATIVE_INFINITY' +); -// CHECK#18 -if (Object(Number.MAX_VALUE).constructor.prototype !== Number.prototype) { - throw new Test262Error('#18: Object(Number.MAX_VALUE).constructor.prototype === Number.prototype. Actual: ' + (Object(Number.MAX_VALUE).constructor.prototype)); -} +assert.sameValue( + typeof Object(Number.NEGATIVE_INFINITY), + "object", + 'The value of `typeof Object(Number.NEGATIVE_INFINITY)` is expected to be "object"' +); -// CHECK#19 -if (Object(Number.POSITIVE_INFINITY).valueOf() !== Number.POSITIVE_INFINITY) { - throw new Test262Error('#19: Object(Number.POSITIVE_INFINITY).valueOf() === Number.POSITIVE_INFINITY. Actual: ' + (Object(Number.POSITIVE_INFINITY).valueOf())); -} +assert.sameValue( + Object(Number.NEGATIVE_INFINITY).constructor.prototype, + Number.prototype, + 'The value of Object(Number.NEGATIVE_INFINITY).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#20 -if (typeof Object(Number.POSITIVE_INFINITY) !== "object") { - throw new Test262Error('#20: typeof Object(Number.POSITIVE_INFINITY) === "object". Actual: ' + (typeof Object(Number.POSITIVE_INFINITY))); -} +assert.sameValue(Object(NaN).valueOf(), NaN, 'Object(NaN).valueOf() returns NaN'); -// CHECK#21 -if (Object(Number.POSITIVE_INFINITY).constructor.prototype !== Number.prototype) { - throw new Test262Error('#21: Object(Number.POSITIVE_INFINITY).constructor.prototype === Number.prototype. Actual: ' + (Object(Number.POSITIVE_INFINITY).constructor.prototype)); -} +assert.sameValue( + typeof Object(Number.NaN), + "object", + 'The value of `typeof Object(Number.NaN)` is expected to be "object"' +); -// CHECK#22 -if (Object(Number.NEGATIVE_INFINITY).valueOf() !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#22: Object(Number.NEGATIVE_INFINITY).valueOf() === Number.NEGATIVE_INFINITY. Actual: ' + (Object(Number.NEGATIVE_INFINITY).valueOf())); -} +assert.sameValue( + Object(Number.NaN).constructor.prototype, + Number.prototype, + 'The value of Object(Number.NaN).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#23 -if (typeof Object(Number.NEGATIVE_INFINITY) !== "object") { - throw new Test262Error('#23: typeof Object(Number.NEGATIVE_INFINITY) === "object". Actual: ' + (typeof Object(Number.NEGATIVE_INFINITY))); -} +assert.sameValue(Object(1.2345).valueOf(), 1.2345, 'Object(1.2345).valueOf() must return 1.2345'); +assert.sameValue(typeof Object(1.2345), "object", 'The value of `typeof Object(1.2345)` is expected to be "object"'); -// CHECK#24 -if (Object(Number.NEGATIVE_INFINITY).constructor.prototype !== Number.prototype) { - throw new Test262Error('#24: Object(Number.NEGATIVE_INFINITY).constructor.prototype === Number.prototype. Actual: ' + (Object(Number.NEGATIVE_INFINITY).constructor.prototype)); -} +assert.sameValue( + Object(1.2345).constructor.prototype, + Number.prototype, + 'The value of Object(1.2345).constructor.prototype is expected to equal the value of Number.prototype' +); -// CHECK#25 -assert.sameValue(Object(NaN).valueOf(), NaN, "Object(NaN).valueOf()"); +assert.sameValue(Object(-1.2345).valueOf(), -1.2345, 'Object(-1.2345).valueOf() must return -1.2345'); +assert.sameValue(typeof Object(-1.2345), "object", 'The value of `typeof Object(-1.2345)` is expected to be "object"'); -// CHECK#26 -if (typeof Object(Number.NaN) !== "object") { - throw new Test262Error('#26: typeof Object(Number.NaN) === "object". Actual: ' + (typeof Object(Number.NaN))); -} - -// CHECK#27 -if (Object(Number.NaN).constructor.prototype !== Number.prototype) { - throw new Test262Error('#27: Object(Number.NaN).constructor.prototype === Number.prototype. Actual: ' + (Object(Number.NaN).constructor.prototype)); -} - -// CHECK#28 -if (Object(1.2345).valueOf() !== 1.2345) { - throw new Test262Error('#28: Object(1.2345).valueOf() === 1.2345. Actual: ' + (Object(1.2345).valueOf())); -} - -// CHECK#29 -if (typeof Object(1.2345) !== "object") { - throw new Test262Error('#29: typeof Object(1.2345) === "object". Actual: ' + (typeof Object(1.2345))); -} - -// CHECK#30 -if (Object(1.2345).constructor.prototype !== Number.prototype) { - throw new Test262Error('#30: Object(1.2345).constructor.prototype === Number.prototype. Actual: ' + (Object(1.2345).constructor.prototype)); -} - -// CHECK#31 -if (Object(-1.2345).valueOf() !== -1.2345) { - throw new Test262Error('#31: Object(-1.2345).valueOf() === -1.2345. Actual: ' + (Object(-1.2345).valueOf())); -} - -// CHECK#32 -if (typeof Object(-1.2345) !== "object") { - throw new Test262Error('#32: typeof Object(-1.2345) === "object". Actual: ' + (typeof Object(-1.2345))); -} - -// CHECK#33 -if (Object(-1.2345).constructor.prototype !== Number.prototype) { - throw new Test262Error('#33: Object(-1.2345).constructor.prototype === Number.prototype. Actual: ' + (Object(-1.2345).constructor.prototype)); -} +assert.sameValue( + Object(-1.2345).constructor.prototype, + Number.prototype, + 'The value of Object(-1.2345).constructor.prototype is expected to equal the value of Number.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S9.9_A5.js b/js/src/tests/test262/built-ins/Object/S9.9_A5.js index c547fec84384..5f130f03ed40 100644 --- a/js/src/tests/test262/built-ins/Object/S9.9_A5.js +++ b/js/src/tests/test262/built-ins/Object/S9.9_A5.js @@ -8,65 +8,59 @@ info: | es5id: 9.9_A5 description: Converting from various strings to Object ---*/ +assert.sameValue( + Object("some string").valueOf(), + "some string", + 'Object("some string").valueOf() must return "some string"' +); -// CHECK#1 -if (Object("some string").valueOf() !== "some string") { - throw new Test262Error('#1: Object("some string").valueOf() === "some string". Actual: ' + (Object("some string").valueOf())); -} +assert.sameValue( + typeof Object("some string"), + "object", + 'The value of `typeof Object("some string")` is expected to be "object"' +); -// CHECK#2 -if (typeof Object("some string") !== "object") { - throw new Test262Error('#2: typeof Object("some string") === "object". Actual: ' + (typeof Object("some string"))); -} +assert.sameValue( + Object("some string").constructor.prototype, + String.prototype, + 'The value of Object("some string").constructor.prototype is expected to equal the value of String.prototype' +); -// CHECK#3 -if (Object("some string").constructor.prototype !== String.prototype) { - throw new Test262Error('#3: Object("some string").constructor.prototype === String.prototype. Actual: ' + (Object("some string").constructor.prototype)); -} +assert.sameValue(Object("").valueOf(), "", 'Object("").valueOf() must return ""'); +assert.sameValue(typeof Object(""), "object", 'The value of `typeof Object("")` is expected to be "object"'); -// CHECK#4 -if (Object("").valueOf() !== "") { - throw new Test262Error('#4: Object("").valueOf() === false. Actual: ' + (Object("").valueOf())); -} +assert.sameValue( + Object("").constructor.prototype, + String.prototype, + 'The value of Object("").constructor.prototype is expected to equal the value of String.prototype' +); -// CHECK#5 -if (typeof Object("") !== "object") { - throw new Test262Error('#5: typeof Object("") === "object". Actual: ' + (typeof Object(""))); -} +assert.sameValue(Object("\r\t\b\n\v\f").valueOf(), "\r\t\b\n\v\f", 'Object("rtbnvf").valueOf() must return "rtbnvf"'); -// CHECK#6 -if (Object("").constructor.prototype !== String.prototype) { - throw new Test262Error('#6: Object("").constructor.prototype === String.prototype. Actual: ' + (Object("").constructor.prototype)); -} +assert.sameValue( + typeof Object("\r\t\b\n\v\f"), + "object", + 'The value of `typeof Object("rtbnvf")` is expected to be "object"' +); -// CHECK#7 -if (Object("\r\t\b\n\v\f").valueOf() !== "\r\t\b\n\v\f") { - throw new Test262Error('#7: Object("\\r\\t\\b\\n\\v\\f").valueOf() === false. Actual: ' + (Object("\r\t\b\n\v\f").valueOf())); -} +assert.sameValue( + Object("\r\t\b\n\v\f").constructor.prototype, + String.prototype, + 'The value of Object("rtbnvf").constructor.prototype is expected to equal the value of String.prototype' +); -// CHECK#8 -if (typeof Object("\r\t\b\n\v\f") !== "object") { - throw new Test262Error('#8: typeof Object("\\r\\t\\b\\n\\v\\f") === "object". Actual: ' + (typeof Object("\r\t\b\n\v\f"))); -} +assert.sameValue(Object(String(10)).valueOf(), "10", 'Object(String(10)).valueOf() must return "10"'); -// CHECK#9 -if (Object("\r\t\b\n\v\f").constructor.prototype !== String.prototype) { - throw new Test262Error('#9: Object("\\r\\t\\b\\n\\v\\f").constructor.prototype === String.prototype. Actual: ' + (Object("\r\t\b\n\v\f").constructor.prototype)); -} +assert.sameValue( + typeof Object(String(10)), + "object", + 'The value of `typeof Object(String(10))` is expected to be "object"' +); -// CHECK#10 -if (Object(String(10)).valueOf() !== "10") { - throw new Test262Error('#10: Object(String(10)).valueOf() === false. Actual: ' + (Object(String(10)).valueOf())); -} - -// CHECK#11 -if (typeof Object(String(10)) !== "object") { - throw new Test262Error('#11: typeof Object(String(10)) === "object". Actual: ' + (typeof Object(String(10)))); -} - -// CHECK#12 -if (Object(String(10)).constructor.prototype !== String.prototype) { - throw new Test262Error('#12: Object(String(10)).constructor.prototype === String.prototype. Actual: ' + (Object(String(10)).constructor.prototype)); -} +assert.sameValue( + Object(String(10)).constructor.prototype, + String.prototype, + 'The value of Object(String(10)).constructor.prototype is expected to equal the value of String.prototype' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/S9.9_A6.js b/js/src/tests/test262/built-ins/Object/S9.9_A6.js index 6645ceb7648a..ab0d260228c9 100644 --- a/js/src/tests/test262/built-ins/Object/S9.9_A6.js +++ b/js/src/tests/test262/built-ins/Object/S9.9_A6.js @@ -19,25 +19,15 @@ function MyObject(val) { var x = new MyObject(1); var y = Object(x); -// CHECK#1 -if (y.valueOf() !== x.valueOf()) { - throw new Test262Error('#1: Object(obj).valueOf() === obj.valueOf(). Actual: ' + (Object(obj).valueOf())); -} +assert.sameValue(y.valueOf(), x.valueOf(), 'y.valueOf() must return the same value returned by x.valueOf()'); +assert.sameValue(typeof y, typeof x, 'The value of `typeof y` is expected to be typeof x'); -// CHECK#2 -if (typeof y !== typeof x) { - throw new Test262Error('#2: typeof Object(obj) === typeof obj. Actual: ' + (typeof Object(obj))); -} +assert.sameValue( + y.constructor.prototype, + x.constructor.prototype, + 'The value of y.constructor.prototype is expected to equal the value of x.constructor.prototype' +); -// CHECK#3 -if (y.constructor.prototype !== x.constructor.prototype) { - throw new Test262Error('#3: Object(obj).constructor.prototype === obj.constructor.prototype. Actual: ' + (Object(obj).constructor.prototype)); -} - - -// CHECK#4 -if (y !== x) { - throw new Test262Error('#4: Object(obj) === obj'); -} +assert.sameValue(y, x, 'The value of y is expected to equal the value of x'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/assign/Source-Null-Undefined.js b/js/src/tests/test262/built-ins/Object/assign/Source-Null-Undefined.js index e5644ff84302..b2f3a877507d 100644 --- a/js/src/tests/test262/built-ins/Object/assign/Source-Null-Undefined.js +++ b/js/src/tests/test262/built-ins/Object/assign/Source-Null-Undefined.js @@ -9,6 +9,6 @@ esid: sec-object.assign var target = new Object(); var result = Object.assign(target, undefined, null); -assert.sameValue(result, target, "null and undefined should be ignored, result should be original object."); +assert.sameValue(result, target, 'The value of result is expected to equal the value of target'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/assign/Source-Number-Boolen-Symbol.js b/js/src/tests/test262/built-ins/Object/assign/Source-Number-Boolen-Symbol.js index d9c03935b9d2..60a851d5f96a 100644 --- a/js/src/tests/test262/built-ins/Object/assign/Source-Number-Boolen-Symbol.js +++ b/js/src/tests/test262/built-ins/Object/assign/Source-Number-Boolen-Symbol.js @@ -12,6 +12,6 @@ features: [Symbol] var target = new Object(); var result = Object.assign(target, 123, true, Symbol('foo')); -assert.sameValue(result, target, "Numbers, booleans, and symbols cannot have wrappers with own enumerable properties."); +assert.sameValue(result, target, 'The value of result is expected to equal the value of target'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/assign/Source-String.js b/js/src/tests/test262/built-ins/Object/assign/Source-String.js index 33f1993bf9c1..d102c60f45d0 100644 --- a/js/src/tests/test262/built-ins/Object/assign/Source-String.js +++ b/js/src/tests/test262/built-ins/Object/assign/Source-String.js @@ -9,8 +9,8 @@ esid: sec-object.assign var target = new Object(); var result = Object.assign(target, "123"); -assert.sameValue(result[0], "1", "The value should be {\"0\":\"1\"}."); -assert.sameValue(result[1], "2", "The value should be {\"1\":\"2\"}."); -assert.sameValue(result[2], "3", "The value should be {\"2\":\"3\"}."); +assert.sameValue(result[0], "1", 'The value of result[0] is expected to be "1"'); +assert.sameValue(result[1], "2", 'The value of result[1] is expected to be "2"'); +assert.sameValue(result[2], "3", 'The value of result[2] is expected to be "3"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/assign/assign-descriptor.js b/js/src/tests/test262/built-ins/Object/assign/assign-descriptor.js index e598566bbb16..5ee1c8216e33 100644 --- a/js/src/tests/test262/built-ins/Object/assign/assign-descriptor.js +++ b/js/src/tests/test262/built-ins/Object/assign/assign-descriptor.js @@ -3,8 +3,7 @@ /*--- description: Testing descriptor property of Object.assign -includes: - - propertyHelper.js +includes: [propertyHelper.js] es6id: 19.1.2.1 ---*/ diff --git a/js/src/tests/test262/built-ins/Object/defineProperties/15.2.3.7-6-a-36.js b/js/src/tests/test262/built-ins/Object/defineProperties/15.2.3.7-6-a-36.js index 3bfb09e71dab..cd1476eaea45 100644 --- a/js/src/tests/test262/built-ins/Object/defineProperties/15.2.3.7-6-a-36.js +++ b/js/src/tests/test262/built-ins/Object/defineProperties/15.2.3.7-6-a-36.js @@ -7,8 +7,7 @@ description: > Object.defineProperties - 'P' doesn't exist in 'O', test [[Configurable]] of 'P' is set as false value if absent in accessor descriptor 'desc' (8.12.9 step 4.b.i) -includes: - - propertyHelper.js +includes: [propertyHelper.js] ---*/ var obj = {}; diff --git a/js/src/tests/test262/built-ins/Object/defineProperty/S15.2.3.6_A1.js b/js/src/tests/test262/built-ins/Object/defineProperty/S15.2.3.6_A1.js index e5aa5071dd75..e57b9345ff85 100644 --- a/js/src/tests/test262/built-ins/Object/defineProperty/S15.2.3.6_A1.js +++ b/js/src/tests/test262/built-ins/Object/defineProperty/S15.2.3.6_A1.js @@ -31,9 +31,7 @@ if (typeof document !== 'undefined' && } if (!refused) { var desc = Object.getOwnPropertyDescriptor(f, 'foo'); - if (desc.get !== getter) { - throw new Test262Error('Getter on HTMLFormElement disappears'); - } + assert.sameValue(desc.get, getter, 'The value of desc.get is expected to equal the value of getter'); } } diff --git a/js/src/tests/test262/built-ins/Object/defineProperty/S15.2.3.6_A2.js b/js/src/tests/test262/built-ins/Object/defineProperty/S15.2.3.6_A2.js index 7ce3aec7b579..ea75252e6d63 100644 --- a/js/src/tests/test262/built-ins/Object/defineProperty/S15.2.3.6_A2.js +++ b/js/src/tests/test262/built-ins/Object/defineProperty/S15.2.3.6_A2.js @@ -17,8 +17,10 @@ function getter() { Object.defineProperty(base, 'foo', { get: getter }); -if (derived.hasOwnProperty('foo')) { - throw new Test262Error('Accessor properties inherit as own properties'); -} + +assert( + !derived.hasOwnProperty('foo'), + 'The value of !derived.hasOwnProperty("foo") is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-2.js b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-2.js index 8365b029c5c0..2870645c468c 100644 --- a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-2.js +++ b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-2.js @@ -4,12 +4,24 @@ /*--- es5id: 15.2.3.4-4-2 description: Object.getOwnPropertyNames returns array of property names (Object) -includes: [arrayContains.js] ---*/ var result = Object.getOwnPropertyNames(Object); -var expResult = ["getPrototypeOf", "getOwnPropertyDescriptor", "getOwnPropertyNames", "create", "defineProperty", "defineProperties", "seal", "freeze", "preventExtensions", "isSealed", "isFrozen", "isExtensible", "keys", "prototype", "length"]; -assert(arrayContains(result, expResult), 'arrayContains(result, expResult) !== true'); +assert(result.indexOf("getPrototypeOf") > -1, "getPrototypeOf"); +assert(result.indexOf("getOwnPropertyDescriptor") > -1, "getOwnPropertyDescriptor"); +assert(result.indexOf("getOwnPropertyNames") > -1, "getOwnPropertyNames"); +assert(result.indexOf("create") > -1, "create"); +assert(result.indexOf("defineProperty") > -1, "defineProperty"); +assert(result.indexOf("defineProperties") > -1, "defineProperties"); +assert(result.indexOf("seal") > -1, "seal"); +assert(result.indexOf("freeze") > -1, "freeze"); +assert(result.indexOf("preventExtensions") > -1, "preventExtensions"); +assert(result.indexOf("isSealed") > -1, "isSealed"); +assert(result.indexOf("isFrozen") > -1, "isFrozen"); +assert(result.indexOf("isExtensible") > -1, "isExtensible"); +assert(result.indexOf("keys") > -1, "keys"); +assert(result.indexOf("prototype") > -1, "prototype"); +assert(result.indexOf("length") > -1, "length"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-44.js b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-44.js index afc6047f00a5..5aaccf652c68 100644 --- a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-44.js +++ b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-44.js @@ -12,9 +12,6 @@ includes: [compareArray.js] var str = new String("abc"); str[5] = "de"; -var expected = ["0", "1", "2", "5", "length"]; -var actual = Object.getOwnPropertyNames(str); - -assert(compareArray(actual, expected), 'compareArray(actual, expected) !== true'); +assert.compareArray(Object.getOwnPropertyNames(str), ["0", "1", "2", "5", "length"]); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-49.js b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-49.js index 4b7aaca6020d..d8f23995c62b 100644 --- a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-49.js +++ b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-49.js @@ -10,9 +10,6 @@ includes: [compareArray.js] ---*/ var arr = [0, 1, 2]; -var expected = ["0", "1", "2", "length"]; -var actual = Object.getOwnPropertyNames(arr); - -assert(compareArray(actual, expected), 'compareArray(actual, expected) !== true'); +assert.compareArray(Object.getOwnPropertyNames(arr), ["0", "1", "2", "length"]); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-b-2.js b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-b-2.js index 2b78c69d6768..4317af80fc8d 100644 --- a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-b-2.js +++ b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/15.2.3.4-4-b-2.js @@ -35,9 +35,6 @@ Object.defineProperty(obj, "d", { configurable: true }); -var actual = Object.getOwnPropertyNames(obj); -var expected = ["a", "b", "c", "d"]; - -assert(compareArray(actual, expected), 'compareArray(actual, expected) !== true'); +assert.compareArray(Object.getOwnPropertyNames(obj), ["a", "b", "c", "d"]); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/S15.2.3.4_A1_T1.js b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/S15.2.3.4_A1_T1.js index 20d4a09c822f..c683929cbbdf 100644 --- a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/S15.2.3.4_A1_T1.js +++ b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/S15.2.3.4_A1_T1.js @@ -16,9 +16,7 @@ function foo() {} var names = Object.getOwnPropertyNames(foo); for (var i = 0, len = names.length; i < len; i++) { - if (!foo.hasOwnProperty(names[i])) { - throw new Test262Error('Phantom own property: ' + names[i]); - } + assert(!!foo.hasOwnProperty(names[i]), 'The value of !!foo.hasOwnProperty(names[i]) is expected to be true'); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/shell.js b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/shell.js index 40bfce343709..e69de29bb2d1 100644 --- a/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/shell.js +++ b/js/src/tests/test262/built-ins/Object/getOwnPropertyNames/shell.js @@ -1,31 +0,0 @@ -// GENERATED, DO NOT EDIT -// file: arrayContains.js -// Copyright (C) 2017 Ecma International. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -description: | - Verify that a subArray is contained within an array. -defines: [arrayContains] ----*/ - -/** - * @param {Array} array - * @param {Array} subArray - */ - -function arrayContains(array, subArray) { - var found; - for (var i = 0; i < subArray.length; i++) { - found = false; - for (var j = 0; j < array.length; j++) { - if (subArray[i] === array[j]) { - found = true; - break; - } - } - if (!found) { - return false; - } - } - return true; -} diff --git a/js/src/tests/test262/built-ins/Object/hasOwn/descriptor.js b/js/src/tests/test262/built-ins/Object/hasOwn/descriptor.js index 93422936f95c..105e9eaa10f9 100644 --- a/js/src/tests/test262/built-ins/Object/hasOwn/descriptor.js +++ b/js/src/tests/test262/built-ins/Object/hasOwn/descriptor.js @@ -4,8 +4,7 @@ /*--- esid: sec-object.hasown description: Testing descriptor property of Object.hasOwn -includes: - - propertyHelper.js +includes: [propertyHelper.js] author: Jamie Kyle features: [Object.hasOwn] ---*/ diff --git a/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A1.js b/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A1.js index e10bb50de3f8..df8799dce498 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A1.js +++ b/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A1.js @@ -13,17 +13,17 @@ verifyNotWritable(Object, "prototype", null, function() { return "shifted"; }); -//CHECK#1 -if (Object.prototype !== obj) { - throw new Test262Error('#1: the Object.prototype property has the attributes ReadOnly.'); -} +assert.sameValue(Object.prototype, obj, 'The value of Object.prototype is expected to equal the value of obj'); -//CHECK#2 try { Object.prototype(); throw new Test262Error('#2: the Object.prototype property has the attributes ReadOnly'); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A2.js b/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A2.js index 77b53ccec6f1..44dbf8dd02b6 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A2.js +++ b/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A2.js @@ -6,21 +6,21 @@ info: The Object.prototype property has the attribute DontEnum es5id: 15.2.3.1_A2 description: Checking if enumerating "Object.prototype" property fails ---*/ +assert( + !Object.propertyIsEnumerable('prototype'), + 'The value of !Object.propertyIsEnumerable("prototype") is expected to be true' +); -// CHECK#1 -if (Object.propertyIsEnumerable('prototype')) { - throw new Test262Error('#1: the Object.prototype property has the attributes DontEnum'); -} - -// CHECK#2 var cout = 0; for (var p in Object) { - if (p === "prototype") cout++; + if (p === "prototype") { + cout++; + } } -if (cout !== 0) { - throw new Test262Error('#2: the Object.prototype property has the attributes DontEnum'); -} +assert.sameValue(cout, 0, 'The value of cout is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A3.js b/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A3.js index 18bd71bb8431..a60160dccecd 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A3.js +++ b/js/src/tests/test262/built-ins/Object/prototype/S15.2.3.1_A3.js @@ -9,19 +9,19 @@ includes: [propertyHelper.js] verifyNotConfigurable(Object, "prototype"); -//CHECK#1 try { - if ((delete Object.prototype) !== false) { - throw new Test262Error('#1: Object.prototype has the attribute DontDelete'); - } + assert.sameValue(delete Object.prototype, false, 'The value of `delete Object.prototype` is expected to be false'); } catch (e) { - if (e instanceof Test262Error) throw e; - assert(e instanceof TypeError); + if (e instanceof Test262Error) { + throw e; + } + assert(e instanceof TypeError, 'The result of evaluating (e instanceof TypeError) is expected to be true'); } -//CHECK#2 if (!(Object.hasOwnProperty('prototype'))) { throw new Test262Error('#2: the Object.prototype property has the attributes DontDelete.'); } +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A1_T1.js b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A1_T1.js index 45b09496ee04..4dc07aac2f96 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A1_T1.js +++ b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A1_T1.js @@ -6,10 +6,10 @@ info: Object prototype object has not prototype es5id: 15.2.4_A1_T1 description: Checking if obtaining Object.prototype.prototype fails ---*/ - -// CHECK#1 -if (Object.prototype.prototype !== undefined) { - throw new Test262Error('#1: Object prototype has not prototype'); -} +assert.sameValue( + Object.prototype.prototype, + undefined, + 'The value of Object.prototype.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A1_T2.js b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A1_T2.js index 97c52297d458..26fa71ae3310 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A1_T2.js +++ b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A1_T2.js @@ -8,22 +8,19 @@ description: > Since the Object prototype object has not prototype, deleted toString method can not be found in prototype chain ---*/ - -//CHECK#1 -if (Object.prototype.toString() == false) { - throw new Test262Error('#1: Object prototype object has not prototype'); -} +assert.notSameValue(Object.prototype.toString(), false, 'Object.prototype.toString() must return false'); delete Object.prototype.toString; -// CHECK#2 try { Object.prototype.toString(); throw new Test262Error('#2: Object prototype object has not prototype'); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.1: delete Object.prototype.toString; Object.prototype.toString() throw a TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } // diff --git a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A2.js b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A2.js index 5dbe0f673fa3..52fd2735f74c 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A2.js +++ b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A2.js @@ -13,9 +13,6 @@ description: > var tostr = Object.prototype.toString(); -//CHECK#1 -if (tostr !== "[object Object]") { - throw new Test262Error('#1: the value of the internal [[Class]] property of Object prototype object is "Object"'); -} +assert.sameValue(tostr, "[object Object]", 'The value of tostr is expected to be "[object Object]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A3.js b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A3.js index b581c23ae5da..06c9c56c45d5 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A3.js +++ b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A3.js @@ -11,6 +11,6 @@ description: Checking if calling Object prototype as a function fails assert.throws(TypeError, function() { Object.prototype(); -}); +}, 'Object.prototype() throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A4.js b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A4.js index 3432083ba6c5..4502a1647839 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A4.js +++ b/js/src/tests/test262/built-ins/Object/prototype/S15.2.4_A4.js @@ -11,6 +11,6 @@ description: Checking if creating "new Object.prototype" fails assert.throws(TypeError, function() { new Object.prototype; -}); +}, '`new Object.prototype` throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/constructor/S15.2.4.1_A1_T1.js b/js/src/tests/test262/built-ins/Object/prototype/constructor/S15.2.4.1_A1_T1.js index cfe7dacdd00e..f22e1fc143ed 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/constructor/S15.2.4.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/Object/prototype/constructor/S15.2.4.1_A1_T1.js @@ -8,10 +8,10 @@ info: | es5id: 15.2.4.1_A1_T1 description: Checking the Object.prototype.constructor ---*/ - -//CHECK#1 -if (Object.prototype.constructor !== Object) { - throw new Test262Error('#1: The initial value of Object.prototype.constructor is the built-in Object constructor'); -} +assert.sameValue( + Object.prototype.constructor, + Object, + 'The value of Object.prototype.constructor is expected to equal the value of Object' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/constructor/S15.2.4.1_A1_T2.js b/js/src/tests/test262/built-ins/Object/prototype/constructor/S15.2.4.1_A1_T2.js index 69d612079239..c987017fde35 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/constructor/S15.2.4.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/Object/prototype/constructor/S15.2.4.1_A1_T2.js @@ -15,30 +15,16 @@ var constr = Object.prototype.constructor; var obj = new constr; -// CHECK#0 -if (obj === undefined) { - throw new Test262Error('#0: new Object() return the newly created native object.'); -} +assert.notSameValue(obj, undefined, 'The value of obj is expected to not equal ``undefined``'); +assert.sameValue(obj.constructor, Object, 'The value of obj.constructor is expected to equal the value of Object'); -// CHECK#1 -if (obj.constructor !== Object) { - throw new Test262Error('#1: new Object() create a new native ECMAScript object'); -} +assert( + !!Object.prototype.isPrototypeOf(obj), + 'The value of !!Object.prototype.isPrototypeOf(obj) is expected to be true' +); -// CHECK#2 -if (!(Object.prototype.isPrototypeOf(obj))) { - throw new Test262Error('#2: when new Object() calls the [[Prototype]] property of the newly constructed object is set to the Object prototype object.'); -} - -// CHECK#3 var to_string_result = '[object ' + 'Object' + ']'; -if (obj.toString() !== to_string_result) { - throw new Test262Error('#3: when new Object() calls the [[Class]] property of the newly constructed object is set to "Object".'); -} - -// CHECK#4 -if (obj.valueOf().toString() !== to_string_result) { - throw new Test262Error('#4: when new Object() calls the newly constructed object has no [[Value]] property.'); -} +assert.sameValue(obj.toString(), to_string_result, 'obj.toString() returns to_string_result'); +assert.sameValue(obj.valueOf().toString(), to_string_result, 'obj.valueOf().toString() returns to_string_result'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A12.js b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A12.js index 2cf0599a7fe3..d22be23a7d8a 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A12.js +++ b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A12.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Object.prototype.hasOwnProperty.call(undefined, 'foo'); -}); +}, 'Object.prototype.hasOwnProperty.call(undefined, "foo") throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A13.js b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A13.js index 8eb9750bf11f..b8f3f150acf4 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A13.js +++ b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A13.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Object.prototype.hasOwnProperty.call(null, 'foo'); -}); +}, 'Object.prototype.hasOwnProperty.call(null, "foo") throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T1.js b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T1.js index 1097d21b0a8b..72f641c6ea26 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T1.js +++ b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T1.js @@ -13,16 +13,15 @@ description: > Checking type of the Object.prototype.hasOwnProperty and the returned result ---*/ +assert.sameValue( + typeof Object.prototype.hasOwnProperty, + "function", + 'The value of `typeof Object.prototype.hasOwnProperty` is expected to be "function"' +); -//CHECK#1 -if (typeof Object.prototype.hasOwnProperty !== "function") { - throw new Test262Error('#1: hasOwnProperty method is defined'); -} - -//CHECK#2 -if (!(Object.prototype.hasOwnProperty("hasOwnProperty"))) { - throw new Test262Error('#2: hasOwnProperty method works properly'); -} -// +assert( + !!Object.prototype.hasOwnProperty("hasOwnProperty"), + 'The value of !!Object.prototype.hasOwnProperty("hasOwnProperty") is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T2.js b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T2.js index f932bc76b873..d3b6acdad588 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T2.js +++ b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T2.js @@ -11,30 +11,30 @@ info: | es5id: 15.2.4.5_A1_T2 description: Argument of the hasOwnProperty method is a custom boolean property ---*/ - -//CHECK#1 -if (typeof Object.prototype.hasOwnProperty !== "function") { - throw new Test262Error('#1: hasOwnProperty method is defined'); -} +assert.sameValue( + typeof Object.prototype.hasOwnProperty, + "function", + 'The value of `typeof Object.prototype.hasOwnProperty` is expected to be "function"' +); var obj = { the_property: true }; -//CHECK#2 -if (typeof obj.hasOwnProperty !== "function") { - throw new Test262Error('#2: hasOwnProperty method is accessed'); -} +assert.sameValue( + typeof obj.hasOwnProperty, + "function", + 'The value of `typeof obj.hasOwnProperty` is expected to be "function"' +); -//CHECK#3 -if (obj.hasOwnProperty("hasOwnProperty")) { - throw new Test262Error('#3: hasOwnProperty method works properly'); -} +assert( + !obj.hasOwnProperty("hasOwnProperty"), + 'The value of !obj.hasOwnProperty("hasOwnProperty") is expected to be true' +); -//CHECK#4 -if (!(obj.hasOwnProperty("the_property"))) { - throw new Test262Error('#4: hasOwnProperty method works properly'); -} -// +assert( + !!obj.hasOwnProperty("the_property"), + 'The value of !!obj.hasOwnProperty("the_property") is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T3.js b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T3.js index 73fa218a1859..407765b8653e 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T3.js +++ b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A1_T3.js @@ -20,24 +20,26 @@ var FACTORY = function() { var instance = new FACTORY; -//CHECK#1 -if (typeof Object.prototype.hasOwnProperty !== "function") { - throw new Test262Error('#1: hasOwnProperty method is defined'); -} +assert.sameValue( + typeof Object.prototype.hasOwnProperty, + "function", + 'The value of `typeof Object.prototype.hasOwnProperty` is expected to be "function"' +); -//CHECK#2 -if (typeof instance.hasOwnProperty !== "function") { - throw new Test262Error('#2: hasOwnProperty method is accessed'); -} +assert.sameValue( + typeof instance.hasOwnProperty, + "function", + 'The value of `typeof instance.hasOwnProperty` is expected to be "function"' +); -//CHECK#3 -if (instance.hasOwnProperty("toString")) { - throw new Test262Error('#3: hasOwnProperty method works properly'); -} +assert( + !instance.hasOwnProperty("toString"), + 'The value of !instance.hasOwnProperty("toString") is expected to be true' +); -//CHECK#4 -if (!(instance.hasOwnProperty("aproperty"))) { - throw new Test262Error('#4: hasOwnProperty method works properly'); -} +assert( + !!instance.hasOwnProperty("aproperty"), + 'The value of !!instance.hasOwnProperty("aproperty") is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A6.js b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A6.js index 71d7882ff7dd..7b1ee66e757f 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A6.js +++ b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A6.js @@ -8,11 +8,10 @@ description: > Checking if obtaining the prototype property of Object.prototype.hasOwnProperty fails ---*/ - -//CHECK#1 -if (Object.prototype.hasOwnProperty.prototype !== undefined) { - throw new Test262Error('#1: Object.prototype.hasOwnProperty has not prototype property' + Object.prototype.hasOwnProperty.prototype); -} -// +assert.sameValue( + Object.prototype.hasOwnProperty.prototype, + undefined, + 'The value of Object.prototype.hasOwnProperty.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A7.js b/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A7.js deleted file mode 100644 index ab20ea9d9c46..000000000000 --- a/js/src/tests/test262/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A7.js +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Object.prototype.hasOwnProperty can't be used as a constructor -es5id: 15.2.4.5_A7 -description: Checking if creating "new Object.prototype.hasOwnProperty" fails ----*/ - -var FACTORY = Object.prototype.hasOwnProperty; - -assert.throws(TypeError, function() { - new FACTORY; -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A10.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A10.js index 72888142f163..399bcf58a732 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A10.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A10.js @@ -11,11 +11,10 @@ description: > Object.prototype.propertyIsEnumerable.length property fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (!(Object.prototype.propertyIsEnumerable.hasOwnProperty('length'))) { - throw new Test262Error('#1: the Object.prototype.propertyIsEnumerable has length property'); -} +assert( + !!Object.prototype.propertyIsEnumerable.hasOwnProperty('length'), + 'The value of !!Object.prototype.propertyIsEnumerable.hasOwnProperty("length") is expected to be true' +); var obj = Object.prototype.propertyIsEnumerable.length; @@ -23,9 +22,12 @@ verifyNotWritable(Object.prototype.propertyIsEnumerable, "length", null, functio return "shifted"; }); -//CHECK#2 -if (Object.prototype.propertyIsEnumerable.length !== obj) { - throw new Test262Error('#2: the Object.prototype.propertyIsEnumerable length property has the attributes ReadOnly'); -} +assert.sameValue( + Object.prototype.propertyIsEnumerable.length, + obj, + 'The value of Object.prototype.propertyIsEnumerable.length is expected to equal the value of obj' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A11.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A11.js index 21242d2e809f..7f091b33b463 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A11.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A11.js @@ -6,15 +6,15 @@ info: The length property of the hasOwnProperty method is 1 es5id: 15.2.4.7_A11 description: Checking the value of Object.prototype.hasOwnProperty.length ---*/ +assert( + !!Object.prototype.propertyIsEnumerable.hasOwnProperty("length"), + 'The value of !!Object.prototype.propertyIsEnumerable.hasOwnProperty("length") is expected to be true' +); -//CHECK#1 -if (!(Object.prototype.propertyIsEnumerable.hasOwnProperty("length"))) { - throw new Test262Error('#1: the Object.prototype.propertyIsEnumerable has length property'); -} - -//CHECK#2 -if (Object.prototype.propertyIsEnumerable.length !== 1) { - throw new Test262Error('#2: The length property of the toObject method is 1'); -} +assert.sameValue( + Object.prototype.propertyIsEnumerable.length, + 1, + 'The value of Object.prototype.propertyIsEnumerable.length is expected to be 1' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A12.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A12.js index 2f4e08845379..545bb9f14e10 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A12.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A12.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Object.prototype.propertyIsEnumerable.call(undefined, 'foo'); -}); +}, 'Object.prototype.propertyIsEnumerable.call(undefined, "foo") throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A13.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A13.js index 2b045554a128..95520cb23317 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A13.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A13.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Object.prototype.propertyIsEnumerable.call(null, 'foo'); -}); +}, 'Object.prototype.propertyIsEnumerable.call(null, "foo") throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A1_T1.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A1_T1.js index 0857d77445e6..ccdabf7a1453 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A1_T1.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A1_T1.js @@ -10,11 +10,11 @@ description: > Calling the propertyIsEnumerable method for object in the prototype chain ---*/ - -//CHECK#1 -if (typeof Object.prototype.propertyIsEnumerable !== "function") { - throw new Test262Error('#1: propertyIsEnumerable method is defined'); -} +assert.sameValue( + typeof Object.prototype.propertyIsEnumerable, + "function", + 'The value of `typeof Object.prototype.propertyIsEnumerable` is expected to be "function"' +); var proto = { rootprop: "avis" @@ -22,26 +22,26 @@ var proto = { function AVISFACTORY(name) { this.name = name -}; +} AVISFACTORY.prototype = proto; var seagull = new AVISFACTORY("seagull"); -//CHECK#2 -if (typeof seagull.propertyIsEnumerable !== "function") { - throw new Test262Error('#2: propertyIsEnumerable method is accessed'); -} +assert.sameValue( + typeof seagull.propertyIsEnumerable, + "function", + 'The value of `typeof seagull.propertyIsEnumerable` is expected to be "function"' +); -//CHECK#3 -if (!(seagull.propertyIsEnumerable("name"))) { - throw new Test262Error('#3: propertyIsEnumerable method works properly'); -} +assert( + !!seagull.propertyIsEnumerable("name"), + 'The value of !!seagull.propertyIsEnumerable("name") is expected to be true' +); -//CHECK#4 -if (seagull.propertyIsEnumerable("rootprop")) { - throw new Test262Error('#4: propertyIsEnumerable method does not consider objects in the prototype chain'); -} -// +assert( + !seagull.propertyIsEnumerable("rootprop"), + 'The value of !seagull.propertyIsEnumerable("rootprop") is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A2_T1.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A2_T1.js index 5c103b9c205f..bcdeb0265619 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A2_T1.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A2_T1.js @@ -14,16 +14,17 @@ description: > Checking the type of Object.prototype.propertyIsEnumerable and the returned result ---*/ +assert.sameValue( + typeof Object.prototype.propertyIsEnumerable, + "function", + 'The value of `typeof Object.prototype.propertyIsEnumerable` is expected to be "function"' +); -//CHECK#1 -if (typeof Object.prototype.propertyIsEnumerable !== "function") { - throw new Test262Error('#1: hasOwnProperty method is defined'); -} +assert( + !Object.prototype.propertyIsEnumerable("propertyIsEnumerable"), + 'The value of !Object.prototype.propertyIsEnumerable("propertyIsEnumerable") is expected to be true' +); -//CHECK#2 -if (Object.prototype.propertyIsEnumerable("propertyIsEnumerable")) { - throw new Test262Error('#2: hasOwnProperty method works properly'); -} -// +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A2_T2.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A2_T2.js index 8d2b9b049a36..cfee052ef91e 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A2_T2.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A2_T2.js @@ -14,34 +14,33 @@ description: > Argument of the propertyIsEnumerable method is a custom boolean property ---*/ - -//CHECK#1 -if (typeof Object.prototype.propertyIsEnumerable !== "function") { - throw new Test262Error('#1: propertyIsEnumerable method is defined'); -} +assert.sameValue( + typeof Object.prototype.propertyIsEnumerable, + "function", + 'The value of `typeof Object.prototype.propertyIsEnumerable` is expected to be "function"' +); var obj = { the_property: true }; -//CHECK#2 -if (typeof obj.propertyIsEnumerable !== "function") { - throw new Test262Error('#2: propertyIsEnumerable method is accessed'); -} +assert.sameValue( + typeof obj.propertyIsEnumerable, + "function", + 'The value of `typeof obj.propertyIsEnumerable` is expected to be "function"' +); -//CHECK#3 -if (!(obj.propertyIsEnumerable("the_property"))) { - throw new Test262Error('#3: propertyIsEnumerable method works properly'); -} +assert( + !!obj.propertyIsEnumerable("the_property"), + 'The value of !!obj.propertyIsEnumerable("the_property") is expected to be true' +); -//CHECK#4 var accum = ""; for (var prop in obj) { accum += prop; } -if (accum.indexOf("the_property") !== 0) { - throw new Test262Error('#4: enumerating works properly'); -} -// +assert.sameValue(accum.indexOf("the_property"), 0, 'accum.indexOf("the_property") must return 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A6.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A6.js index 10684d62f709..ee0a6b3eb4d5 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A6.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A6.js @@ -8,11 +8,10 @@ description: > Checking if obtaining the prototype property of Object.prototype.propertyIsEnumerable fails ---*/ - -//CHECK#1 -if (Object.prototype.propertyIsEnumerable.prototype !== undefined) { - throw new Test262Error('#1: Object.prototype.propertyIsEnumerable has not prototype property' + Object.prototype.propertyIsEnumerable.prototype); -} -// +assert.sameValue( + Object.prototype.propertyIsEnumerable.prototype, + undefined, + 'The value of Object.prototype.propertyIsEnumerable.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A7.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A7.js deleted file mode 100644 index d19a37317b70..000000000000 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A7.js +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Object.prototype.propertyIsEnumerable can't be used as a constructor -es5id: 15.2.4.7_A7 -description: > - Checking if creating "new Object.prototype.propertyIsEnumerable" - fails ----*/ - -var FACTORY = Object.prototype.propertyIsEnumerable; - -assert.throws(TypeError, function() { - new FACTORY; -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A8.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A8.js index 6151477ae994..8555db0e5f36 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A8.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A8.js @@ -10,23 +10,21 @@ description: > Checking if enumerating the Object.prototype.propertyIsEnumerable.length property fails ---*/ +assert( + !!Object.prototype.propertyIsEnumerable.hasOwnProperty('length'), + 'The value of !!Object.prototype.propertyIsEnumerable.hasOwnProperty("length") is expected to be true' +); -//CHECK#0 -if (!(Object.prototype.propertyIsEnumerable.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Object.prototype.propertyIsEnumerable has length property'); -} +assert( + !Object.prototype.propertyIsEnumerable.propertyIsEnumerable('length'), + 'The value of !Object.prototype.propertyIsEnumerable.propertyIsEnumerable("length") is expected to be true' +); - -// CHECK#1 -if (Object.prototype.propertyIsEnumerable.propertyIsEnumerable('length')) { - throw new Test262Error('#1: the Object.prototype.propertyIsEnumerable.length property has the attributes DontEnum'); -} - -// CHECK#2 for (var p in Object.prototype.propertyIsEnumerable) { - if (p === "length") - throw new Test262Error('#2: the Object.prototype.propertyIsEnumerable.length property has the attributes DontEnum'); + assert.notSameValue(p, "length", 'The value of p is not "length"'); } // +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A9.js b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A9.js index f735b6b549cc..8f7264d09e6a 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A9.js +++ b/js/src/tests/test262/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A9.js @@ -10,16 +10,16 @@ description: > Checking if deleting the Object.prototype.propertyIsEnumerable.length property fails ---*/ +assert( + !!Object.prototype.propertyIsEnumerable.hasOwnProperty('length'), + 'The value of !!Object.prototype.propertyIsEnumerable.hasOwnProperty("length") is expected to be true' +); -//CHECK#0 -if (!(Object.prototype.propertyIsEnumerable.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Object.prototype.propertyIsEnumerable has length property'); -} +assert( + !!delete Object.prototype.propertyIsEnumerable.length, + 'The value of !!delete Object.prototype.propertyIsEnumerable.length is expected to be true' +); -//CHECK#1 -if (!delete Object.prototype.propertyIsEnumerable.length) { - throw new Test262Error('#1: The Object.prototype.propertyIsEnumerable.length property does not have the attributes DontDelete'); -} -// +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A1.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A1.js index 57259a715f06..1875921aa6b3 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A1.js +++ b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A1.js @@ -8,20 +8,22 @@ description: > Checking the type of Object.prototype.toLocaleString and the returned result ---*/ +assert.sameValue( + typeof Object.prototype.toLocaleString, + "function", + 'The value of `typeof Object.prototype.toLocaleString` is expected to be "function"' +); -//CHECK#1 -if (typeof Object.prototype.toLocaleString !== "function") { - throw new Test262Error('#1: toLocaleString method defined'); -} +assert.sameValue( + Object.prototype.toLocaleString(), + Object.prototype.toString(), + 'Object.prototype.toLocaleString() must return the same value returned by Object.prototype.toString()' +); -//CHECK#2 -if (Object.prototype.toLocaleString() !== Object.prototype.toString()) { - throw new Test262Error('#1: toLocaleString function returns the result of calling toString()'); -} - -//CHECK#2 -if ({}.toLocaleString() !== {}.toString()) { - throw new Test262Error('#2: toLocaleString function returns the result of calling toString()'); -} +assert.sameValue( + {}.toLocaleString(), + {}.toString(), + '({}).toLocaleString() must return the same value returned by ({}).toString()' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A10.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A10.js index 657cc24481b8..788bc2719682 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A10.js +++ b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A10.js @@ -11,11 +11,10 @@ description: > property fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (!(Object.prototype.toLocaleString.hasOwnProperty('length'))) { - throw new Test262Error('#1: the Object.prototype.toLocaleString has length property.'); -} +assert( + !!Object.prototype.toLocaleString.hasOwnProperty('length'), + 'The value of !!Object.prototype.toLocaleString.hasOwnProperty("length") is expected to be true' +); var obj = Object.prototype.toLocaleString.length; @@ -23,9 +22,12 @@ verifyNotWritable(Object.prototype.toLocaleString, "length", null, function() { return "shifted"; }); -//CHECK#2 -if (Object.prototype.toLocaleString.length !== obj) { - throw new Test262Error('#2: the Object.prototype.toLocaleString length property has the attributes ReadOnly.'); -} +assert.sameValue( + Object.prototype.toLocaleString.length, + obj, + 'The value of Object.prototype.toLocaleString.length is expected to equal the value of obj' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A11.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A11.js index ce7b16801b4d..1afdd3a546d0 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A11.js +++ b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A11.js @@ -6,15 +6,15 @@ info: The length property of the toLocaleString method is 0 es5id: 15.2.4.3_A11 description: Checking the Object.prototype.toLocaleString.length ---*/ +assert( + !!Object.prototype.toLocaleString.hasOwnProperty("length"), + 'The value of !!Object.prototype.toLocaleString.hasOwnProperty("length") is expected to be true' +); -//CHECK#1 -if (!(Object.prototype.toLocaleString.hasOwnProperty("length"))) { - throw new Test262Error('#1: The length property of the toLocaleString method is 0'); -} - -//CHECK#2 -if (Object.prototype.toLocaleString.length !== 0) { - throw new Test262Error('#2: The length property of the toLocaleString method is 0'); -} +assert.sameValue( + Object.prototype.toLocaleString.length, + 0, + 'The value of Object.prototype.toLocaleString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A12.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A12.js index c426b688c20f..299609daedbf 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A12.js +++ b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A12.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Object.prototype.toLocaleString.call(undefined); -}); +}, 'Object.prototype.toLocaleString.call(undefined) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A13.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A13.js index f4f903a9e139..c51669fa6492 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A13.js +++ b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A13.js @@ -10,6 +10,6 @@ description: > assert.throws(TypeError, function() { Object.prototype.toLocaleString.call(null); -}); +}, 'Object.prototype.toLocaleString.call(null) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A6.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A6.js index 2963dd8b6f3f..8f316e0dd459 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A6.js +++ b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A6.js @@ -8,11 +8,10 @@ description: > Checking if obtaining the prototype property of Object.prototype.toLocaleString fails ---*/ - -//CHECK#1 -if (Object.prototype.toLocaleString.prototype !== undefined) { - throw new Test262Error('#1: Object.prototype.toLocaleString has not prototype property' + Object.prototype.toLocaleString.prototype); -} -// +assert.sameValue( + Object.prototype.toLocaleString.prototype, + undefined, + 'The value of Object.prototype.toLocaleString.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A7.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A7.js deleted file mode 100644 index 5d8bc3bbec24..000000000000 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A7.js +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Object.prototype.toLocaleString can't be used as a constructor -es5id: 15.2.4.3_A7 -description: Checking if creating "new Object.prototype.toLocaleString" fails ----*/ - -var FACTORY = Object.prototype.toLocaleString; - -assert.throws(TypeError, function() { - new FACTORY; -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A8.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A8.js index ccda94cf2f4f..4b67335a4c6f 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A8.js +++ b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A8.js @@ -10,23 +10,21 @@ description: > Checking if enumerating the Object.prototype.toLocaleString.length property fails ---*/ +assert( + !!Object.prototype.toLocaleString.hasOwnProperty('length'), + 'The value of !!Object.prototype.toLocaleString.hasOwnProperty("length") is expected to be true' +); -//CHECK#0 -if (!(Object.prototype.toLocaleString.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Object.prototype.toLocaleString has length property.'); -} +assert( + !Object.prototype.toLocaleString.propertyIsEnumerable('length'), + 'The value of !Object.prototype.toLocaleString.propertyIsEnumerable("length") is expected to be true' +); - -// CHECK#1 -if (Object.prototype.toLocaleString.propertyIsEnumerable('length')) { - throw new Test262Error('#1: the Object.prototype.toLocaleString.length property has the attributes DontEnum'); -} - -// CHECK#2 for (var p in Object.prototype.toLocaleString) { - if (p === "length") - throw new Test262Error('#2: the Object.prototype.toLocaleString.length property has the attributes DontEnum'); + assert.notSameValue(p, "length", 'The value of p is not "length"'); } // +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A9.js b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A9.js index 9dc79e7f3a2b..861a0728d9f3 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A9.js +++ b/js/src/tests/test262/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A9.js @@ -10,20 +10,21 @@ description: > Checknig if deleting of the Object.prototype.toLocaleString.length property fails ---*/ +assert( + !!Object.prototype.toLocaleString.hasOwnProperty('length'), + 'The value of !!Object.prototype.toLocaleString.hasOwnProperty("length") is expected to be true' +); -//CHECK#0 -if (!(Object.prototype.toLocaleString.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Object.prototype.toLocaleString has length property'); -} +assert( + !!delete Object.prototype.toLocaleString.length, + 'The value of !!delete Object.prototype.toLocaleString.length is expected to be true' +); -//CHECK#1 -if (!delete Object.prototype.toLocaleString.length) { - throw new Test262Error('#1: The Object.prototype.toLocaleString.length property does not have the attributes DontDelete'); -} +assert( + !Object.prototype.toLocaleString.hasOwnProperty('length'), + 'The value of !Object.prototype.toLocaleString.hasOwnProperty("length") is expected to be true' +); -//CHECK#2 -if (Object.prototype.toLocaleString.hasOwnProperty('length')) { - throw new Test262Error('#2: The Object.prototype.toLocaleString.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/toString/not-ctor.js b/js/src/tests/test262/built-ins/Object/prototype/toString/not-ctor.js deleted file mode 100644 index fde9e257ced6..000000000000 --- a/js/src/tests/test262/built-ins/Object/prototype/toString/not-ctor.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-ecmascript-standard-built-in-objects -description: Object.prototype.toString is not a constructor -info: | - Built-in function objects that are not identified as constructors do - not implement the [[Construct]] internal method unless otherwise specified - in the description of a particular function ----*/ - -assert.throws(TypeError, function() { - new Object.prototype.toString(); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A10.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A10.js index d068bf1ab89a..ff4efa939a0c 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A10.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A10.js @@ -9,11 +9,10 @@ description: > fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (!(Object.prototype.valueOf.hasOwnProperty('length'))) { - throw new Test262Error('#1: the Object.prototype.valueOf has length property.'); -} +assert( + !!Object.prototype.valueOf.hasOwnProperty('length'), + 'The value of !!Object.prototype.valueOf.hasOwnProperty("length") is expected to be true' +); var obj = Object.prototype.valueOf.length; @@ -21,9 +20,12 @@ verifyNotWritable(Object.prototype.valueOf, "length", null, function() { return "shifted"; }); -//CHECK#2 -if (Object.prototype.valueOf.length !== obj) { - throw new Test262Error('#2: the Object.prototype.valueOf length property has the attributes ReadOnly.'); -} +assert.sameValue( + Object.prototype.valueOf.length, + obj, + 'The value of Object.prototype.valueOf.length is expected to equal the value of obj' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A11.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A11.js index 25ae74e19d5b..de2b758efb6c 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A11.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A11.js @@ -6,15 +6,15 @@ info: The length property of the valueOf method is 0 es5id: 15.2.4.4_A11 description: Checking the Object.prototype.valueOf.length ---*/ +assert( + !!Object.prototype.valueOf.hasOwnProperty("length"), + 'The value of !!Object.prototype.valueOf.hasOwnProperty("length") is expected to be true' +); -//CHECK#1 -if (!(Object.prototype.valueOf.hasOwnProperty("length"))) { - throw new Test262Error('#1: The length property of the toObject method is 0'); -} - -//CHECK#2 -if (Object.prototype.valueOf.length !== 0) { - throw new Test262Error('#2: The length property of the toObject method is 0'); -} +assert.sameValue( + Object.prototype.valueOf.length, + 0, + 'The value of Object.prototype.valueOf.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A12.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A12.js index 8eb232236adb..a95ea6e0659f 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A12.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A12.js @@ -11,6 +11,6 @@ description: Checking Object.prototype.valueOf invoked by the 'call' property. assert.throws(TypeError, function() { Object.prototype.valueOf.call(undefined); -}); +}, 'Object.prototype.valueOf.call(undefined) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A13.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A13.js index 9f368c774b3c..3a9d28b0f204 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A13.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A13.js @@ -11,6 +11,6 @@ description: Checking Object.prototype.valueOf invoked by the 'call' property. assert.throws(TypeError, function() { Object.prototype.valueOf.call(null); -}); +}, 'Object.prototype.valueOf.call(null) throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A14.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A14.js index b35177f1db24..27322400549b 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A14.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A14.js @@ -11,6 +11,6 @@ description: Checking Object.prototype.valueOf invoked by the 'call' property. assert.throws(TypeError, function() { (1, Object.prototype.valueOf)(); -}); +}, '(1, Object.prototype.valueOf)() throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A15.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A15.js index 2d59bc797be1..c924da8b0f9a 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A15.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A15.js @@ -9,10 +9,9 @@ es5id: 15.2.4.4_A15 description: Checking Object.prototype.valueOf when called as a global function. ---*/ -var v = Object.prototype.valueOf; - assert.throws(TypeError, function() { - v(); -}); + const valueOf = Object.prototype.valueOf; + valueOf(); +}, '`const valueOf = Object.prototype.valueOf; valueOf()` throws a TypeError exception'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T1.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T1.js index 72aa6f0bc92c..e60e7afc9a99 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T1.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T1.js @@ -6,22 +6,15 @@ info: The valueOf method returns its "this" value es5id: 15.2.4.4_A1_T1 description: "\"this\" value is a number" ---*/ - -//CHECK#1 -if (typeof Object.prototype.valueOf !== "function") { - throw new Test262Error('#1: valueOf method defined'); -} +assert.sameValue( + typeof Object.prototype.valueOf, + "function", + 'The value of `typeof Object.prototype.valueOf` is expected to be "function"' +); var obj = new Object(1.1); -//CHECK#2 -if (typeof obj.valueOf !== "function") { - throw new Test262Error('#2: valueOf method accessed'); -} - -//CHECK#3 -if (obj.valueOf() !== 1.1) { - throw new Test262Error('#3: The valueOf method returns its this value'); -} +assert.sameValue(typeof obj.valueOf, "function", 'The value of `typeof obj.valueOf` is expected to be "function"'); +assert.sameValue(obj.valueOf(), 1.1, 'obj.valueOf() must return 1.1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T2.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T2.js index d91820c57c3e..fa83ef26505e 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T2.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T2.js @@ -6,22 +6,15 @@ info: The valueOf method returns its "this" value es5id: 15.2.4.4_A1_T2 description: "\"this\" value is a boolean" ---*/ - -//CHECK#1 -if (typeof Object.prototype.valueOf !== "function") { - throw new Test262Error('#1: valueOf method defined'); -} +assert.sameValue( + typeof Object.prototype.valueOf, + "function", + 'The value of `typeof Object.prototype.valueOf` is expected to be "function"' +); var obj = new Object(true); -//CHECK#2 -if (typeof obj.valueOf !== "function") { - throw new Test262Error('#2: valueOf method accessed'); -} - -//CHECK#3 -if (obj.valueOf() !== true) { - throw new Test262Error('#3: The valueOf method returns its this value'); -} +assert.sameValue(typeof obj.valueOf, "function", 'The value of `typeof obj.valueOf` is expected to be "function"'); +assert.sameValue(obj.valueOf(), true, 'obj.valueOf() must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T3.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T3.js index 9da8956f0896..73933b535c1b 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T3.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T3.js @@ -6,22 +6,15 @@ info: The valueOf method returns its "this" value es5id: 15.2.4.4_A1_T3 description: "\"this\" value is a string" ---*/ - -//CHECK#1 -if (typeof Object.prototype.valueOf !== "function") { - throw new Test262Error('#1: valueOf method defined'); -} +assert.sameValue( + typeof Object.prototype.valueOf, + "function", + 'The value of `typeof Object.prototype.valueOf` is expected to be "function"' +); var obj = new Object("greenfield"); -//CHECK#2 -if (typeof obj.valueOf !== "function") { - throw new Test262Error('#2: valueOf method accessed'); -} - -//CHECK#3 -if (obj.valueOf() !== "greenfield") { - throw new Test262Error('#3: The valueOf method returns its this value'); -} +assert.sameValue(typeof obj.valueOf, "function", 'The value of `typeof obj.valueOf` is expected to be "function"'); +assert.sameValue(obj.valueOf(), "greenfield", 'obj.valueOf() must return "greenfield"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T4.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T4.js index f49165c3ec97..f5e20832e151 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T4.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T4.js @@ -6,22 +6,15 @@ info: The valueOf method returns its "this" value es5id: 15.2.4.4_A1_T4 description: "\"this\" value is an object" ---*/ - -//CHECK#1 -if (typeof Object.prototype.valueOf !== "function") { - throw new Test262Error('#1: valueOf method defined'); -} +assert.sameValue( + typeof Object.prototype.valueOf, + "function", + 'The value of `typeof Object.prototype.valueOf` is expected to be "function"' +); var obj = new Object; -//CHECK#2 -if (typeof obj.valueOf !== "function") { - throw new Test262Error('#2: valueOf method accessed'); -} - -//CHECK#3 -if (obj.valueOf() !== obj) { - throw new Test262Error('#3: The valueOf method returns its this value'); -} +assert.sameValue(typeof obj.valueOf, "function", 'The value of `typeof obj.valueOf` is expected to be "function"'); +assert.sameValue(obj.valueOf(), obj, 'obj.valueOf() returns obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T5.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T5.js index b71c46839a55..76fbd4a6be8d 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T5.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T5.js @@ -6,22 +6,15 @@ info: The valueOf method returns its "this" value es5id: 15.2.4.4_A1_T5 description: "\"this\" value is \"null\"" ---*/ - -//CHECK#1 -if (typeof Object.prototype.valueOf !== "function") { - throw new Test262Error('#1: valueOf method defined'); -} +assert.sameValue( + typeof Object.prototype.valueOf, + "function", + 'The value of `typeof Object.prototype.valueOf` is expected to be "function"' +); var obj = new Object(null); -//CHECK#2 -if (typeof obj.valueOf !== "function") { - throw new Test262Error('#2: valueOf method accessed'); -} - -//CHECK#3 -if (obj.valueOf() !== obj) { - throw new Test262Error('#3: The valueOf method returns its this value'); -} +assert.sameValue(typeof obj.valueOf, "function", 'The value of `typeof obj.valueOf` is expected to be "function"'); +assert.sameValue(obj.valueOf(), obj, 'obj.valueOf() returns obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T6.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T6.js index 7a7b7e549c41..1272ae585a31 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T6.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T6.js @@ -6,22 +6,15 @@ info: The valueOf method returns its "this" value es5id: 15.2.4.4_A1_T6 description: "\"this\" value is \"undefined\"" ---*/ - -//CHECK#1 -if (typeof Object.prototype.valueOf !== "function") { - throw new Test262Error('#1: valueOf method defined'); -} +assert.sameValue( + typeof Object.prototype.valueOf, + "function", + 'The value of `typeof Object.prototype.valueOf` is expected to be "function"' +); var obj = new Object(undefined); -//CHECK#2 -if (typeof obj.valueOf !== "function") { - throw new Test262Error('#2: valueOf method accessed'); -} - -//CHECK#3 -if (obj.valueOf() !== obj) { - throw new Test262Error('#3: The valueOf method returns its this value'); -} +assert.sameValue(typeof obj.valueOf, "function", 'The value of `typeof obj.valueOf` is expected to be "function"'); +assert.sameValue(obj.valueOf(), obj, 'obj.valueOf() returns obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T7.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T7.js index 48120a8a32eb..6c6f5a505928 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T7.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A1_T7.js @@ -6,22 +6,15 @@ info: The valueOf method returns its "this" value es5id: 15.2.4.4_A1_T7 description: "\"this\" value is \"void 0\"" ---*/ - -//CHECK#1 -if (typeof Object.prototype.valueOf !== "function") { - throw new Test262Error('#1: valueOf method defined'); -} +assert.sameValue( + typeof Object.prototype.valueOf, + "function", + 'The value of `typeof Object.prototype.valueOf` is expected to be "function"' +); var obj = new Object(void 0); -//CHECK#2 -if (typeof obj.valueOf !== "function") { - throw new Test262Error('#2: valueOf method accessed'); -} - -//CHECK#3 -if (obj.valueOf() !== obj) { - throw new Test262Error('#3: The valueOf method returns its this value'); -} +assert.sameValue(typeof obj.valueOf, "function", 'The value of `typeof obj.valueOf` is expected to be "function"'); +assert.sameValue(obj.valueOf(), obj, 'obj.valueOf() returns obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A6.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A6.js index 27a58ba028ce..846c25a5d11c 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A6.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A6.js @@ -8,11 +8,10 @@ description: > Checking if obtaining the prototype property of Object.prototype.valueOf fails ---*/ - -//CHECK#1 -if (Object.prototype.valueOf.prototype !== undefined) { - throw new Test262Error('#1: Object.prototype.valueOf has not prototype property' + Object.prototype.valueOf.prototype); -} -// +assert.sameValue( + Object.prototype.valueOf.prototype, + undefined, + 'The value of Object.prototype.valueOf.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A7.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A7.js deleted file mode 100644 index 831baf87b444..000000000000 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A7.js +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2009 the Sputnik authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Object.prototype.valueOf can't be used as a constructor -es5id: 15.2.4.4_A7 -description: Checking if creating "new Object.prototype.valueOf" fails ----*/ - -var FACTORY = Object.prototype.valueOf; - -assert.throws(TypeError, function() { - new FACTORY; -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A8.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A8.js index da02b8de0dd0..07479f15e30d 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A8.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A8.js @@ -8,23 +8,21 @@ description: > Checking if enumerating the Object.prototype.valueOf.length property fails ---*/ +assert( + !!Object.prototype.valueOf.hasOwnProperty('length'), + 'The value of !!Object.prototype.valueOf.hasOwnProperty("length") is expected to be true' +); -//CHECK#0 -if (!(Object.prototype.valueOf.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Object.prototype.valueOf has length property.'); -} +assert( + !Object.prototype.valueOf.propertyIsEnumerable('length'), + 'The value of !Object.prototype.valueOf.propertyIsEnumerable("length") is expected to be true' +); - -// CHECK#1 -if (Object.prototype.valueOf.propertyIsEnumerable('length')) { - throw new Test262Error('#1: the Object.prototype.valueOf.length property has the attributes DontEnum'); -} - -// CHECK#2 for (var p in Object.prototype.valueOf) { - if (p === "length") - throw new Test262Error('#2: the Object.prototype.valueOf.length property has the attributes DontEnum'); + assert.notSameValue(p, "length", 'The value of p is not "length"'); } // +// TODO: Convert to verifyProperty() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A9.js b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A9.js index ad883a872997..36eb233a0616 100644 --- a/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A9.js +++ b/js/src/tests/test262/built-ins/Object/prototype/valueOf/S15.2.4.4_A9.js @@ -10,20 +10,21 @@ description: > Checknig if deleting of the Object.prototype.valueOf.length property fails ---*/ +assert( + !!Object.prototype.valueOf.hasOwnProperty('length'), + 'The value of !!Object.prototype.valueOf.hasOwnProperty("length") is expected to be true' +); -//CHECK#0 -if (!(Object.prototype.valueOf.hasOwnProperty('length'))) { - throw new Test262Error('#0: the Object.prototype.valueOf has length property'); -} +assert( + !!delete Object.prototype.valueOf.length, + 'The value of !!delete Object.prototype.valueOf.length is expected to be true' +); -//CHECK#1 -if (!delete Object.prototype.valueOf.length) { - throw new Test262Error('#1: The Object.prototype.valueOf.length property does not have the attributes DontDelete'); -} +assert( + !Object.prototype.valueOf.hasOwnProperty('length'), + 'The value of !Object.prototype.valueOf.hasOwnProperty("length") is expected to be true' +); -//CHECK#2 -if (Object.prototype.valueOf.hasOwnProperty('length')) { - throw new Test262Error('#2: The Object.prototype.valueOf.length property does not have the attributes DontDelete'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Object/seal/seal-aggregateerror.js b/js/src/tests/test262/built-ins/Object/seal/seal-aggregateerror.js index bbfcc1323bca..909979f3fe4b 100644 --- a/js/src/tests/test262/built-ins/Object/seal/seal-aggregateerror.js +++ b/js/src/tests/test262/built-ins/Object/seal/seal-aggregateerror.js @@ -31,6 +31,7 @@ info: | Perform ? DefinePropertyOrThrow(O, k, desc). Return true. +features: [AggregateError] ---*/ Object.seal(new AggregateError([])); diff --git a/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species.js b/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species.js index 9a8bcf2abad2..24da4e82ee66 100644 --- a/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species.js +++ b/js/src/tests/test262/built-ins/Promise/Symbol.species/symbol-species.js @@ -7,8 +7,7 @@ info: | es6id: 6.1.5.1 author: Sam Mikes description: Promise[Symbol.species] exists per spec -includes: - - propertyHelper.js +includes: [propertyHelper.js] features: [Symbol.species] ---*/ diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A1.1_T1.js index 90ff50b7ace6..1cf29b6a21b4 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A1.1_T1.js @@ -7,9 +7,6 @@ es6id: 25.4.4.1_A1.1_T1 author: Sam Mikes description: Promise.all is callable ---*/ - -if ((typeof Promise.all) !== "function") { - throw new Test262Error('Expected Promise.all to be a function'); -} +assert.sameValue(typeof Promise.all, "function", 'The value of `typeof Promise.all` is expected to be "function"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.1_T1.js index 3d4164286813..5d27aaab3521 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.1_T1.js @@ -9,8 +9,6 @@ description: Promise.all returns a Promise ---*/ var p = Promise.all([]); -if (!(p instanceof Promise)) { - throw new Test262Error('Expected p to be a Promise'); -} +assert(!!(p instanceof Promise), 'The value of !!(p instanceof Promise) is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T1.js index c33bf1b91a92..c737bb4f9990 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T1.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T1.js @@ -13,7 +13,5 @@ flags: [async] var arg = []; Promise.all(arg).then(function(result) { - if (!(result instanceof Array)) { - throw new Test262Error("expected an array from Promise.all, got " + result); - } + assert(!!(result instanceof Array), 'The value of !!(result instanceof Array) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T2.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T2.js index 2a3f33138f39..ad9bfa6c4866 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T2.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T2.js @@ -13,7 +13,5 @@ flags: [async] var arg = []; Promise.all(arg).then(function(result) { - if (result.length !== 0) { - throw new Test262Error("expected an empty array from Promise.all([]), got " + result); - } + assert.sameValue(result.length, 0, 'The value of result.length is expected to be 0'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T3.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T3.js index af3dc79a51ab..09b598f3fcf3 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T3.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A2.3_T3.js @@ -13,7 +13,5 @@ flags: [async] var arg = []; Promise.all(arg).then(function(result) { - if (result === arg) { - throw new Test262Error("expected a new array from Promise.all but argument was re-used"); - } + assert.notSameValue(result, arg, 'The value of result is expected to not equal the value of `arg`'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T1.js index 889dcc45dcf6..88e7558c3d9f 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T1.js @@ -18,7 +18,5 @@ var nonIterable = 3; Promise.all(nonIterable).then(function() { throw new Test262Error('Promise unexpectedly resolved: Promise.all(nonIterable) should throw TypeError'); }, function(err) { - if (!(err instanceof TypeError)) { - throw new Test262Error('Expected TypeError, got ' + err); - } + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T2.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T2.js index bb56f94db2f6..23c5d8390d44 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T2.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T2.js @@ -17,7 +17,5 @@ flags: [async] Promise.all(new Error("abrupt")).then(function() { throw new Test262Error('Promise unexpectedly resolved: Promise.all(abruptCompletion) should throw TypeError'); }, function(err) { - if (!(err instanceof TypeError)) { - throw new Test262Error('Expected TypeError, got ' + err); - } + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T3.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T3.js index 181bb6d5c939..9a93d8bd9f97 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T3.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A3.1_T3.js @@ -23,7 +23,5 @@ Object.defineProperty(iterThrows, Symbol.iterator, { Promise.all(iterThrows).then(function() { throw new Test262Error('Promise unexpectedly fulfilled: Promise.all(iterThrows) should throw TypeError'); }, function(err) { - if (!(err instanceof Error)) { - throw new Test262Error('Expected promise to be rejected with error, got ' + err); - } + assert(!!(err instanceof Error), 'The value of !!(err instanceof Error) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A5.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A5.1_T1.js index 41a1651b39ed..b670d9e937e8 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A5.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A5.1_T1.js @@ -26,5 +26,5 @@ iterThrows[Symbol.iterator] = function() { Promise.all(iterThrows).then(function() { throw new Test262Error('Promise unexpectedly resolved: Promise.all(iterThrows) should throw TypeError'); }, function(reason) { - assert.sameValue(reason, error); + assert.sameValue(reason, error, 'The value of reason is expected to equal the value of error'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.1_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.1_T1.js index 7a4fca923054..0cc08b3f2a6a 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A7.1_T1.js @@ -17,16 +17,8 @@ var p1 = Promise.resolve(3); var pAll = Promise.all([p1]); pAll.then(function(result) { - if (!(pAll instanceof Promise)) { - throw new Test262Error("Expected Promise.all() to be promise, actually " + pAll); - } - if (!(result instanceof Array)) { - throw new Test262Error("Expected Promise.all() to be promise for an Array, actually " + result); - } - if (result.length !== 1) { - throw new Test262Error("Expected Promise.all([p1]) to be a promise for one-element Array, actually " + result); - } - if (result[0] !== 3) { - throw new Test262Error("Expected result[0] to be 3, actually " + result[0]); - } + assert(!!(pAll instanceof Promise), 'The value of !!(pAll instanceof Promise) is expected to be true'); + assert(!!(result instanceof Array), 'The value of !!(result instanceof Array) is expected to be true'); + assert.sameValue(result.length, 1, 'The value of result.length is expected to be 1'); + assert.sameValue(result[0], 3, 'The value of result[0] is expected to be 3'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T1.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T1.js index c837a1e55775..d5ffb354d8fa 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T1.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T1.js @@ -20,9 +20,7 @@ var rejectP1, Promise.all([p1, p2]).then(function(resolve) { throw new Test262Error("Did not expect promise to be fulfilled."); }, function(rejected) { - if (rejected !== 1) { - throw new Test262Error("Expected promise to be rejected with 1, actually " + rejected); - } + assert.sameValue(rejected, 1, 'The value of rejected is expected to be 1'); }).then($DONE, $DONE); rejectP1(1); diff --git a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T2.js b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T2.js index 525503dc240c..71390b4c7154 100644 --- a/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T2.js +++ b/js/src/tests/test262/built-ins/Promise/all/S25.4.4.1_A8.2_T2.js @@ -20,9 +20,7 @@ var rejectP2, Promise.all([p1, p2]).then(function() { throw new Test262Error("Did not expect promise to be fulfilled."); }, function(rejected) { - if (rejected !== 2) { - throw new Test262Error("Expected promise to be rejected with 2, actually " + rejected); - } + assert.sameValue(rejected, 2, 'The value of rejected is expected to be 2'); }).then($DONE, $DONE); rejectP2(2); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js index 32324280e14a..3c08a74243d0 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js @@ -9,9 +9,10 @@ es6id: S25.4.4.2_A1.1_T1 author: Sam Mikes description: Promise prototype exists ---*/ - -if (Promise.prototype === undefined) { - throw new Test262Error("Expected Promise.prototype to be defined."); -} +assert.notSameValue( + Promise.prototype, + undefined, + 'The value of Promise.prototype is expected to not equal ``undefined``' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js index 47fe1e0e2a8b..5095976ce7d7 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js @@ -8,9 +8,10 @@ es6id: S25.4.5_A3.1_T1 author: Sam Mikes description: Promise.prototype.constructor is the Promise constructor ---*/ - -if (Promise.prototype.constructor !== Promise) { - throw new Test262Error("Expected Promise.prototype.constructor to be Promise"); -} +assert.sameValue( + Promise.prototype.constructor, + Promise, + 'The value of Promise.prototype.constructor is expected to equal the value of Promise' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js index 56d6efb8dd61..0f145ac2b24f 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js @@ -8,9 +8,9 @@ es6id: S25.4.5.1_A1.1_T1 author: Sam Mikes description: Promise.prototype.catch is a function ---*/ - -if (!(Promise.prototype.catch instanceof Function)) { - throw new Test262Error("Expected Promise.prototype.catch to be a function"); -} +assert( + !!(Promise.prototype.catch instanceof Function), + 'The value of !!(Promise.prototype.catch instanceof Function) is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js index cb3f4a9a95a9..efdf80c4a83d 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js @@ -11,8 +11,9 @@ description: catch is a method on a Promise var p = Promise.resolve(3); -if (!(p.catch instanceof Function)) { - throw new Test262Error("Expected p.catch to be a function"); -} +assert( + !!(p.catch instanceof Function), + 'The value of !!(p.catch instanceof Function) is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js index 16a78bf5f43c..415daf47aba8 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js @@ -11,14 +11,12 @@ description: catch is implemented in terms of then flags: [async] ---*/ -var obj = {}; +var arg = {}; -var p = Promise.resolve(obj); +var p = Promise.resolve(arg); p.catch(function() { throw new Test262Error("Should not be called - promise is fulfilled"); -}).then(function(arg) { - if (arg !== obj) { - throw new Test262Error("Expected promise to be fulfilled with obj, got " + arg); - } +}).then(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js index efa6f7b9f4f8..df555fd774c2 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js @@ -11,14 +11,12 @@ description: catch is implemented in terms of then flags: [async] ---*/ -var obj = {}; +var arg = {}; -var p = Promise.reject(obj); +var p = Promise.reject(arg); p.then(function() { throw new Test262Error("Should not be called: did not expect promise to be fulfilled"); -}).catch(function(arg) { - if (arg !== obj) { - throw new Test262Error("Should have been rejected with reason obj, got " + arg); - } +}).catch(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js index 87b183b749ac..959bc284dc8e 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js @@ -8,9 +8,9 @@ es6id: S25.4.5.3_A1.1_T1 author: Sam Mikes description: Promise.prototype.then is a function of two arguments ---*/ - -if (!(Promise.prototype.then instanceof Function)) { - throw new Test262Error("Expected Promise.prototype.then to be a function"); -} +assert( + !!(Promise.prototype.then instanceof Function), + 'The value of !!(Promise.prototype.then instanceof Function) is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js index f60fd8d00ee3..c89023e08383 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js @@ -11,12 +11,7 @@ description: Promise.prototype.then is a function of two arguments var p = new Promise(function() {}); -if (!(p.then instanceof Function)) { - throw new Test262Error("Expected p.then to be a function"); -} - -if (p.then.length !== 2) { - throw new Test262Error("Expected p.then to be a function of two arguments"); -} +assert(!!(p.then instanceof Function), 'The value of !!(p.then instanceof Function) is expected to be true'); +assert.sameValue(p.then.length, 2, 'The value of p.then.length is expected to be 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js index 5bad9a15a0a1..8fc66ab9642c 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js @@ -12,12 +12,10 @@ description: Promise.prototype.then accepts 'undefined' as arg1, arg2 flags: [async] ---*/ -var obj = {}; -var p = Promise.resolve(obj); +var arg = {}; +var p = Promise.resolve(arg); p.then(undefined, undefined) - .then(function(arg) { - if (arg !== obj) { - throw new Test262Error("Expected resolution object to be passed through, got " + arg); - } - }).then($DONE, $DONE); + .then(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js index f23d0dfb0c11..3aeca23d955a 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js @@ -12,13 +12,11 @@ description: Promise.prototype.then accepts 'undefined' as arg1, arg2 flags: [async] ---*/ -var obj = {}; -var p = Promise.reject(obj); +var arg = {}; +var p = Promise.reject(arg); p.then(undefined, undefined).then(function() { throw new Test262Error("Should not be called -- promise was rejected."); -}, function(arg) { - if (arg !== obj) { - throw new Test262Error("Expected resolution object to be passed through, got " + arg); - } +}, function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js index dc233819c855..5b1ac21b2714 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js @@ -12,12 +12,10 @@ description: Promise.prototype.then treats non-callable arg1, arg2 as undefined flags: [async] ---*/ -var obj = {}; -var p = Promise.resolve(obj); +var arg = {}; +var p = Promise.resolve(arg); p.then(3, 5) - .then(function(arg) { - if (arg !== obj) { - throw new Test262Error("Expected resolution object to be passed through, got " + arg); - } - }).then($DONE, $DONE); + .then(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js index bab8ae9e116d..5efe836020e4 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js @@ -12,13 +12,11 @@ description: Promise.prototype.then treats non-callable arg1, arg2 as undefined flags: [async] ---*/ -var obj = {}; -var p = Promise.reject(obj); +var arg = {}; +var p = Promise.reject(arg); p.then(3, 5).then(function() { throw new Test262Error("Should not be called -- promise was rejected."); -}, function(arg) { - if (arg !== obj) { - throw new Test262Error("Expected resolution object to be passed through, got " + arg); - } +}, function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js index d5e5feb058b2..87a2b2271b1b 100644 --- a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js +++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js @@ -27,7 +27,7 @@ p.then(function() { throw new Test262Error("Should not be called -- Promise rejected."); }, function() { sequence.push(3); - assert.sameValue(sequence.length, 3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); checkSequence(sequence, "Should be first"); }).catch($DONE); @@ -37,12 +37,12 @@ Promise.resolve().then(function() { throw new Test262Error("Should not be called (2) -- Promise rejected."); }, function() { sequence.push(5); - assert.sameValue(sequence.length, 5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); checkSequence(sequence, "Should be third"); }).then($DONE, $DONE); sequence.push(4); - assert.sameValue(sequence.length, 4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); checkSequence(sequence, "Should be second"); }).catch($DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js index a8792e3f4e4d..fadedf1e242d 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js @@ -7,9 +7,6 @@ es6id: S25.4.4.3_A1.1_T1 author: Sam Mikes description: Promise.race is callable ---*/ - -if (typeof Promise.race !== "function") { - throw new Test262Error("Expected Promise.race to be a function, actually " + typeof Promise.race); -} +assert.sameValue(typeof Promise.race, "function", 'The value of `typeof Promise.race` is expected to be "function"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js index ae0938f6c647..0200158ab594 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.1_T1.js @@ -10,8 +10,6 @@ description: Promise.race returns a new promise var p = Promise.race([]); -if (!(p instanceof Promise)) { - throw new Test262Error("Expected Promise.race([]) to return a promise."); -} +assert(!!(p instanceof Promise), 'The value of !!(p instanceof Promise) is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js index dc41d520dc62..1adfb40d633d 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T1.js @@ -15,7 +15,5 @@ var nonIterable = 3; Promise.race(nonIterable).then(function() { throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(nonIterable) should throw TypeError'); }, function(err) { - if (!(err instanceof TypeError)) { - throw new Test262Error('Expected TypeError, got ' + err); - } + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js index bbe8e5277c60..3555d007f734 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T2.js @@ -13,7 +13,5 @@ flags: [async] Promise.race(new Error("abrupt")).then(function() { throw new Test262Error('Promise unexpectedly resolved: Promise.race(abruptCompletion) should throw TypeError'); }, function(err) { - if (!(err instanceof TypeError)) { - throw new Test262Error('Expected TypeError, got ' + err); - } + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js index e8ff9d11ec66..7e8f21d0daf2 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A2.2_T3.js @@ -24,7 +24,5 @@ Object.defineProperty(iterThrows, Symbol.iterator, { Promise.race(iterThrows).then(function() { throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw'); }, function(err) { - if (!(err instanceof Error)) { - throw new Test262Error('Expected Promise to be rejected with an error, got ' + err); - } + assert(!!(err instanceof Error), 'The value of !!(err instanceof Error) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js index de4bfec6421d..e4602242f2e7 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T1.js @@ -23,5 +23,5 @@ iterThrows[Symbol.iterator] = function() { Promise.race(iterThrows).then(function() { throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw TypeError'); }, function(reason) { - assert.sameValue(reason, error); + assert.sameValue(reason, error, 'The value of reason is expected to equal the value of error'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js index 946ba3e82710..c8aeb4602f40 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A4.1_T2.js @@ -30,7 +30,5 @@ Object.defineProperty(iterThrows, Symbol.iterator, { Promise.race(iterThrows).then(function() { throw new Test262Error('Promise unexpectedly fulfilled: Promise.race(iterThrows) should throw TypeError'); }, function(err) { - if (!(err instanceof TypeError)) { - throw new Test262Error('Expected TypeError, got ' + err); - } + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js index 2775442e5c6b..5be746bfab40 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js @@ -21,17 +21,17 @@ p.then(function() { throw new Test262Error("Should not fulfill."); }, function() { sequence.push(4); - assert.sameValue(sequence.length, 4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); checkSequence(sequence, "This happens second"); }).catch($DONE); Promise.resolve().then(function() { sequence.push(3); - assert.sameValue(sequence.length, 3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); checkSequence(sequence, "This happens first"); }).then(function() { sequence.push(5); - assert.sameValue(sequence.length, 5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); checkSequence(sequence, "This happens third"); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js index 8126071a4f36..768f25c84277 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js @@ -18,23 +18,21 @@ var p1 = Promise.resolve(1), sequence.push(1); -p.then(function(arg) { - if (arg !== 1) { - throw new Test262Error("Expected promise to be fulfilled with 1, got " + arg); - } +p.then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); sequence.push(4); - assert.sameValue(sequence.length, 4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); checkSequence(sequence, "This happens second"); }).catch($DONE); Promise.resolve().then(function() { sequence.push(3); - assert.sameValue(sequence.length, 3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); checkSequence(sequence, "This happens first"); }).then(function() { sequence.push(5); - assert.sameValue(sequence.length, 5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); checkSequence(sequence, "This happens third"); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js index 58bd3f12d3af..72b7200f8596 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T2.js @@ -18,23 +18,21 @@ var p1 = Promise.resolve(1), sequence.push(1); -p.then(function(arg) { - if (arg !== 1) { - throw new Test262Error("Expected promise to be fulfilled with 1, got " + arg); - } +p.then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); sequence.push(4); - assert.sameValue(sequence.length, 4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); checkSequence(sequence, "This happens second"); }).catch($DONE); Promise.resolve().then(function() { sequence.push(3); - assert.sameValue(sequence.length, 3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); checkSequence(sequence, "This happens first"); }).then(function() { sequence.push(5); - assert.sameValue(sequence.length, 5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); checkSequence(sequence, "This happens third"); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js index ff8f5f8dea3f..ce763b023abd 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.1_T3.js @@ -18,23 +18,21 @@ var p1 = new Promise(function() {}), sequence.push(1); -p.then(function(arg) { - if (arg !== 2) { - throw new Test262Error("Expected promise to be fulfilled with 2, got " + arg); - } +p.then(function(result) { + assert.sameValue(result, 2, 'The value of result is expected to be 2'); sequence.push(4); - assert.sameValue(sequence.length, 4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); checkSequence(sequence, "This happens second"); }).catch($DONE); Promise.resolve().then(function() { sequence.push(3); - assert.sameValue(sequence.length, 3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); checkSequence(sequence, "This happens first"); }).then(function() { sequence.push(5); - assert.sameValue(sequence.length, 5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); checkSequence(sequence, "This happens third"); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js index aa795da610aa..b38ba8eae62e 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js @@ -20,23 +20,21 @@ sequence.push(1); p.then(function() { throw new Test262Error("Should not be fulfilled - expected rejection."); -}, function(arg) { - if (arg !== 1) { - throw new Test262Error("Expected rejection reason to be 1, got " + arg); - } +}, function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); sequence.push(4); - assert.sameValue(sequence.length, 4); + assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4'); checkSequence(sequence, "This happens second"); }).catch($DONE); Promise.resolve().then(function() { sequence.push(3); - assert.sameValue(sequence.length, 3); + assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3'); checkSequence(sequence, "This happens first"); }).then(function() { sequence.push(5); - assert.sameValue(sequence.length, 5); + assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5'); checkSequence(sequence, "This happens third"); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js index b915c9dfea55..303441a11d6c 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js @@ -20,8 +20,6 @@ var resolveP1, rejectP2, rejectP2(new Error("Promise.race should not see this if P1 already resolved")); resolveP1(1); -Promise.race([p1, p2]).then(function(arg) { - if (arg !== 1) { - throw new Test262Error("Expected fulfillment with 1, got " + arg); - } +Promise.race([p1, p2]).then(function(result) { + assert.sameValue(result, 1, 'The value of result is expected to be 1'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js index 59cb1f4237bb..7081e0b3f7eb 100644 --- a/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js +++ b/js/src/tests/test262/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js @@ -19,10 +19,8 @@ var resolveP1, rejectP2, Promise.race([p1, p2]).then(function() { throw new Test262Error("Should not be fulfilled: expected rejection."); -}, function(arg) { - if (arg !== 2) { - throw new Test262Error("Expected rejection reason to be 2, got " + arg); - } +}, function(result) { + assert.sameValue(result, 2, 'The value of result is expected to be 2'); }).then($DONE, $DONE); rejectP2(2); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js index a7bac87a8601..882684d04f66 100644 --- a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence-with-rejections.js @@ -45,7 +45,7 @@ Promise.all([ return checkSequence(sequence, 'Expected to be called second.'); }) ]).then(result => { - compareArray(result, [true, true, true]); + assert.compareArray(result, [true, true, true]); assert.sameValue(sequence.length, 5); checkSequence(sequence); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js index fcf2b7c0d436..316db984bf03 100644 --- a/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js +++ b/js/src/tests/test262/built-ins/Promise/race/resolved-sequence.js @@ -45,7 +45,7 @@ Promise.all([ return checkSequence(sequence, 'Expected to be called second.'); }) ]).then(result => { - compareArray(result, [true, true, true]); + assert.compareArray(result, [true, true, true]); assert.sameValue(sequence.length, 5); checkSequence(sequence) }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js index 80bd2d80774e..999e0db577d4 100644 --- a/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js @@ -8,9 +8,10 @@ es6id: S25.4.4.4_A1.1_T1 author: Sam Mikes description: Promise.reject is a function ---*/ - -if ((typeof Promise.reject) !== "function") { - throw new Test262Error("Expected Promise.reject to be a function"); -} +assert.sameValue( + typeof Promise.reject, + "function", + 'The value of `typeof Promise.reject` is expected to be "function"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A2.1_T1.js index 62d3280661ab..101f184caf76 100644 --- a/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/reject/S25.4.4.4_A2.1_T1.js @@ -19,14 +19,10 @@ flags: [async] var p = Promise.reject(3); -if (!(p instanceof Promise)) { - throw new Test262Error("Expected Promise.reject to return a promise."); -} +assert(!!(p instanceof Promise), 'The value of !!(p instanceof Promise) is expected to be true'); p.then(function() { throw new Test262Error("Promise should not be fulfilled."); -}, function(arg) { - if (arg !== 3) { - throw new Test262Error("Expected promise to be rejected with supplied arg, got " + arg); - } +}, function(result) { + assert.sameValue(result, 3, 'The value of result is expected to be 3'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js index 1d94ada58eb8..ba9e815a667f 100644 --- a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js @@ -8,9 +8,10 @@ es6id: S25.4.4.5_A1.1_T1 author: Sam Mikes description: Promise.resolve is a function ---*/ - -if ((typeof Promise.resolve) !== "function") { - throw new Test262Error("Expected Promise.resolve to be a function"); -} +assert.sameValue( + typeof Promise.resolve, + "function", + 'The value of `typeof Promise.resolve` is expected to be "function"' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js index 53d8011fcf74..4277dcbbd517 100644 --- a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js @@ -10,8 +10,6 @@ description: Promise.resolve passes through a promise w/ same Constructor var p1 = Promise.resolve(1), p2 = Promise.resolve(p1); -if (p1 !== p2) { - throw new Test262Error("Expected p1 === Promise.resolve(p1) because they have same constructor"); -} +assert.sameValue(p1, p2, 'The value of p1 is expected to equal the value of p2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.2_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.2_T1.js index ab55251cd5c2..1445d3a242aa 100644 --- a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.2_T1.js +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.2_T1.js @@ -14,16 +14,12 @@ var resolveP1, resolveP1 = resolve; }), p2 = Promise.resolve(p1), - obj = {}; + arg = {}; -if (p1 !== p2) { - throw new Test262Error("Expected p1 === Promise.resolve(p1) because they have same constructor"); -} +assert.sameValue(p1, p2, 'The value of p1 is expected to equal the value of p2'); -p2.then(function(arg) { - if (arg !== obj) { - throw new Test262Error("Expected promise to be resolved with obj, actually " + arg); - } +p2.then(function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); }).then($DONE, $DONE); -resolveP1(obj); +resolveP1(arg); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.3_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.3_T1.js index 8fdea5f215a8..e028c21cbac0 100644 --- a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.3_T1.js +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A2.3_T1.js @@ -14,18 +14,14 @@ var rejectP1, rejectP1 = reject; }), p2 = Promise.resolve(p1), - obj = {}; + arg = {}; -if (p1 !== p2) { - throw new Test262Error("Expected p1 === Promise.resolve(p1) because they have same constructor"); -} +assert.sameValue(p1, p2, 'The value of p1 is expected to equal the value of p2'); p2.then(function() { throw new Test262Error("Expected p2 to be rejected, not fulfilled."); -}, function(arg) { - if (arg !== obj) { - throw new Test262Error("Expected promise to be rejected with reason obj, actually " + arg); - } +}, function(result) { + assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg'); }).then($DONE, $DONE); -rejectP1(obj); +rejectP1(arg); diff --git a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A4.1_T1.js index 279f62d2cfb1..25b8acf3a283 100644 --- a/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A4.1_T1.js +++ b/js/src/tests/test262/built-ins/Promise/resolve/S25.4.4.5_A4.1_T1.js @@ -21,7 +21,5 @@ resolveP(p); p.then(function() { throw new Test262Error("Should not fulfill: should reject with TypeError."); }, function(err) { - if (!(err instanceof TypeError)) { - throw new Test262Error("Expected TypeError, got " + err); - } + assert(!!(err instanceof TypeError), 'The value of !!(err instanceof TypeError) is expected to be true'); }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-number.js b/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-number.js index 967065bf5831..bc1c591b288a 100644 --- a/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-number.js +++ b/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-number.js @@ -11,8 +11,6 @@ info: | features: [Proxy] ---*/ -function Target() {} - var P = new Proxy(function() { throw new Test262Error('target should not be called'); }, { diff --git a/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-string.js b/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-string.js index cff36e2baaa2..32bb69bfa59a 100644 --- a/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-string.js +++ b/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-string.js @@ -11,8 +11,6 @@ info: | features: [Proxy] ---*/ -function Target() {} - var P = new Proxy(function() { throw new Test262Error('target should not be called'); }, { diff --git a/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-symbol.js b/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-symbol.js index c210669954ef..857e0b6ae73e 100644 --- a/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-symbol.js +++ b/js/src/tests/test262/built-ins/Proxy/construct/return-not-object-throws-symbol.js @@ -11,8 +11,6 @@ info: | features: [Proxy, Symbol] ---*/ -function Target() {} - var P = new Proxy(function() { throw new Test262Error('target should not be called'); }, { diff --git a/js/src/tests/test262/built-ins/Proxy/enumerate/removed-does-not-trigger.js b/js/src/tests/test262/built-ins/Proxy/enumerate/removed-does-not-trigger.js index a13f6966a940..c738d3adaa90 100644 --- a/js/src/tests/test262/built-ins/Proxy/enumerate/removed-does-not-trigger.js +++ b/js/src/tests/test262/built-ins/Proxy/enumerate/removed-does-not-trigger.js @@ -23,14 +23,14 @@ for (x in p) { forInResults.push(x); } -assert(compareArray(forInResults, ["0", "1", "2"])); +assert.compareArray(forInResults, ["0", "1", "2"]); var forOfResults = []; for (x of p) { forOfResults.push(x); } -assert(compareArray(forOfResults, [1, 2, 3])); +assert.compareArray(forOfResults, [1, 2, 3]); var itor = p[Symbol.iterator](); var next = itor.next(); diff --git a/js/src/tests/test262/built-ins/Proxy/revocable/tco-fn-realm-strict.js b/js/src/tests/test262/built-ins/Proxy/revocable/tco-fn-realm-strict.js new file mode 100644 index 000000000000..6714f09e6334 --- /dev/null +++ b/js/src/tests/test262/built-ins/Proxy/revocable/tco-fn-realm-strict.js @@ -0,0 +1,27 @@ +// |reftest| skip -- tail-call-optimization is not supported +'use strict'; +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Realm of the TypeError from invoking a revoked Proxy during tail-call + optimization +esid: sec-tail-position-calls +flags: [onlyStrict] +features: [Proxy, tail-call-optimization] +---*/ + +var other = $262.createRealm(); +var F = other.evalScript(` + (function() { + var { proxy, revoke } = Proxy.revocable(function() {}, {}); + revoke(); + return proxy(); + }) +`); + +assert.throws(other.global.TypeError, function() { + F(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/constructor.js b/js/src/tests/test262/built-ins/Realm/constructor.js deleted file mode 100644 index f6e6d3dba6a6..000000000000 --- a/js/src/tests/test262/built-ins/Realm/constructor.js +++ /dev/null @@ -1,21 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm-constructor -description: > - Realm is a constructor and has [[Construct]] internal method. -includes: [isConstructor.js] -features: [callable-boundary-realms, Reflect.construct] ----*/ -assert.sameValue( - typeof Realm, - 'function', - 'This test must fail if Realm is not a function' -); - -assert(isConstructor(Realm)); -assert.sameValue(Object.getPrototypeOf(Realm), Function.prototype); -new Realm(); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/instance.js b/js/src/tests/test262/built-ins/Realm/instance.js deleted file mode 100644 index b6668d0f149c..000000000000 --- a/js/src/tests/test262/built-ins/Realm/instance.js +++ /dev/null @@ -1,33 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm-constructor -description: > - new Realm() returns a realm instance -info: | - Realm ( ) - - ... - 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Realm.prototype%", - « [[Realm]], [[ExecutionContext]] »). - ... - 13. Return O. -features: [callable-boundary-realms] ----*/ -assert.sameValue( - typeof Realm, - 'function', - 'This test must fail if Realm is not a function' -); - -var realm = new Realm(); - -assert(realm instanceof Realm); -assert.sameValue( - Object.getPrototypeOf(realm), - Realm.prototype, - '[[Prototype]] is set to %Realm.prototype%' -); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/errors-from-the-other-realm-is-wrapped-into-a-typeerror.js b/js/src/tests/test262/built-ins/Realm/prototype/evaluate/errors-from-the-other-realm-is-wrapped-into-a-typeerror.js deleted file mode 100644 index f7b9ce2d8986..000000000000 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/errors-from-the-other-realm-is-wrapped-into-a-typeerror.js +++ /dev/null @@ -1,24 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm.prototype.evaluate -description: > - Realm.prototype.evaluate wraps errors from other realm into TypeErrors -features: [callable-boundary-realms] ----*/ - -assert.sameValue( - typeof Realm.prototype.evaluate, - 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' -); - -const r = new Realm(); - -assert.throws(TypeError, () => r.evaluate('...'), 'SyntaxError => TypeError'); -assert.throws(TypeError, () => r.evaluate('throw 42'), 'throw primitive => TypeError'); -assert.throws(TypeError, () => r.evaluate('throw new ReferenceError("aaa")'), 'custom ctor => TypeError'); -assert.throws(TypeError, () => r.evaluate('throw new TypeError("aaa")'), 'Child TypeError => Parent TypeError'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/not-constructor.js b/js/src/tests/test262/built-ins/Realm/prototype/evaluate/not-constructor.js deleted file mode 100644 index aa6e87d90931..000000000000 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/not-constructor.js +++ /dev/null @@ -1,37 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm.prototype.evaluate -description: > - Realm.prototype.evaluate is not a constructor. -includes: [isConstructor.js] -features: [callable-boundary-realms, Reflect.construct] ----*/ - -assert.sameValue( - typeof Realm.prototype.evaluate, - 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' -); - -assert.sameValue( - isConstructor(Realm.prototype.evaluate), - false, - 'isConstructor(Realm.prototype.evaluate) must return false' -); - -assert.throws(TypeError, () => { - new Realm.prototype.evaluate(""); -}, '`new Realm.prototype.evaluate("")` throws TypeError'); - -const r = new Realm(); -r.evaluate('globalThis.x = 0'); - -assert.throws(TypeError, () => { - new r.evaluate("globalThis.x += 1;"); -}, '`new r.evaluate("...")` throws TypeError'); - -assert.sameValue(r.evaluate('globalThis.x'), 0, 'No code evaluated in the new expression'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/returns-symbol-values.js b/js/src/tests/test262/built-ins/Realm/prototype/evaluate/returns-symbol-values.js deleted file mode 100644 index 34a81e3aa68b..000000000000 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/returns-symbol-values.js +++ /dev/null @@ -1,26 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm.prototype.evaluate -description: > - Realm.prototype.evaluate returns symbol values -features: [callable-boundary-realms] ----*/ - -assert.sameValue( - typeof Realm.prototype.evaluate, - 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' -); - -const r = new Realm(); -const s = r.evaluate('Symbol()'); - -assert.sameValue(typeof s, 'symbol'); -assert.sameValue(s.constructor, Symbol, 'primitive does not expose other Realm constructor'); -assert.sameValue(Object.getPrototypeOf(s), Symbol.prototype); -assert.sameValue(r.evaluate('Symbol.for("x")'), Symbol.for('x')); -assert.sameValue(Symbol.prototype.toString.call(s), 'Symbol()'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/validates-realm-object.js b/js/src/tests/test262/built-ins/Realm/prototype/evaluate/validates-realm-object.js deleted file mode 100644 index b0627decc11e..000000000000 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/validates-realm-object.js +++ /dev/null @@ -1,24 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm.prototype.evaluate -description: > - Realm.prototype.evaluate validates realm object. -features: [callable-boundary-realms] ----*/ - -assert.sameValue( - typeof Realm.prototype.evaluate, - 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' -); - -const r = new Realm(); -const bogus = {}; - -assert.throws(TypeError, function() { - r.evaluate.call(bogus, ''); -}, 'throws a TypeError if this is not a Realm object'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/import-value.js b/js/src/tests/test262/built-ins/Realm/prototype/importValue/import-value.js deleted file mode 100644 index 50a17e02d2bf..000000000000 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/import-value.js +++ /dev/null @@ -1,24 +0,0 @@ -// |reftest| skip module async -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm.prototype.importvalue -description: > - Realm.prototype.importValue can import a value. -flags: [async, module] -features: [callable-boundary-realms] ----*/ - -assert.sameValue( - typeof Realm.prototype.importValue, - 'function', - 'This test must fail if Realm.prototype.importValue is not a function' -); - -const r = new Realm(); - -r.importValue('./import-value_FIXTURE.js', 'x').then(x => { - - assert.sameValue(x, 1); - -}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/not-constructor.js b/js/src/tests/test262/built-ins/Realm/prototype/importValue/not-constructor.js deleted file mode 100644 index 0065d2910b9f..000000000000 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/not-constructor.js +++ /dev/null @@ -1,34 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm.prototype.importvalue -description: > - Realm.prototype.importValue is not a constructor. -includes: [isConstructor.js] -features: [callable-boundary-realms, Reflect.construct] ----*/ - -assert.sameValue( - typeof Realm.prototype.importValue, - 'function', - 'This test must fail if Realm.prototype.importValue is not a function' -); - -assert.sameValue( - isConstructor(Realm.prototype.importValue), - false, - 'isConstructor(Realm.prototype.importValue) must return false' -); - -assert.throws(TypeError, () => { - new Realm.prototype.importValue("", "name"); -}, '`new Realm.prototype.importValue("")` throws TypeError'); - -const r = new Realm(); - -assert.throws(TypeError, () => { - new r.imporValue("./import-value_FIXTURE.js", "x"); -}, '`new r.imporValue("...")` throws TypeError'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/specifier-tostring.js b/js/src/tests/test262/built-ins/Realm/prototype/importValue/specifier-tostring.js deleted file mode 100644 index 466dd81b6b07..000000000000 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/specifier-tostring.js +++ /dev/null @@ -1,33 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm.prototype.importvalue -description: > - Realm.prototype.importValue coerces specifier to string. -features: [callable-boundary-realms] ----*/ - -assert.sameValue( - typeof Realm.prototype.importValue, - 'function', - 'This test must fail if Realm.prototype.importValue is not a function' -); - -const r = new Realm(); -let count = 0; - -const specifier = { - toString() { - count += 1; - throw new Test262Error(); - } -}; - -assert.throws(Test262Error, () => { - r.importValue(specifier); -}); - -assert.sameValue(count, 1); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/validates-realm-object.js b/js/src/tests/test262/built-ins/Realm/prototype/importValue/validates-realm-object.js deleted file mode 100644 index 24e2a3e7bb2e..000000000000 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/validates-realm-object.js +++ /dev/null @@ -1,24 +0,0 @@ -// |reftest| skip -- callable-boundary-realms is not supported -// Copyright (C) 2021 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-realm.prototype.importvalue -description: > - Realm.prototype.importValue validates realm object. -features: [callable-boundary-realms] ----*/ - -assert.sameValue( - typeof Realm.prototype.importValue, - 'function', - 'This test must fail if Realm.prototype.importValue is not a function' -); - -const r = new Realm(); -const bogus = {}; - -assert.throws(TypeError, function() { - r.importValue.call(bogus, "specifier", "name"); -}, 'throws a TypeError if this is not a Realm object'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/return-from-accessor-descriptor.js b/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/return-from-accessor-descriptor.js index 48c17a004c49..e4200db1c2d9 100644 --- a/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/return-from-accessor-descriptor.js +++ b/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/return-from-accessor-descriptor.js @@ -45,10 +45,9 @@ Object.defineProperty(o1, 'p', { var result = Reflect.getOwnPropertyDescriptor(o1, 'p'); -assert( - compareArray( - Object.getOwnPropertyNames(result), ['get', 'set', 'enumerable', 'configurable'] - ) +assert.compareArray( + Object.getOwnPropertyNames(result), + ['get', 'set', 'enumerable', 'configurable'] ); assert.sameValue(result.enumerable, false); assert.sameValue(result.configurable, true); diff --git a/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/return-from-data-descriptor.js b/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/return-from-data-descriptor.js index 1967fe9d7f16..6acc6cdcff63 100644 --- a/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/return-from-data-descriptor.js +++ b/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/return-from-data-descriptor.js @@ -21,10 +21,9 @@ var o1 = { var result = Reflect.getOwnPropertyDescriptor(o1, 'p'); -assert( - compareArray( - Object.getOwnPropertyNames(result), ['value', 'writable', 'enumerable', 'configurable'] - ) +assert.compareArray( + Object.getOwnPropertyNames(result), + ['value', 'writable', 'enumerable', 'configurable'] ); assert.sameValue(result.value, 'foo'); assert.sameValue(result.enumerable, true); diff --git a/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/symbol-property.js b/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/symbol-property.js index 12a4d3699629..ed4956702db5 100644 --- a/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/symbol-property.js +++ b/js/src/tests/test262/built-ins/Reflect/getOwnPropertyDescriptor/symbol-property.js @@ -27,10 +27,9 @@ o[s] = 42; var result = Reflect.getOwnPropertyDescriptor(o, s); -assert( - compareArray( - Object.getOwnPropertyNames(result), ['value', 'writable', 'enumerable', 'configurable'] - ) +assert.compareArray( + Object.getOwnPropertyNames(result), + ['value', 'writable', 'enumerable', 'configurable'] ); assert.sameValue(result.value, 42); assert.sameValue(result.enumerable, true); diff --git a/js/src/tests/test262/built-ins/Reflect/ownKeys/return-array-with-own-keys-only.js b/js/src/tests/test262/built-ins/Reflect/ownKeys/return-array-with-own-keys-only.js index 0f3ae2f89e4d..1d23fd7b3216 100644 --- a/js/src/tests/test262/built-ins/Reflect/ownKeys/return-array-with-own-keys-only.js +++ b/js/src/tests/test262/built-ins/Reflect/ownKeys/return-array-with-own-keys-only.js @@ -23,9 +23,6 @@ var o = Object.create(proto); o.p1 = 42; o.p2 = 43; o.p3 = 44; -assert( - compareArray(Reflect.ownKeys(o), ['p1', 'p2', 'p3']), - 'return object own keys' -); +assert.compareArray(Reflect.ownKeys(o), ['p1', 'p2', 'p3'], 'return object own keys'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Reflect/ownKeys/return-empty-array.js b/js/src/tests/test262/built-ins/Reflect/ownKeys/return-empty-array.js index 50bc23159252..a43aadca9e14 100644 --- a/js/src/tests/test262/built-ins/Reflect/ownKeys/return-empty-array.js +++ b/js/src/tests/test262/built-ins/Reflect/ownKeys/return-empty-array.js @@ -15,12 +15,12 @@ includes: [compareArray.js] features: [Reflect] ---*/ -assert(compareArray(Reflect.ownKeys({}), [])); +assert.compareArray(Reflect.ownKeys({}), []); var o = { d: 42 }; delete o.d; -assert(compareArray(Reflect.ownKeys(o), [])); +assert.compareArray(Reflect.ownKeys(o), []); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Reflect/ownKeys/return-non-enumerable-keys.js b/js/src/tests/test262/built-ins/Reflect/ownKeys/return-non-enumerable-keys.js index 0387bb22a06f..10c4ee2d70df 100644 --- a/js/src/tests/test262/built-ins/Reflect/ownKeys/return-non-enumerable-keys.js +++ b/js/src/tests/test262/built-ins/Reflect/ownKeys/return-non-enumerable-keys.js @@ -15,15 +15,13 @@ includes: [compareArray.js] features: [Reflect] ---*/ -assert( - compareArray(Reflect.ownKeys([]), ['length']), +assert.compareArray( + Reflect.ownKeys([]), + ['length'], 'return non enumerable `length` from empty array' ); -assert( - compareArray(Reflect.ownKeys([, , 2]), ['2', 'length']), - 'return array keys' -); +assert.compareArray(Reflect.ownKeys([, , 2]), ['2', 'length'], 'return array keys'); var o = {}; Object.defineProperty(o, 'p1', { @@ -35,6 +33,6 @@ Object.defineProperty(o, 'p2', { enumerable: false }); -assert(compareArray(Reflect.ownKeys(o), ['p1', 'p2'])); +assert.compareArray(Reflect.ownKeys(o), ['p1', 'p2']); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/CharacterClassEscapes/shell.js b/js/src/tests/test262/built-ins/RegExp/CharacterClassEscapes/shell.js index b21e5a8be535..1c0f4dad1409 100644 --- a/js/src/tests/test262/built-ins/RegExp/CharacterClassEscapes/shell.js +++ b/js/src/tests/test262/built-ins/RegExp/CharacterClassEscapes/shell.js @@ -5,7 +5,7 @@ /*--- description: | Collection of functions used to assert the correctness of RegExp objects. -defines: [buildString, testPropertyEscapes, matchValidator] +defines: [buildString, testPropertyEscapes, testPropertyOfStrings, matchValidator] ---*/ function buildString(args) { @@ -33,23 +33,65 @@ function buildString(args) { return result; } -function testPropertyEscapes(regex, string, expression) { - if (!regex.test(string)) { +function printCodePoint(codePoint) { + const hex = codePoint + .toString(16) + .toUpperCase() + .padStart(6, "0"); + return `U+${hex}`; +} + +function printStringCodePoints(string) { + const buf = []; + for (const symbol of string) { + const formatted = printCodePoint(symbol.codePointAt(0)); + buf.push(formatted); + } + return buf.join(' '); +} + +function testPropertyEscapes(regExp, string, expression) { + if (!regExp.test(string)) { for (const symbol of string) { - const hex = symbol - .codePointAt(0) - .toString(16) - .toUpperCase() - .padStart(6, "0"); + printCodePoint(symbol.codePointAt(0)); assert( - regex.test(symbol), + regExp.test(symbol), `\`${ expression }\` should match U+${ hex } (\`${ symbol }\`)` ); } } } -// Returns a function that will validate RegExp match result +function testPropertyOfStrings(args) { + // Use member expressions rather than destructuring `args` for improved + // compatibility with engines that only implement assignment patterns + // partially or not at all. + const regExp = args.regExp; + const expression = args.expression; + const matchStrings = args.matchStrings; + const nonMatchStrings = args.nonMatchStrings; + const allStrings = matchStrings.join(''); + if (!regExp.test(allStrings)) { + for (const string of matchStrings) { + assert( + regExp.test(string), + `\`${ expression }\` should match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } + + const allNonMatchStrings = nonMatchStrings.join(''); + if (regExp.test(allNonMatchStrings)) { + for (const string of nonMatchStrings) { + assert( + !regExp.test(string), + `\`${ expression }\` should not match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } +} + +// Returns a function that validates a RegExp match result. // // Example: // diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T1.js index 0f4435d183dd..e2f3444095dc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T1.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T1 description: Tested RegExp is "a**" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("a**") throw SyntaxError. Actual: ' + (new RegExp("a**"))); + throw new Test262Error('#1.1: new RegExp("a**") throw SyntaxError. Actual: ' + (new RegExp("a**"))); } catch (e) { - if ((e instanceof SyntaxError !== true)) { - throw new Test262Error('#1.2: new RegExp("a**") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T10.js index 4402c8602f29..646a0ef2d581 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T10.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T10 description: Tested RegExp is "++a" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("++a") throw SyntaxError. Actual: ' + (new RegExp("++a"))); + throw new Test262Error('#1.1: new RegExp("++a") throw SyntaxError. Actual: ' + (new RegExp("++a"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("++a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T11.js index dd392cbd7472..af48741fb27f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T11.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T11 description: Tested RegExp is "?a" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("?a") throw SyntaxError. Actual: ' + (new RegExp("?a"))); + throw new Test262Error('#1.1: new RegExp("?a") throw SyntaxError. Actual: ' + (new RegExp("?a"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("?a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T12.js index 6d39681ba7b4..2ed3c6942ec3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T12.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T12 description: Tested RegExp is "??a" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("??a") throw SyntaxError. Actual: ' + (new RegExp("??a"))); + throw new Test262Error('#1.1: new RegExp("??a") throw SyntaxError. Actual: ' + (new RegExp("??a"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("??a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T13.js index c264b6c5e721..5d2177b2fac8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T13.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T13 description: Tested RegExp is "x{1}{1,}" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("x{1}{1,}") throw SyntaxError. Actual: ' + (new RegExp("x{1}{1,}"))); + throw new Test262Error('#1.1: new RegExp("x{1}{1,}") throw SyntaxError. Actual: ' + (new RegExp("x{1}{1,}"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("x{1}{1,}") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T14.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T14.js index 54e7b96411f9..ca498b4c874e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T14.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T14 description: Tested RegExp is "x{1,2}{1}" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("x{1,2}{1}") throw SyntaxError. Actual: ' + (new RegExp("x{1,2}{1}"))); + throw new Test262Error('#1.1: new RegExp("x{1,2}{1}") throw SyntaxError. Actual: ' + (new RegExp("x{1,2}{1}"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("x{1,2}{1}") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T15.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T15.js index 4465d25b3b8a..81463577344c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T15.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T15 description: Tested RegExp is "x{1,}{1}" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("x{1,}{1}") throw SyntaxError. Actual: ' + (new RegExp("x{1,}{1}"))); + throw new Test262Error('#1.1: new RegExp("x{1,}{1}") throw SyntaxError. Actual: ' + (new RegExp("x{1,}{1}"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("x{1,}{1}") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T16.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T16.js index c63f049efe05..2c0e2b2623a4 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T16.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T16.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T16 description: Tested RegExp is "x{0,1}{1,}" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("x{0,1}{1,}") throw SyntaxError. Actual: ' + (new RegExp("x{0,1}{1,}"))); + throw new Test262Error('#1.1: new RegExp("x{0,1}{1,}") throw SyntaxError. Actual: ' + (new RegExp("x{0,1}{1,}"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("x{0,1}{1,}") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T2.js index ac011d7bed59..579e63f433fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T2.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T2 description: Tested RegExp is "a***" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("a***") throw SyntaxError. Actual: ' + (new RegExp("a***"))); + throw new Test262Error('#1.1: new RegExp("a***") throw SyntaxError. Actual: ' + (new RegExp("a***"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("a***") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T3.js index cbb90abfce2f..a4d8955adb96 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T3.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T3 description: Tested RegExp is "a++" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("a++") throw SyntaxError. Actual: ' + (new RegExp("a++"))); + throw new Test262Error('#1.1: new RegExp("a++") throw SyntaxError. Actual: ' + (new RegExp("a++"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("a++") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T4.js index 47a618d09950..6032464c56a0 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T4.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T4 description: Tested RegExp is "a+++" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("a+++") throw SyntaxError. Actual: ' + (new RegExp("a+++"))); + throw new Test262Error('#1.1: new RegExp("a+++") throw SyntaxError. Actual: ' + (new RegExp("a+++"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("a+++") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T5.js index 4881117cdd60..ffe44746ba7c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T5.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T5 description: Tested RegExp is "a???" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("a???") throw SyntaxError. Actual: ' + (new RegExp("a???"))); + throw new Test262Error('#1.1: new RegExp("a???") throw SyntaxError. Actual: ' + (new RegExp("a???"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("a???") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T6.js index d989adadac00..d5f8dc4feb55 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T6.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T6 description: Tested RegExp is "a????" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("a????") throw SyntaxError. Actual: ' + (new RegExp("a????"))); + throw new Test262Error('#1.1: new RegExp("a????") throw SyntaxError. Actual: ' + (new RegExp("a????"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("a????") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T7.js index d65de061b55b..25a7541cd411 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T7.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T7 description: Tested RegExp is "*a" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("*a") throw SyntaxError. Actual: ' + (new RegExp("*a"))); + throw new Test262Error('#1.1: new RegExp("*a") throw SyntaxError. Actual: ' + (new RegExp("*a"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("*a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T8.js index 5b5671ec5fe3..34897392e5e6 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T8.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T8 description: Tested RegExp is "**a" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("**a") throw SyntaxError. Actual: ' + (new RegExp("**a"))); + throw new Test262Error('#1.1: new RegExp("**a") throw SyntaxError. Actual: ' + (new RegExp("**a"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("**a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T9.js index cac798a86723..f4b6e47fd8da 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.1_A1_T9.js @@ -7,13 +7,16 @@ es5id: 15.10.1_A1_T9 description: Tested RegExp is "+a" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("+a") throw SyntaxError. Actual: ' + (new RegExp("+a"))); + throw new Test262Error('#1.1: new RegExp("+a") throw SyntaxError. Actual: ' + (new RegExp("+a"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("+a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.1_T1.js index 09aa5c15ba45..18e2455db79e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.1_T1.js @@ -9,13 +9,11 @@ es5id: 15.10.2.10_A1.1_T1 description: Use \t in RegExp and \u0009 in tested string ---*/ -//CHECK#1 var arr = /\t/.exec("\u0009"); if ((arr === null) || (arr[0] !== "\u0009")) { throw new Test262Error('#1: var arr = /\\t/.exec("\\u0009"); arr[0] === "\\u0009". Actual. ' + (arr && arr[0])); } -//CHECK#2 var arr = /\t\t/.exec("a\u0009\u0009b"); if ((arr === null) || (arr[0] !== "\u0009\u0009")) { throw new Test262Error('#2: var arr = /\\t\\t/.exec("a\\u0009\\u0009b"); arr[0] === "\\u0009\\u0009". Actual. ' + (arr && arr[0])); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.2_T1.js index cb5c240c30d6..0ca647f8ed3b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.2_T1.js @@ -9,13 +9,11 @@ es5id: 15.10.2.10_A1.2_T1 description: Use \n in RegExp and \u000A in tested string ---*/ -//CHECK#1 var arr = /\n/.exec("\u000A"); if ((arr === null) || (arr[0] !== "\u000A")) { throw new Test262Error('#1: var arr = /\\n/.exec("\\u000A"); arr[0] === "\\u000A". Actual. ' + (arr && arr[0])); } -//CHECK#2 var arr = /\n\n/.exec("a\u000A\u000Ab"); if ((arr === null) || (arr[0] !== "\u000A\u000A")) { throw new Test262Error('#2: var arr = /\\n\\n/.exec("a\\u000A\\u000Ab"); arr[0] === "\\u000A\\u000A". Actual. ' + (arr && arr[0])); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.3_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.3_T1.js index 10f3b9289148..f27ebb19ef7a 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.3_T1.js @@ -9,13 +9,11 @@ es5id: 15.10.2.10_A1.3_T1 description: Use \v in RegExp and \u000B in tested string ---*/ -//CHECK#1 var arr = /\v/.exec("\u000B"); if ((arr === null) || (arr[0] !== "\u000B")) { throw new Test262Error('#1: var arr = /\\v/.exec("\\u000B"); arr[0] === "\\u000B". Actual. ' + (arr && arr[0])); } -//CHECK#2 var arr = /\v\v/.exec("a\u000B\u000Bb"); if ((arr === null) || (arr[0] !== "\u000B\u000B")) { throw new Test262Error('#2: var arr = /\\v\\v/.exec("a\\u000B\\u000Bb"); arr[0] === "\\u000B\\u000B". Actual. ' + (arr && arr[0])); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.4_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.4_T1.js index e794276c52c6..27d31424ecab 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.4_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.4_T1.js @@ -9,13 +9,11 @@ es5id: 15.10.2.10_A1.4_T1 description: Use \f in RegExp and \u000C in tested string ---*/ -//CHECK#1 var arr = /\f/.exec("\u000C"); if ((arr === null) || (arr[0] !== "\u000C")) { throw new Test262Error('#1: var arr = /\\f/.exec("\\u000C"); arr[0] === "\\u000C". Actual. ' + (arr && arr[0])); } -//CHECK#2 var arr = /\f\f/.exec("a\u000C\u000Cb"); if ((arr === null) || (arr[0] !== "\u000C\u000C")) { throw new Test262Error('#2: var arr = /\\f\\f/.exec("a\\u000C\\u000Cb"); arr[0] === "\\u000C\\u000C". Actual. ' + (arr && arr[0])); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.5_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.5_T1.js index 211acbaf9367..86658679d148 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.5_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A1.5_T1.js @@ -9,13 +9,11 @@ es5id: 15.10.2.10_A1.5_T1 description: Use \r in RegExp and \u000D in tested string ---*/ -//CHECK#1 var arr = /\r/.exec("\u000D"); if ((arr === null) || (arr[0] !== "\u000D")) { throw new Test262Error('#1: var arr = /\\r/.exec("\\u000D"); arr[0] === "\\u000D". Actual. ' + (arr && arr[0])); } -//CHECK#2 var arr = /\r\r/.exec("a\u000D\u000Db"); if ((arr === null) || (arr[0] !== "\u000D\u000D")) { throw new Test262Error('#2: var arr = /\\r\\r/.exec("a\\u000D\\u000Db"); arr[0] === "\\u000D\\u000D". Actual. ' + (arr && arr[0])); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A2.1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A2.1_T1.js index fefcd48b898d..5ccba147194a 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A2.1_T1.js @@ -7,8 +7,7 @@ es5id: 15.10.2.10_A2.1_T1 description: "ControlLetter :: A - Z" ---*/ -//CHECK#0041-005A -var result = true; +var result = true; for (var alpha = 0x0041; alpha <= 0x005A; alpha++) { var str = String.fromCharCode(alpha % 32); var arr = (new RegExp("\\c" + String.fromCharCode(alpha))).exec(str); @@ -17,8 +16,6 @@ for (var alpha = 0x0041; alpha <= 0x005A; alpha++) { } } -if (result !== true) { - throw new Test262Error('#1: CharacterEscape :: c A - Z'); -} +assert.sameValue(result, true, 'The value of result is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A2.1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A2.1_T2.js index 3bf5d2b769a2..a2506137bab0 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A2.1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A2.1_T2.js @@ -7,8 +7,7 @@ es5id: 15.10.2.10_A2.1_T2 description: "ControlLetter :: a - z" ---*/ -//CHECK#0061-007A -var result = true; +var result = true; for (var alpha = 0x0061; alpha <= 0x007A; alpha++) { var str = String.fromCharCode(alpha % 32); var arr = (new RegExp("\\c" + String.fromCharCode(alpha))).exec(str); @@ -17,8 +16,6 @@ for (var alpha = 0x0061; alpha <= 0x007A; alpha++) { } } -if (result !== true) { - throw new Test262Error('#1: CharacterEscape :: c a - z'); -} +assert.sameValue(result, true, 'The value of result is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A3.1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A3.1_T1.js index fe2e29e6290c..005de2849d56 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A3.1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A3.1_T1.js @@ -7,25 +7,21 @@ es5id: 15.10.2.10_A3.1_T1 description: Tested string include equal unicode symbols ---*/ -//CHECK#0 var arr = /\x00/.exec("\u0000"); if ((arr === null) || (arr[0] !== "\u0000")) { throw new Test262Error('#0: var arr = /\\x00/.exec(\\u0000); arr[0] === "\\u0000". Actual. ' + (arr && arr[0])); } -//CHECK#1 var arr = /\x01/.exec("\u0001"); if ((arr === null) || (arr[0] !== "\u0001")) { throw new Test262Error('#1: var arr = /\\x01/.exec(\\u0001); arr[0] === "\\u0001". Actual. ' + (arr && arr[0])); } -//CHECK#2 var arr = /\x0A/.exec("\u000A"); if ((arr === null) || (arr[0] !== "\u000A")) { throw new Test262Error('#2: var arr = /\\x0A/.exec(\\u000A); arr[0] === "\\u000A". Actual. ' + (arr && arr[0])); } -//CHECK#3 var arr = /\xFF/.exec("\u00FF"); if ((arr === null) || (arr[0] !== "\u00FF")) { throw new Test262Error('#3: var arr = /\\xFF/.exec(\\u00FF); arr[0] === "\\u00FF". Actual. ' + (arr && arr[0])); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A3.1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A3.1_T2.js index 9e694b164fc6..11b7ff7e4077 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A3.1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A3.1_T2.js @@ -7,7 +7,6 @@ es5id: 15.10.2.10_A3.1_T2 description: Checking ENGLISH CAPITAL ALPHABET and english small alphabet ---*/ -//CHECK#41-5A var hex = ["\\x41", "\\x42", "\\x43", "\\x44", "\\x45", "\\x46", "\\x47", "\\x48", "\\x49", "\\x4A", "\\x4B", "\\x4C", "\\x4D", "\\x4E", "\\x4F", "\\x50", "\\x51", "\\x52", "\\x53", "\\x54", "\\x55", "\\x56", "\\x57", "\\x58", "\\x59", "\\x5A"]; var character = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]; var result = true; @@ -18,11 +17,8 @@ for (var index = 0; index < hex.length; index++) { } } -if (result !== true) { - throw new Test262Error('#1: ENGLISH CAPITAL ALPHABET'); -} +assert.sameValue(result, true, 'The value of result is expected to be true'); -//CHECK#61-7A hex = ["\\x61", "\\x62", "\\x63", "\\x64", "\\x65", "\\x66", "\\x67", "\\x68", "\\x69", "\\x6A", "\\x6B", "\\x6C", "\\x6D", "\\x6E", "\\x6F", "\\x70", "\\x71", "\\x72", "\\x73", "\\x74", "\\x75", "\\x76", "\\x77", "\\x78", "\\x79", "\\x7A"]; character = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]; var result = true; @@ -33,8 +29,6 @@ for (index = 0; index < hex.length; index++) { } } -if (result !== true) { - throw new Test262Error('#1: english small alphabet'); -} +assert.sameValue(result, true, 'The value of result is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T1.js index 98d2cfe0f865..e5c056a85927 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T1.js @@ -9,37 +9,31 @@ es5id: 15.10.2.10_A4.1_T1 description: RegExp and tested string include uncode symbols ---*/ -//CHECK#0 var arr = /\u0000/.exec("\u0000"); if ((arr === null) || (arr[0] !== "\u0000")) { throw new Test262Error('#0: var arr = /\\u0000/.exec(\\u0000); arr[0] === "\\u0000". Actual. ' + (arr && arr[0])); } -//CHECK#1 var arr = /\u0001/.exec("\u0001"); if ((arr === null) || (arr[0] !== "\u0001")) { throw new Test262Error('#1: var arr = /\\u0001/.exec(\\u0001); arr[0] === "\\u0001". Actual. ' + (arr && arr[0])); } -//CHECK#2 var arr = /\u000A/.exec("\u000A"); if ((arr === null) || (arr[0] !== "\u000A")) { throw new Test262Error('#2: var arr = /\\u000A/.exec(\\u000A); arr[0] === "\\u000A". Actual. ' + (arr && arr[0])); } -//CHECK#3 var arr = /\u00FF/.exec("\u00FF"); if ((arr === null) || (arr[0] !== "\u00FF")) { throw new Test262Error('#3: var arr = /\\u00FF/.exec(\\u00FF); arr[0] === "\\u00FF". Actual. ' + (arr && arr[0])); } -//CHECK#4 var arr = /\u0FFF/.exec("\u0FFF"); if ((arr === null) || (arr[0] !== "\u0FFF")) { throw new Test262Error('#4: var arr = /\\u0FFF/.exec(\\u0FFF); arr[0] === "\\u0FFF". Actual. ' + (arr && arr[0])); } -//CHECK#5 var arr = /\uFFFF/.exec("\uFFFF"); if ((arr === null) || (arr[0] !== "\uFFFF")) { throw new Test262Error('#5: var arr = /\\uFFFF/.exec(\\uFFFF); arr[0] === "\\uFFFF". Actual. ' + (arr && arr[0])); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T2.js index a7f86cc94010..7cb62b2d5263 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T2.js @@ -11,7 +11,6 @@ description: > alphabet ---*/ -//CHECK#41-5A var hex = ["\\u0041", "\\u0042", "\\u0043", "\\u0044", "\\u0045", "\\u0046", "\\u0047", "\\u0048", "\\u0049", "\\u004A", "\\u004B", "\\u004C", "\\u004D", "\\u004E", "\\u004F", "\\u0050", "\\u0051", "\\u0052", "\\u0053", "\\u0054", "\\u0055", "\\u0056", "\\u0057", "\\u0058", "\\u0059", "\\u005A"]; var character = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]; var result = true; @@ -22,11 +21,8 @@ for (var index = 0; index < hex.length; index++) { } } -if (result !== true) { - throw new Test262Error('#1: ENGLISH CAPITAL ALPHABET'); -} +assert.sameValue(result, true, 'The value of result is expected to be true'); -//CHECK#61-7A hex = ["\\u0061", "\\u0062", "\\u0063", "\\u0064", "\\u0065", "\\u0066", "\\u0067", "\\u0068", "\\u0069", "\\u006A", "\\u006B", "\\u006C", "\\u006D", "\\u006E", "\\u006F", "\\u0070", "\\u0071", "\\u0072", "\\u0073", "\\u0074", "\\u0075", "\\u0076", "\\u0077", "\\u0078", "\\u0079", "\\u007A"]; character = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]; var result = true; @@ -37,8 +33,6 @@ for (index = 0; index < hex.length; index++) { } } -if (result !== true) { - throw new Test262Error('#1: english small alphabet'); -} +assert.sameValue(result, true, 'The value of result is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T3.js index 6ae5eca13cd8..e10f55ec2711 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A4.1_T3.js @@ -11,7 +11,6 @@ description: > alphabet in unicode notation ---*/ -//CHECK#0410-042F, 0401 var hex = ["\\u0410", "\\u0411", "\\u0412", "\\u0413", "\\u0414", "\\u0415", "\\u0416", "\\u0417", "\\u0418", "\\u0419", "\\u041A", "\\u041B", "\\u041C", "\\u041D", "\\u041E", "\\u041F", "\\u0420", "\\u0421", "\\u0422", "\\u0423", "\\u0424", "\\u0425", "\\u0426", "\\u0427", "\\u0428", "\\u0429", "\\u042A", "\\u042B", "\\u042C", "\\u042D", "\\u042E", "\\u042F", "\\u0401"]; var character = ["\u0410", "\u0411", "\u0412", "\u0413", "\u0414", "\u0415", "\u0416", "\u0417", "\u0418", "\u0419", "\u041A", "\u041B", "\u041C", "\u041D", "\u041E", "\u041F", "\u0420", "\u0421", "\u0422", "\u0423", "\u0424", "\u0425", "\u0426", "\u0427", "\u0428", "\u0429", "\u042A", "\u042B", "\u042C", "\u042D", "\u042E", "\u042F", "\u0401"]; var result = true; @@ -22,11 +21,8 @@ for (var index = 0; index < hex.length; index++) { } } -if (result !== true) { - throw new Test262Error('#1: RUSSIAN CAPITAL ALPHABET'); -} +assert.sameValue(result, true, 'The value of result is expected to be true'); -//CHECK#0430-044F, 0451 hex = ["\\u0430", "\\u0431", "\\u0432", "\\u0433", "\\u0434", "\\u0435", "\\u0436", "\\u0437", "\\u0438", "\\u0439", "\\u043A", "\\u043B", "\\u043C", "\\u043D", "\\u043E", "\\u043F", "\\u0440", "\\u0441", "\\u0442", "\\u0443", "\\u0444", "\\u0445", "\\u0446", "\\u0447", "\\u0448", "\\u0449", "\\u044A", "\\u044B", "\\u044C", "\\u044D", "\\u044E", "\\u044F", "\\u0451"]; character = ["\u0430", "\u0431", "\u0432", "\u0433", "\u0434", "\u0435", "\u0436", "\u0437", "\u0438", "\u0439", "\u043A", "\u043B", "\u043C", "\u043D", "\u043E", "\u043F", "\u0440", "\u0441", "\u0442", "\u0443", "\u0444", "\u0445", "\u0446", "\u0447", "\u0448", "\u0449", "\u044A", "\u044B", "\u044C", "\u044D", "\u044E", "\u044F", "\u0451"]; var result = true; @@ -37,8 +33,6 @@ for (index = 0; index < hex.length; index++) { } } -if (result !== true) { - throw new Test262Error('#1: russian small alphabet'); -} +assert.sameValue(result, true, 'The value of result is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A5.1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A5.1_T1.js index 60f66e2c394a..fdd568379cc6 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A5.1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.10_A5.1_T1.js @@ -9,7 +9,6 @@ es5id: 15.10.2.10_A5.1_T1 description: "Tested string is \"~`!@#$%^&*()-+={[}]|\\\\:;'<,>./?\" + '\"'" ---*/ -//CHECK#1 var non_ident = "~`!@#$%^&*()-+={[}]|\\:;'<,>./?" + '"'; for (var k = 0; k < non_ident.length; ++k) { var arr = new RegExp("\\" + non_ident[k], "g").exec(non_ident); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T1.js index 0dcd8a15c391..d9cdd5f2ce58 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T1.js @@ -9,13 +9,11 @@ description: > consisting of a character (Unicodevalue0000) ---*/ -//CHECK#1 var arr = /\0/.exec("\u0000"); if ((arr === null) || (arr[0] !== "\u0000")) { throw new Test262Error('#1: var arr = /\\0/.exec(\\u0000); arr[0] === "\\u0000". Actual. ' + (arr && arr[0])); } -//CHECK#2 var arr = (new RegExp("\\0")).exec("\u0000"); if ((arr === null) || (arr[0] !== "\u0000")) { throw new Test262Error('#2: var arr = (new RegExp("\\0")).exec(\\u0000); arr[0] === "\\u0000". Actual. ' + (arr && arr[0])); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T4.js index bbc25a3cfc7e..107cf8b1194a 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T4.js @@ -9,12 +9,10 @@ description: DecimalIntegerLiteral is not 0 var arr = /(A)\1/.exec("AA"); -//CHECK#1 if ((arr === null) || (arr[0] !== "AA")) { throw new Test262Error('#1: var arr = (/(A)\\1/.exec("AA")); arr[0] === "AA". Actual. ' + (arr && arr[0])); } -//CHECK#2 if ((arr === null) || (arr[1] !== "A")) { throw new Test262Error('#2: var arr = (/(A)\\1/.exec("AA")); arr[1] === "A". Actual. ' + (arr && arr[1])); } diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T5.js index 94e9334f2576..b1565c418cf8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T5.js @@ -9,12 +9,10 @@ description: DecimalIntegerLiteral is not 0 var arr = /\1(A)/.exec("AA"); -//CHECK#1 if ((arr === null) || (arr[0] !== "A")) { throw new Test262Error('#1: var arr = (/\\1(A)/.exec("AA")); arr[0] === "A". Actual. ' + (arr && arr[0])); } -//CHECK#2 if ((arr === null) || (arr[1] !== "A")) { throw new Test262Error('#2: var arr = (/\\1(A)/.exec("AA")); arr[1] === "A". Actual. ' + (arr && arr[1])); } diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T6.js index 7358043ca336..7c42d31a1d60 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T6.js @@ -9,17 +9,14 @@ description: DecimalIntegerLiteral is not 0 var arr = /(A)\1(B)\2/.exec("AABB"); -//CHECK#1 if ((arr === null) || (arr[0] !== "AABB")) { throw new Test262Error('#1: var arr = /(A)\\1(B)\\2/.exec("AABB"); arr[0] === "AABB". Actual. ' + (arr && arr[0])); } -//CHECK#2 if ((arr === null) || (arr[1] !== "A")) { throw new Test262Error('#2: var arr = /(A)\\1(B)\\2/.exec("AABB"); arr[1] === "A". Actual. ' + (arr && arr[1])); } -//CHECK#3 if ((arr === null) || (arr[2] !== "B")) { throw new Test262Error('#3: var arr = /(A)\\1(B)\\2/.exec("AABB"); arr[2] === "B". Actual. ' + (arr && arr[2])); } diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T7.js index ea45725a2dc6..7e1f5d9dd57b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T7.js @@ -9,17 +9,14 @@ description: DecimalIntegerLiteral is not 0 var arr = /\1(A)(B)\2/.exec("ABB"); -//CHECK#1 if ((arr === null) || (arr[0] !== "ABB")) { throw new Test262Error('#1: var arr = /\\1(A)(B)\\2/.exec("ABB"); arr[0] === "ABB". Actual. ' + (arr && arr[0])); } -//CHECK#2 if ((arr === null) || (arr[1] !== "A")) { throw new Test262Error('#2: var arr = /\\1(A)(B)\\2/.exec("ABB"); arr[1] === "A". Actual. ' + (arr && arr[1])); } -//CHECK#3 if ((arr === null) || (arr[2] !== "B")) { throw new Test262Error('#3: var arr = /\\1(A)(B)\\2/.exec("ABB"); arr[2] === "B". Actual. ' + (arr && arr[2])); } diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T8.js index cbee58ee460e..51b516c8a1ef 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T8.js @@ -9,14 +9,12 @@ description: DecimalIntegerLiteral is not 0 var arr = /((((((((((A))))))))))\1\2\3\4\5\6\7\8\9\10/.exec("AAAAAAAAAAA"); -//CHECK#1 if ((arr === null) || (arr[0] !== "AAAAAAAAAAA")) { throw new Test262Error('#1: var arr = /((((((((((A))))))))))\\1\\2\\3\\4\\5\\6\\7\\8\\9\\10/.exec("AAAAAAAAAAA"); arr[0] === "AAAAAAAAAAA". Actual. ' + (arr && arr[0])); } for (var i = 1; i <= 10; i++) { - //CHECK#i - if ((arr === null) || (arr[i] !== "A")) { + if ((arr === null) || (arr[i] !== "A")) { throw new Test262Error('#2: var arr = /((((((((((A))))))))))\\1\\2\\3\\4\\5\\6\\7\\8\\9\\10/.exec("AAAAAAAAAAA"); arr[' + i + '] === "A". Actual. ' + (arr && arr[i])); } } diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T9.js index 38c52743fef5..0ed36cd7e985 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.11_A1_T9.js @@ -9,14 +9,12 @@ description: DecimalIntegerLiteral is not 0 var arr = /((((((((((A))))))))))\10\9\8\7\6\5\4\3\2\1/.exec("AAAAAAAAAAA"); -//CHECK#1 if ((arr === null) || (arr[0] !== "AAAAAAAAAAA")) { throw new Test262Error('#1: var arr = /((((((((((A))))))))))\\10\\9\\8\\7\\6\\5\\4\\3\\2\\1/.exec("AAAAAAAAAAA"); arr[0] === "AAAAAAAAAAA". Actual. ' + (arr && arr[0])); } for (var i = 1; i <= 10; i++) { - //CHECK#i - if ((arr === null) || (arr[i] !== "A")) { + if ((arr === null) || (arr[i] !== "A")) { throw new Test262Error('#2: var arr = /((((((((((A))))))))))\\10\\9\\8\\7\\6\\5\\4\\3\\2\\1/.exec("AAAAAAAAAAA"); arr[' + i + '] === "A". Actual. ' + (arr && arr[i])); } } diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.12_A3_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.12_A3_T5.js index 64de182cef00..d4dcdc3f0488 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.12_A3_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.12_A3_T5.js @@ -9,13 +9,14 @@ es5id: 15.10.2.12_A3_T5 description: non-w ---*/ -//CHECK#1 var non_w = "\f\n\r\t\v~`!@#$%^&*()-+={[}]|\\:;'<,>./? " + '"'; -if (/\w/.exec(non_w) !== null) { - throw new Test262Error('#1: non-w'); -} -//CHECK#2 +assert.sameValue( + /\w/.exec(non_w), + null, + '/w/.exec(""fnrtv~`!@#$%^&*()-+={[}]|:;\'<,>./? " + \'"\'") must return null' +); + var non_W = "_0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; var regexp_w = /\w/g; var k = 0; @@ -23,8 +24,6 @@ while (regexp_w.exec(non_W) !== null) { k++; } -if (non_W.length !== k) { - throw new Test262Error('#2: non-W'); -} +assert.sameValue(non_W.length, k, 'The value of non_W.length is expected to equal the value of k'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.12_A4_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.12_A4_T5.js index 668167cd9622..f3bcc0c6d064 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.12_A4_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.12_A4_T5.js @@ -9,7 +9,6 @@ es5id: 15.10.2.12_A4_T5 description: non-w ---*/ -//CHECK#1 var non_w = "\f\n\r\t\v~`!@#$%^&*()-+={[}]|\\:;'<,>./? " + '"'; var regexp_W = /\W/g; var k = 0; @@ -17,14 +16,14 @@ while (regexp_W.exec(non_w) !== null) { k++; } -if (non_w.length !== k) { - throw new Test262Error('#1: non-w'); -} +assert.sameValue(non_w.length, k, 'The value of non_w.length is expected to equal the value of k'); -//CHECK#2 var non_W = "_0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -if (/\W/.exec(non_W) !== null) { - throw new Test262Error('#2: non-W'); -} + +assert.sameValue( + /\W/.exec(non_W), + null, + '/W/.exec(""_0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"") must return null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T1.js index 30d19b2eb438..9b535a2e3f8e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T1.js @@ -10,11 +10,7 @@ es5id: 15.10.2.13_A1_T1 description: Execute /[]a/.test("\0a\0a") and check results ---*/ -var __executed = /[]a/.test("\0a\0a");; - -//CHECK#1 - if (__executed) { - throw new Test262Error('#1: /[]a/.test("\\0a\\0a") === false'); -} +var __executed = /[]a/.test("\0a\0a"); +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T10.js index ffc2d8c09664..aa816075ad30 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T10.js @@ -16,26 +16,30 @@ var __expected = ["abc324234"]; __expected.index = 2; __expected.input = "\n\n\abc324234\n"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[a-c\\d]+/.exec("\\n\\n\\abc324234\\n"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[a-c\\d]+/.exec("\\n\\n\\abc324234\\n"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[a-c\\d]+/.exec("\\n\\n\\abc324234\\n"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[a-c\\d]+/.exec("\\n\\n\\abc324234\\n"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T11.js index aad5965f17c3..1c490e122eed 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T11.js @@ -16,26 +16,30 @@ var __expected = ["abc"]; __expected.index = 0; __expected.input = "abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /ab[.]?c/.exec("abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /ab[.]?c/.exec("abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /ab[.]?c/.exec("abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /ab[.]?c/.exec("abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T12.js index e6276f861642..20f9efd7d8d2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T12.js @@ -16,26 +16,30 @@ var __expected = ["abc"]; __expected.index = 0; __expected.input = "abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a[b]c/.exec("abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a[b]c/.exec("abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a[b]c/.exec("abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a[b]c/.exec("abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T13.js index 5f6963ef87d3..944e396867f8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T13.js @@ -18,26 +18,30 @@ var __expected = ["def"]; __expected.index = 15; __expected.input = "a1b b2c c3d def f4g"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[a-z][^1-9][a-z]/.exec("a1b b2c c3d def f4g"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[a-z][^1-9][a-z]/.exec("a1b b2c c3d def f4g"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[a-z][^1-9][a-z]/.exec("a1b b2c c3d def f4g"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[a-z][^1-9][a-z]/.exec("a1b b2c c3d def f4g"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T14.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T14.js index 6a55b9be9987..dc9072d83547 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T14.js @@ -16,26 +16,30 @@ var __expected = ["*&$"]; __expected.index = 3; __expected.input = "123*&$abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[*&$]{3}/.exec("123*&$abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[*&$]{3}/.exec("123*&$abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[*&$]{3}/.exec("123*&$abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[*&$]{3}/.exec("123*&$abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T15.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T15.js index 0a3a3b551dd4..2a0a1f1fe8af 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T15.js @@ -16,26 +16,30 @@ var __expected = ["1\nl"]; __expected.index = 4; __expected.input = "line1\nline2"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[\\d][\\n][^\\d]/.exec("line1\\nline2"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[\\d][\\n][^\\d]/.exec("line1\\nline2"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[\\d][\\n][^\\d]/.exec("line1\\nline2"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[\\d][\\n][^\\d]/.exec("line1\\nline2"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T17.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T17.js index c1b82276864e..e41ac621f683 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T17.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T17.js @@ -12,9 +12,6 @@ description: Execute /[]/.exec("a[b\n[]\tc]d") and check results var __executed = /[]/.exec("a[b\n[]\tc]d"); -//CHECK#1 -if (__executed !== null) { - throw new Test262Error('#1: /[]/.exec("a[b\\n[]\\tc]d") === false'); -} +assert.sameValue(__executed, null, 'The value of __executed is expected to be null'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T2.js index af4b32fe30c5..8bc8d7feb7ed 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T2.js @@ -10,11 +10,7 @@ es5id: 15.10.2.13_A1_T2 description: Execute /a[]/.test("\0a\0a") and check results ---*/ -var __executed = /a[]/.test("\0a\0a");; - -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /a[]/.test("\\0a\\0a") === false'); -} +var __executed = /a[]/.test("\0a\0a"); +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T3.js index 4f1be423fade..68a70433c2cb 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T3.js @@ -16,26 +16,30 @@ var __expected = ["qy"]; __expected.index = 2; __expected.input = "qYqy "; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /q[ax-zb](?=\\s+)/.exec("qYqy "); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /q[ax-zb](?=\\s+)/.exec("qYqy "); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /q[ax-zb](?=\\s+)/.exec("qYqy "); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /q[ax-zb](?=\\s+)/.exec("qYqy "); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T4.js index 03b3c89d2b36..60d7939f0f24 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T4.js @@ -16,26 +16,30 @@ var __expected = ["qy"]; __expected.index = 3; __expected.input = "tqaqy "; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /q[ax-zb](?=\\s+)/.exec("tqaqy "); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /q[ax-zb](?=\\s+)/.exec("tqaqy "); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /q[ax-zb](?=\\s+)/.exec("tqaqy "); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /q[ax-zb](?=\\s+)/.exec("tqaqy "); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T5.js index ad7cbebdca9c..04a47f75b8ca 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T5.js @@ -16,26 +16,30 @@ var __expected = ["qa"]; __expected.index = 1; __expected.input = "tqa\t qy "; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /q[ax-zb](?=\\s+)/.exec("tqa\\t qy "); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /q[ax-zb](?=\\s+)/.exec("tqa\\t qy "); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /q[ax-zb](?=\\s+)/.exec("tqa\\t qy "); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /q[ax-zb](?=\\s+)/.exec("tqa\\t qy "); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T6.js index e4785e37e9b5..e7ef9156b8c2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T6.js @@ -16,26 +16,30 @@ var __expected = ["abcde"]; __expected.index = 0; __expected.input = "abcde"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /ab[ercst]de/.exec("abcde"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /ab[ercst]de/.exec("abcde"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /ab[ercst]de/.exec("abcde"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /ab[ercst]de/.exec("abcde"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T7.js index 590cb26aaaf8..bbef9f124b99 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T7.js @@ -12,9 +12,6 @@ description: Execute /ab[erst]de/.test("abcde") and check results var __executed = /ab[erst]de/.test("abcde"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /ab[erst]de/.test("abcde") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T8.js index b9ebd728124a..5d616fca7208 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T8.js @@ -16,26 +16,30 @@ var __expected = ["defgh"]; __expected.index = 3; __expected.input = "abcdefghijkl"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[d-h]+/.exec("abcdefghijkl"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[d-h]+/.exec("abcdefghijkl"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[d-h]+/.exec("abcdefghijkl"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[d-h]+/.exec("abcdefghijkl"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T9.js index 9143f2acef09..eca4bdcd1479 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A1_T9.js @@ -16,26 +16,30 @@ var __expected = ["6de"]; __expected.index = 3; __expected.input = "abc6defghijkl"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[1234567].{2}/.exec("abc6defghijkl"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[1234567].{2}/.exec("abc6defghijkl"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[1234567].{2}/.exec("abc6defghijkl"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[1234567].{2}/.exec("abc6defghijkl"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T1.js index 9008b651daec..3c9b4032e014 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T1.js @@ -16,26 +16,30 @@ var __expected = ["\na"]; __expected.index = 1; __expected.input = "a\naba"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^]a/m.exec("a\\naba"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^]a/m.exec("a\\naba"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^]a/m.exec("a\\naba"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^]a/m.exec("a\\naba"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T2.js index ee7bb7ca2ba0..2ac8ff3c4afd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T2.js @@ -16,26 +16,30 @@ var __expected = ["a\t"]; __expected.index = 3; __expected.input = " a\t\n"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a[^]/.exec(" a\\t\\n"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a[^]/.exec(" a\\t\\n"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a[^]/.exec(" a\\t\\n"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a[^]/.exec(" a\\t\\n"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T3.js index 0bccef378603..42161ba17d4f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T3.js @@ -16,26 +16,30 @@ var __expected = ["aY "]; __expected.index = 9; __expected.input = "ab an az aY n"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a[^b-z]\\s+/.exec("ab an az aY n"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a[^b-z]\\s+/.exec("ab an az aY n"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a[^b-z]\\s+/.exec("ab an az aY n"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a[^b-z]\\s+/.exec("ab an az aY n"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T4.js index 63184e367d52..7c204f12ae29 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T4.js @@ -16,26 +16,30 @@ var __expected = ["easy"]; __expected.index = 0; __expected.input = "easy\bto\u0008ride"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^\\b]+/g.exec("easy\\bto\\u0008ride"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^\\b]+/g.exec("easy\\bto\\u0008ride"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^\\b]+/g.exec("easy\\bto\\u0008ride"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^\\b]+/g.exec("easy\\bto\\u0008ride"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T5.js index 0ced6a900a6b..d2ed2187aab9 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T5.js @@ -16,26 +16,30 @@ var __expected = ["abc"]; __expected.index = 0; __expected.input = "abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a[^1-9]c/.exec("abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a[^1-9]c/.exec("abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a[^1-9]c/.exec("abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a[^1-9]c/.exec("abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T6.js index 010facccdac5..46aefd0f037c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T6.js @@ -12,9 +12,6 @@ description: Execute /a[^b]c/.test("abc") and check results var __executed = /a[^b]c/.test("abc"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /a[^b]c/.test("abc") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T7.js index 4187166ba0db..cc9c45060f9f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T7.js @@ -16,26 +16,30 @@ var __expected = ["%&*@"]; __expected.index = 9; __expected.input = "abc#$%def%&*@ghi"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^a-z]{4}/.exec("abc#$%def%&*@ghi"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^a-z]{4}/.exec("abc#$%def%&*@ghi"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^a-z]{4}/.exec("abc#$%def%&*@ghi"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^a-z]{4}/.exec("abc#$%def%&*@ghi"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T8.js index 4dc047a9750f..16b262456d13 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A2_T8.js @@ -16,26 +16,30 @@ var __expected = ["a"]; __expected.index = 0; __expected.input = "abc#$%def%&*@ghi"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^]/.exec("abc#$%def%&*@ghi"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^]/.exec("abc#$%def%&*@ghi"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^]/.exec("abc#$%def%&*@ghi"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^]/.exec("abc#$%def%&*@ghi"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T1.js index e0fbe7923e11..f7410bc10bc0 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T1.js @@ -13,26 +13,30 @@ var __expected = ["c\bd"]; __expected.index = 2; __expected.input = "abc\bdef"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /.[\\b]./.exec("abc\\bdef"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /.[\\b]./.exec("abc\\bdef"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /.[\\b]./.exec("abc\\bdef"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /.[\\b]./.exec("abc\\bdef"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T2.js index 6744cd77a46d..693278004b61 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T2.js @@ -13,26 +13,30 @@ var __expected = ["c\b\b\bd"]; __expected.index = 2; __expected.input = "abc\b\b\bdef"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /c[\\b]{3}d/.exec("abc\\b\\b\\bdef"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /c[\\b]{3}d/.exec("abc\\b\\b\\bdef"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /c[\\b]{3}d/.exec("abc\\b\\b\\bdef"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /c[\\b]{3}d/.exec("abc\\b\\b\\bdef"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T3.js index 1363670c1d25..10dbcc25bd04 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T3.js @@ -13,26 +13,30 @@ var __expected = ["abc"]; __expected.index = 0; __expected.input = "abc\bdef"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^\\[\\b\\]]+/.exec("abc\\bdef"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^\\[\\b\\]]+/.exec("abc\\bdef"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^\\[\\b\\]]+/.exec("abc\\bdef"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^\\[\\b\\]]+/.exec("abc\\bdef"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T4.js index 478762b4d2e7..b158386550cc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.13_A3_T4.js @@ -13,26 +13,30 @@ var __expected = ["abcdef"]; __expected.index = 0; __expected.input = "abcdef"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^\\[\\b\\]]+/.exec("abcdef"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^\\[\\b\\]]+/.exec("abcdef"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^\\[\\b\\]]+/.exec("abcdef"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^\\[\\b\\]]+/.exec("abcdef"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T1.js index d73347838866..cdcf0e9f42e2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T1.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-ac-e]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-ac-e]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-ac-e]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T10.js index b9dabf00c8d7..ceedfbbad1db 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T10.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\10b-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\10b-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\10b-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T11.js index 2a7f64a97416..a936f005ea4d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T11.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\bd-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\bd-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\bd-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T12.js index c3c8d7b180dc..0adc1f2575c8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T12.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\Bd-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\Bd-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\Bd-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T13.js index e4ebd9317019..f159e9cbb4b8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T13.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\td-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\td-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\td-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T14.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T14.js index 1c997fb29a22..8a10b5695444 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T14.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\nd-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\nd-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\nd-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T15.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T15.js index d1f08eec3578..801266013dfd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T15.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\vd-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\vd-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\vd-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T16.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T16.js index fde16d023936..79d78cbb724c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T16.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T16.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\fd-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\fd-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\fd-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T17.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T17.js index 089eb1ff8228..76bea152fb52 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T17.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T17.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\rd-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\rd-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\rd-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T18.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T18.js index 7107052ee7bf..71d67c145515 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T18.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T18.js @@ -16,13 +16,16 @@ description: > throwing the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\c0001d-G]/.exec("1") throw SyntaxError. Actual: ' + (new RegExp("[\\c0001d-G]").exec("1"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\c0001d-G]/.exec("1") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T19.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T19.js index 7127de955af3..dde7055f7025 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T19.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T19.js @@ -16,13 +16,16 @@ description: > throwing the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\x0061d-G]/.exec("1") throw SyntaxError. Actual: ' + (new RegExp("[\\x0061d-G]").exec("1"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\x0061d-G]/.exec("1") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T2.js index a44269b0ad2d..9237c603d75a 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T2.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[a-dc-b]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[a-dc-b]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[a-dc-b]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T20.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T20.js index 23685a45ac1c..f5e5ef365850 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T20.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T20.js @@ -16,13 +16,16 @@ description: > throwing the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\u0061d-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\u0061d-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\u0061d-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T21.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T21.js index 0661def33cd0..8e1e6f505e6c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T21.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T21.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\ad-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\ad-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\ad-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T22.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T22.js index db6ecf812431..83386db9aabc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T22.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T22.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[c-eb-a]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[c-eb-a]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[c-eb-a]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T23.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T23.js index f29346ed5b32..25940b01bb05 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T23.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T23.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-G\\d]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-G\\d]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-G\\d]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T24.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T24.js index 8cf4bfe8144f..705b88d66b31 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T24.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T24.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-G\\D]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-G\\D]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-G\\D]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T25.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T25.js index 67c44c6d49c2..89adf8be03c2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T25.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T25.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-G\\s]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-G\\s]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-G\\s]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T26.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T26.js index e94fd04f9de5..a7c25bf6864d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T26.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T26.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-G\\S]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-G\\S]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-G\\S]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T27.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T27.js index bc3cbafc0b10..5c4186280a9c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T27.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T27.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-G\\w]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-G\\w]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-G\\w]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T28.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T28.js index 1da63d357afa..07ae0e85f9f1 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T28.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T28.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-G\\W]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-G\\W]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-G\\W]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T29.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T29.js index b00d6a732e54..0d14d5df0227 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T29.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T29.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-G\\0]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-G\\0]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-G\\0]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T3.js index 446a518fab0a..8c3d9e8b6666 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T3.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\db-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\db-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\db-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T30.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T30.js index 66b1b28b9182..32219f1133a5 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T30.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T30.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[b-G\\10]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[b-G\\10]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[b-G\\10]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T31.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T31.js index 0ef5287cf5eb..a7280a204c34 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T31.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T31.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\b]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\b]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\b]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T32.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T32.js index 1e842d0d2a77..47805bf1b34e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T32.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T32.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\B]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\B]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\B]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T33.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T33.js index e0ffb4b86eb8..d2c55d0a7906 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T33.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T33.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\t]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\t]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\t]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T34.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T34.js index 9261e7c68e09..51d8cb00d0f9 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T34.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T34.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\n]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\n]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\n]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T35.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T35.js index a0f711b37508..f89adc57b008 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T35.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T35.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\v]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\v]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\v]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T36.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T36.js index 70ada582067a..8234169341dd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T36.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T36.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\f]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\f]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\f]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T37.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T37.js index 54423536c9fd..84660c66333e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T37.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T37.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\r]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\r]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\r]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T38.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T38.js index 0cc2719aa61f..9bc2fd2c0ebf 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T38.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T38.js @@ -16,13 +16,16 @@ description: > throwing the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\c0001]/.exec("1") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\c0001]").exec("1"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\c0001]/.exec("1") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T39.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T39.js index 003b8020c73f..7e9776e80f9e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T39.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T39.js @@ -16,13 +16,16 @@ description: > throwing the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\x0061]/.exec("1") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\x0061]").exec("1"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\x0061]/.exec("1") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T4.js index d095011f2f0b..3d2f9c794012 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T4.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\Db-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\Db-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\Db-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T40.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T40.js index 16fcb79469e6..484e4f7a3e36 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T40.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T40.js @@ -16,13 +16,16 @@ description: > throwing the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\u0061]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\u0061]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\u0061]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T41.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T41.js index 5479ba24528b..b7602ed2d5fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T41.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T41.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[d-G\\a]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[d-G\\a]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[d-G\\a]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T5.js index 19d4fb08c84d..784c14f8e8b5 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T5.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\sb-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\sb-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\sb-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T6.js index 69b845fde74e..4e8925c196be 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T6.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\Sb-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\Sb-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\Sb-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T7.js index 12c3baf2c169..1a54c701d6ec 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T7.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\wb-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\wb-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\wb-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T8.js index 1405376d0e57..e11bce529c71 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T8.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\Wb-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\Wb-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\Wb-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T9.js index f7f5ea889d48..cc05a2123dfe 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.15_A1_T9.js @@ -16,13 +16,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[\\0b-G]/.exec("a") throw SyntaxError. Actual: ' + (new RegExp("[\\0b-G]").exec("a"))); } catch (e) { - if((e instanceof SyntaxError) !== true){ - throw new Test262Error('#1.2: /[\\0b-G]/.exec("a") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T1.js index baf13355b2d6..b1a3d5728bec 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T1.js @@ -16,26 +16,30 @@ var __expected = ["a"]; __expected.index = 0; __expected.input = "abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a|ab/.exec("abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a|ab/.exec("abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a|ab/.exec("abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a|ab/.exec("abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T10.js index 7080222f0c26..eedbe81f06fa 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T10.js @@ -16,26 +16,30 @@ var __expected = ["eF"]; __expected.index = 3; __expected.input = "AEKeFCDab"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(?:ab|cd)+|ef/i.exec("AEKeFCDab"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(?:ab|cd)+|ef/i.exec("AEKeFCDab"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(?:ab|cd)+|ef/i.exec("AEKeFCDab"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(?:ab|cd)+|ef/i.exec("AEKeFCDab"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T11.js index a98a0f04b8f7..67cce12424fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T11.js @@ -16,26 +16,30 @@ var __expected = ["11111"]; __expected.index = 0; __expected.input = "1111111111111111"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /11111|111/.exec("1111111111111111"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /11111|111/.exec("1111111111111111"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /11111|111/.exec("1111111111111111"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /11111|111/.exec("1111111111111111"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T12.js index f251884454c0..54834ab06f56 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T12.js @@ -16,26 +16,30 @@ var __expected = ["abc"]; __expected.index = 0; __expected.input = "abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /xyz|.../.exec("abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /xyz|.../.exec("abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /xyz|.../.exec("abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /xyz|.../.exec("abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T13.js index 48b4f6bddbe3..525d5ac02813 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T13.js @@ -16,26 +16,30 @@ var __expected = ["abc","a"]; __expected.index = 0; __expected.input = "abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(.)..|abc/.exec("abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(.)..|abc/.exec("abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(.)..|abc/.exec("abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(.)..|abc/.exec("abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T14.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T14.js index 763f66aa27ba..a758b725ab79 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T14.js @@ -16,26 +16,30 @@ var __expected = ["color: grey","e"]; __expected.index = 0; __expected.input = "color: grey"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /.+: gr(a|e)y/.exec("color: grey"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /.+: gr(a|e)y/.exec("color: grey"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /.+: gr(a|e)y/.exec("color: grey"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /.+: gr(a|e)y/.exec("color: grey"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T15.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T15.js index 307b271001eb..88f68b83e78e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T15.js @@ -18,26 +18,30 @@ var __expected = ["Bob",undefined,"Bob", undefined, undefined]; __expected.index = 3; __expected.input = "Hi Bob"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(Rob)|(Bob)|(Robert)|(Bobby)/.exec("Hi Bob"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(Rob)|(Bob)|(Robert)|(Bobby)/.exec("Hi Bob"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(Rob)|(Bob)|(Robert)|(Bobby)/.exec("Hi Bob"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(Rob)|(Bob)|(Robert)|(Bobby)/.exec("Hi Bob"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T16.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T16.js index 887469647f21..500d24ed4538 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T16.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T16.js @@ -16,26 +16,30 @@ var __expected = ["",""]; __expected.index = 0; __expected.input = ""; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /()|/.exec(""); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /()|/.exec(""); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /()|/.exec(""); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /()|/.exec(""); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T17.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T17.js index 6ac7e2b94dff..4780213347d9 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T17.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T17.js @@ -16,26 +16,30 @@ var __expected = ["",undefined]; __expected.index = 0; __expected.input = ""; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /|()/.exec(""); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /|()/.exec(""); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /|()/.exec(""); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /|()/.exec(""); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T2.js index a30323b5e5d5..e48da33a03dc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T2.js @@ -16,26 +16,30 @@ var __expected = ["abc", "a", "a", undefined, "bc", undefined, "bc"]; __expected.index = 0; __expected.input = "abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /((a)|(ab))((c)|(bc))/.exec("abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /((a)|(ab))((c)|(bc))/.exec("abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /((a)|(ab))((c)|(bc))/.exec("abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /((a)|(ab))((c)|(bc))/.exec("abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T3.js index 48b2e9b54e7d..cc627d8c60f0 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T3.js @@ -18,26 +18,30 @@ var __expected = ["cour"]; __expected.index = 13; __expected.input = "2, 12 and of course repeat 12"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{3}|[a-z]{4}/.exec("2, 12 and of course repeat 12"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{3}|[a-z]{4}/.exec("2, 12 and of course repeat 12"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{3}|[a-z]{4}/.exec("2, 12 and of course repeat 12"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{3}|[a-z]{4}/.exec("2, 12 and of course repeat 12"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T4.js index 21d099597638..47827a040959 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T4.js @@ -18,26 +18,30 @@ var __expected = ["234"]; __expected.index = 10; __expected.input = "2, 12 and 234 AND of course repeat 12"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{3}|[a-z]{4}/.exec("2, 12 and 234 AND of course repeat 12"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{3}|[a-z]{4}/.exec("2, 12 and 234 AND of course repeat 12"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{3}|[a-z]{4}/.exec("2, 12 and 234 AND of course repeat 12"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{3}|[a-z]{4}/.exec("2, 12 and 234 AND of course repeat 12"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T5.js index cdf8b72a8e64..db7b6bc3f411 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T5.js @@ -14,9 +14,6 @@ description: > var __executed = /\d{3}|[a-z]{4}/.test("2, 12 and 23 AND 0.00.1"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /\\d{3}|[a-z]{4}/.test("2, 12 and 23 AND 0.00.1") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T6.js index b58343630ae7..dbc9adec6859 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T6.js @@ -16,26 +16,30 @@ var __expected = ["CD"]; __expected.index = 4; __expected.input = "AEKFCD"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /ab|cd|ef/i.exec("AEKFCD"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /ab|cd|ef/i.exec("AEKFCD"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /ab|cd|ef/i.exec("AEKFCD"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /ab|cd|ef/i.exec("AEKFCD"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T7.js index efb202e36264..4c239a847eac 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T7.js @@ -12,9 +12,6 @@ description: Execute /ab|cd|ef/.test("AEKFCD") and check results var __executed = /ab|cd|ef/.test("AEKFCD"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /ab|cd|ef/.test("AEKFCD") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T8.js index 1a3b54ed09cb..d8657663ea4c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T8.js @@ -16,26 +16,30 @@ var __expected = ["CD"]; __expected.index = 4; __expected.input = "AEKFCD"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(?:ab|cd)+|ef/i.exec("AEKFCD"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(?:ab|cd)+|ef/i.exec("AEKFCD"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(?:ab|cd)+|ef/i.exec("AEKFCD"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(?:ab|cd)+|ef/i.exec("AEKFCD"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T9.js index 9a6b180fe782..58ff15a8c33d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.3_A1_T9.js @@ -16,26 +16,30 @@ var __expected = ["CDab"]; __expected.index = 4; __expected.input = "AEKFCDab"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(?:ab|cd)+|ef/i.exec("AEKFCDab"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(?:ab|cd)+|ef/i.exec("AEKFCDab"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(?:ab|cd)+|ef/i.exec("AEKFCDab"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(?:ab|cd)+|ef/i.exec("AEKFCDab"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T1.js index 817f881ec413..dcb7f09d4365 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T1.js @@ -15,26 +15,30 @@ var __expected = ["abcde"]; __expected.index = 0; __expected.input = "abcdefghi"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a[a-z]{2,4}/.exec("abcdefghi"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a[a-z]{2,4}/.exec("abcdefghi"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a[a-z]{2,4}/.exec("abcdefghi"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a[a-z]{2,4}/.exec("abcdefghi"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T2.js index 0f91a8944642..3e881512284f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T2.js @@ -15,26 +15,30 @@ var __expected = ["abc"]; __expected.index = 0; __expected.input = "abcdefghi"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a[a-z]{2,4}?/.exec("abcdefghi"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a[a-z]{2,4}?/.exec("abcdefghi"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a[a-z]{2,4}?/.exec("abcdefghi"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a[a-z]{2,4}?/.exec("abcdefghi"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T3.js index 8119e8849fa8..f395719dfc94 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T3.js @@ -15,26 +15,30 @@ var __expected = ["aaba", "ba"]; __expected.index = 0; __expected.input = "aabaac"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(aa|aabaac|ba|b|c)*/.exec("aabaac"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(aa|aabaac|ba|b|c)*/.exec("aabaac"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(aa|aabaac|ba|b|c)*/.exec("aabaac"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(aa|aabaac|ba|b|c)*/.exec("aabaac"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T4.js index f66300c8bbbc..e3ef4d864036 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T4.js @@ -15,26 +15,30 @@ var __expected = ["zaacbbbcac", "z", "ac", "a", undefined, "c"]; __expected.index = 0; __expected.input = "zaacbbbcac"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T5.js index 3520e1f5bb59..2ffe40efd299 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.5_A1_T5.js @@ -15,26 +15,30 @@ var __expected = ["b", ""]; __expected.index = 0; __expected.input = "baaaac"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(a*)b\\1+/.exec("baaaac"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(a*)b\\1+/.exec("baaaac"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(a*)b\\1+/.exec("baaaac"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(a*)b\\1+/.exec("baaaac"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T1.js index be8d2d944bd8..3ba6f1a88088 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T1.js @@ -11,9 +11,6 @@ description: Execute /s$/.test("pairs\nmakes\tdouble") and check results var __executed = /s$/.test("pairs\nmakes\tdouble"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /s$/.test("pairs\\nmakes\\tdouble") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T2.js index c8852626058b..d314d096bb9c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T2.js @@ -15,26 +15,30 @@ var __expected = ["e"]; __expected.index = 17; __expected.input = "pairs\nmakes\tdouble"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /e$/.exec("pairs\\nmakes\\tdouble"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /e$/.exec("pairs\\nmakes\\tdouble"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /e$/.exec("pairs\\nmakes\\tdouble"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /e$/.exec("pairs\\nmakes\\tdouble"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T3.js index ff290c3eb52a..16dee376404a 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T3.js @@ -15,26 +15,30 @@ var __expected = ["s"]; __expected.index = 4; __expected.input = "pairs\nmakes\tdouble"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /s$/m.exec("pairs\\nmakes\\tdouble"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /s$/m.exec("pairs\\nmakes\\tdouble"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /s$/m.exec("pairs\\nmakes\\tdouble"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /s$/m.exec("pairs\\nmakes\\tdouble"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T4.js index 2d49953e141d..34109058e1dd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T4.js @@ -15,26 +15,30 @@ var __expected = ["s"]; __expected.index = 4; __expected.input = "pairs\nmakes\tdouble"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^e]$/mg.exec("pairs\\nmakes\\tdouble"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^e]$/mg.exec("pairs\\nmakes\\tdouble"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^e]$/mg.exec("pairs\\nmakes\\tdouble"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^e]$/mg.exec("pairs\\nmakes\\tdouble"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T5.js index b4588b4bffa0..da6610d97aee 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A1_T5.js @@ -17,26 +17,30 @@ var __expected = ["es"]; __expected.index = 17; __expected.input = "pairs\nmakes\tdoubles"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /es$/mg.exec("pairs\\nmakes\\tdoubl\\u0065s"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /es$/mg.exec("pairs\\nmakes\\tdoubl\\u0065s"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /es$/mg.exec("pairs\\nmakes\\tdoubl\\u0065s"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /es$/mg.exec("pairs\\nmakes\\tdoubl\\u0065s"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T1.js index 0c94b920e312..8af0b6fe9abe 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T1.js @@ -11,9 +11,6 @@ description: Execute /^m/.test("pairs\nmakes\tdouble") and check results var __executed = /^m/.test("pairs\nmakes\tdouble"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /^m/.test("pairs\\nmakes\\tdouble") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T10.js index 6a6cdd34574c..b8d18b59c1b4 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T10.js @@ -15,26 +15,30 @@ var __expected = ["123"]; __expected.index = 4; __expected.input = "abc\n123xyz"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^\\d+/m.exec("abc\\n123xyz"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^\\d+/m.exec("abc\\n123xyz"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^\\d+/m.exec("abc\\n123xyz"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^\\d+/m.exec("abc\\n123xyz"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T2.js index d435b125bfd2..a9884c5c508c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T2.js @@ -15,26 +15,30 @@ var __expected = ["m"]; __expected.index = 6; __expected.input = "pairs\nmakes\tdouble"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^m/m.exec("pairs\\nmakes\\tdouble"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^m/m.exec("pairs\\nmakes\\tdouble"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^m/m.exec("pairs\\nmakes\\tdouble"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^m/m.exec("pairs\\nmakes\\tdouble"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T3.js index a059d9255414..aeb06cccdb9b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T3.js @@ -17,26 +17,30 @@ var __expected = ["pa"]; __expected.index = 0; __expected.input = "pairs\nmakes\tdouble\npesos"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^p[a-z]/.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^p[a-z]/.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^p[a-z]/.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^p[a-z]/.exec("pairs\\nmakes\\tdouble\\npesos"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T4.js index 7a9756d9b180..df304897e4c1 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T4.js @@ -17,26 +17,30 @@ var __expected = ["pe"]; __expected.index = 19; __expected.input = "pairs\nmakes\tdouble\npesos"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^p[b-z]/m.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^p[b-z]/m.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^p[b-z]/m.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^p[b-z]/m.exec("pairs\\nmakes\\tdouble\\npesos"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T5.js index bf912f521b25..546bf531a330 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T5.js @@ -17,26 +17,30 @@ var __expected = ["m"]; __expected.index = 6; __expected.input = "pairs\nmakes\tdouble\npesos"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^[^p]/m.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^[^p]/m.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^[^p]/m.exec("pairs\\nmakes\\tdouble\\npesos"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^[^p]/m.exec("pairs\\nmakes\\tdouble\\npesos"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T6.js index af971ab49968..49e4ba2cc4a7 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T6.js @@ -15,26 +15,30 @@ var __expected = ["ab"]; __expected.index = 0; __expected.input = "abcde"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^ab/.exec("abcde"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^ab/.exec("abcde"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^ab/.exec("abcde"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^ab/.exec("abcde"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T7.js index 6e52c4805314..4d346246bc47 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T7.js @@ -11,9 +11,6 @@ description: Execute /^..^e/.test("ab\ncde") and check results var __executed = /^..^e/.test("ab\ncde"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /^..^e/.test("ab\\ncde") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T8.js index dae132c1b4b4..e56cf8b95776 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T8.js @@ -11,9 +11,6 @@ description: Execute /^xxx/.test("yyyyy") and check results var __executed = /^xxx/.test("yyyyy"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /^xxx/.test("yyyyy") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T9.js index b8c89d6a47ee..6587eb1bbcb3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A2_T9.js @@ -15,26 +15,30 @@ var __expected = ["^^^"]; __expected.index = 0; __expected.input = "^^^x"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^\\^+/.exec("^^^x"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^\\^+/.exec("^^^x"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^\\^+/.exec("^^^x"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^\\^+/.exec("^^^x"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T1.js index 08d7547d557f..9b50a149cfa7 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T1.js @@ -17,26 +17,30 @@ var __expected = ["p"]; __expected.index = 0; __expected.input = "pilot\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\bp/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\bp/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\bp/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\bp/.exec("pilot\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T10.js index deb21ca73b52..873b729522b9 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T10.js @@ -17,26 +17,30 @@ var __expected = ["robot"]; __expected.index = 13; __expected.input = "pilot\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\brobot\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\brobot\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\brobot\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\brobot\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T11.js index 071d0cacf072..17e48b1d853b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T11.js @@ -17,26 +17,30 @@ var __expected = ["pilot"]; __expected.index = 0; __expected.input = "pilot\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\b\\w{5}\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\b\\w{5}\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\b\\w{5}\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\b\\w{5}\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T12.js index b4ab14df9dc2..cfcde0a25735 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T12.js @@ -17,26 +17,30 @@ var __expected = ["op"]; __expected.index = 19; __expected.input = "pilot\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\bop/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\bop/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\bop/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\bop/.exec("pilot\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T13.js index e90cbbca11b4..ec17f59bc469 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T13.js @@ -13,9 +13,6 @@ description: > var __executed = /op\b/.test("pilot\nsoviet robot\topenoffice"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /op\\b/.test("pilot\\nsoviet robot\\topenoffice") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T14.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T14.js index d0f7d40b41fa..e899c72c1b47 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T14.js @@ -17,26 +17,30 @@ var __expected = ["e"]; __expected.index = 28; __expected.input = "pilot\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /e\\b/.exec("pilot\\nsoviet robot\\topenoffic\\u0065"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /e\\b/.exec("pilot\\nsoviet robot\\topenoffic\\u0065"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /e\\b/.exec("pilot\\nsoviet robot\\topenoffic\\u0065"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /e\\b/.exec("pilot\\nsoviet robot\\topenoffic\\u0065"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T15.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T15.js index 57503371c77f..9b450811e8ba 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T15.js @@ -13,9 +13,6 @@ description: > var __executed = /\be/.test("pilot\nsoviet robot\topenoffic\u0065"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /\\be/.test("pilot\\nsoviet robot\\topenoffic\\u0065") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T2.js index 077c4039730c..2c4bedaa6835 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T2.js @@ -17,26 +17,30 @@ var __expected = ["ot"]; __expected.index = 3; __expected.input = "pilot\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /ot\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /ot\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /ot\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /ot\\b/.exec("pilot\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T3.js index 79a2db1f39c1..edb7b1a9f69d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T3.js @@ -13,9 +13,6 @@ description: > var __executed = /\bot/.test("pilot\nsoviet robot\topenoffice"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /\\bot/.test("pilot\\nsoviet robot\\topenoffice") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T4.js index be3d0924f710..02cbed9dd02b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T4.js @@ -17,26 +17,30 @@ var __expected = ["so"]; __expected.index = 6; __expected.input = "pilot\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\bso/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\bso/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\bso/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\bso/.exec("pilot\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T5.js index d9615852832d..de857fe73a20 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T5.js @@ -13,9 +13,6 @@ description: > var __executed = /so\b/.test("pilot\nsoviet robot\topenoffice"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /so\\b/.test("pilot\\nsoviet robot\\topenoffice") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T6.js index 18fe91ebb590..36c5708757e1 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T6.js @@ -17,26 +17,30 @@ var __expected = ["Ot"]; __expected.index = 3; __expected.input = "pilOt\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^o]t\\b/.exec("pilOt\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^o]t\\b/.exec("pilOt\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^o]t\\b/.exec("pilOt\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^o]t\\b/.exec("pilOt\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T7.js index 67890d4aeabc..ff918dfa2e75 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T7.js @@ -17,26 +17,30 @@ var __expected = ["et"]; __expected.index = 10; __expected.input = "pilOt\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^o]t\\b/i.exec("pilOt\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^o]t\\b/i.exec("pilOt\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^o]t\\b/i.exec("pilOt\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^o]t\\b/i.exec("pilOt\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T8.js index d9888a0af4a0..2a1cdb82cbf6 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T8.js @@ -17,26 +17,30 @@ var __expected = ["ro"]; __expected.index = 13; __expected.input = "pilot\nsoviet robot\topenoffice"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\bro/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\bro/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\bro/.exec("pilot\\nsoviet robot\\topenoffice"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\bro/.exec("pilot\\nsoviet robot\\topenoffice"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T9.js index cfe38bc71c76..98da926ed4d4 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A3_T9.js @@ -13,9 +13,6 @@ description: > var __executed = /r\b/.test("pilot\nsoviet robot\topenoffice"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /r\\b/.test("pilot\\nsoviet robot\\topenoffice") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T1.js index 541536b82eb6..671488030654 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T1.js @@ -17,26 +17,30 @@ var __expected = ["evil"]; __expected.index = 1; __expected.input = "devils arise\tfor\nevil"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\Bevil\\B/.exec("devils arise\\tfor\\nevil"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\Bevil\\B/.exec("devils arise\\tfor\\nevil"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\Bevil\\B/.exec("devils arise\\tfor\\nevil"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\Bevil\\B/.exec("devils arise\\tfor\\nevil"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T2.js index 0e59ca34246e..19f5f976f479 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T2.js @@ -17,26 +17,30 @@ var __expected = ["re"]; __expected.index = 17; __expected.input = "devils arise\tfor\nrevil"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[f-z]e\\B/.exec("devils arise\\tfor\\nrevil"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[f-z]e\\B/.exec("devils arise\\tfor\\nrevil"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[f-z]e\\B/.exec("devils arise\\tfor\\nrevil"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[f-z]e\\B/.exec("devils arise\\tfor\\nrevil"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T3.js index d85f1e23fb6e..cb9b12e48410 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T3.js @@ -15,26 +15,30 @@ var __expected = ["O"]; __expected.index = 14; __expected.input = "devils arise\tfOr\nrevil"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\Bo\\B/i.exec("devils arise\\tfOr\\nrevil"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\Bo\\B/i.exec("devils arise\\tfOr\\nrevil"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\Bo\\B/i.exec("devils arise\\tfOr\\nrevil"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\Bo\\B/i.exec("devils arise\\tfOr\\nrevil"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T4.js index cbbf7a46d3b9..696fa8745a13 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T4.js @@ -15,26 +15,30 @@ var __expected = ["e"]; __expected.index = 1; __expected.input = "devils arise\tfor\nrevil"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\B\\w\\B/.exec("devils arise\\tfor\\nrevil"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\B\\w\\B/.exec("devils arise\\tfor\\nrevil"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\B\\w\\B/.exec("devils arise\\tfor\\nrevil"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\B\\w\\B/.exec("devils arise\\tfor\\nrevil"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T5.js index 00eb5b588805..68a46190c75f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T5.js @@ -15,26 +15,30 @@ var __expected = ["d"]; __expected.index = 0; __expected.input = "devils arise\tfor\nrevil"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\w\\B/.exec("devils arise\\tfor\\nrevil"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\w\\B/.exec("devils arise\\tfor\\nrevil"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\w\\B/.exec("devils arise\\tfor\\nrevil"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\w\\B/.exec("devils arise\\tfor\\nrevil"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T6.js index dbe57cf83ee2..fef789b36705 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T6.js @@ -15,26 +15,30 @@ var __expected = ["e"]; __expected.index = 1; __expected.input = "devils arise\tfor\nrevil"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\B\\w/.exec("devils arise\\tfor\\nrevil"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\B\\w/.exec("devils arise\\tfor\\nrevil"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\B\\w/.exec("devils arise\\tfor\\nrevil"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\B\\w/.exec("devils arise\\tfor\\nrevil"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T7.js index 85366482d620..1da61dbe0689 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T7.js @@ -17,26 +17,30 @@ var __expected = ["il a"]; __expected.index = 3; __expected.input = "devil arise\tforzzx\nevils"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\B[^z]{4}\B/.exec("devil arise\\tforzzx\\nevils"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\B[^z]{4}\B/.exec("devil arise\\tforzzx\\nevils"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\B[^z]{4}\B/.exec("devil arise\\tforzzx\\nevils"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\B[^z]{4}\B/.exec("devil arise\\tforzzx\\nevils"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T8.js index 4a9ead8a486c..486eeac080cd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A4_T8.js @@ -17,26 +17,30 @@ var __expected = ["orzz"]; __expected.index = 13; __expected.input = "devil arise\tforzzx\nevils"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\B\\w{4}\\B/.exec("devil arise\\tforzzx\\nevils"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\B\\w{4}\\B/.exec("devil arise\\tforzzx\\nevils"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\B\\w{4}\\B/.exec("devil arise\\tforzzx\\nevils"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\B\\w{4}\\B/.exec("devil arise\\tforzzx\\nevils"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A5_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A5_T1.js index 2845fcd1ab65..23b889928532 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A5_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A5_T1.js @@ -15,26 +15,30 @@ var __expected = ["robot"]; __expected.index = 0; __expected.input = "robot"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^^^^^^^robot$$$$/.exec("robot"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^^^^^^^robot$$$$/.exec("robot"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^^^^^^^robot$$$$/.exec("robot"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^^^^^^^robot$$$$/.exec("robot"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A5_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A5_T2.js index a02889e77fb7..75b64eb6c4f1 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A5_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A5_T2.js @@ -17,26 +17,30 @@ var __expected = ["bot"]; __expected.index = 2; __expected.input = "robot wall-e"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\B\\B\\B\\B\\B\\Bbot\\b\\b\\b\\b\\b\\b\\b/.exec("robot wall-e"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\B\\B\\B\\B\\B\\Bbot\\b\\b\\b\\b\\b\\b\\b/.exec("robot wall-e"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\B\\B\\B\\B\\B\\Bbot\\b\\b\\b\\b\\b\\b\\b/.exec("robot wall-e"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\B\\B\\B\\B\\B\\Bbot\\b\\b\\b\\b\\b\\b\\b/.exec("robot wall-e"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T1.js index 58e119350ba5..0a20bbd8deda 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T1.js @@ -15,26 +15,30 @@ var __expected = ["Hello World"]; __expected.index = 0; __expected.input = "Hello World"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^.*?$/.exec("Hello World"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^.*?$/.exec("Hello World"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^.*?$/.exec("Hello World"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^.*?$/.exec("Hello World"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T2.js index 4d9a24053f67..0bbaf8cb71e6 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T2.js @@ -13,26 +13,30 @@ var __expected = [""]; __expected.index = 0; __expected.input = "Hello World"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^.*?/.exec("Hello World"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^.*?/.exec("Hello World"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^.*?/.exec("Hello World"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^.*?/.exec("Hello World"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T3.js index d7c5e72c7a3f..c7c25431ce38 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T3.js @@ -13,26 +13,30 @@ var __expected = ["Hello:", ":"]; __expected.index = 0; __expected.input = "Hello: World"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^.*?(:|$)/.exec("Hello: World"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^.*?(:|$)/.exec("Hello: World"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^.*?(:|$)/.exec("Hello: World"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^.*?(:|$)/.exec("Hello: World"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T4.js index 26b0bf3eacbd..8dbaa0ba089c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.6_A6_T4.js @@ -13,26 +13,30 @@ var __expected = ["Hello: World", ""]; __expected.index = 0; __expected.input = "Hello: World"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^.*(:|$)/.exec("Hello: World"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^.*(:|$)/.exec("Hello: World"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^.*(:|$)/.exec("Hello: World"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^.*(:|$)/.exec("Hello: World"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T1.js index 39773d2536bc..e8072e7423fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T1.js @@ -15,26 +15,30 @@ var __expected = ["42"]; __expected.index = 14; __expected.input = "the answer is 42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{2,4}/.exec("the answer is 42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{2,4}/.exec("the answer is 42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{2,4}/.exec("the answer is 42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{2,4}/.exec("the answer is 42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T10.js index 937f7d852770..10983028b7c8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T10.js @@ -15,26 +15,30 @@ var __expected = ["bbbbc"]; __expected.index = 3; __expected.input = "aaabbbbcccddeeeefffff"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /b{0,93}c/.exec("aaabbbbcccddeeeefffff"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /b{0,93}c/.exec("aaabbbbcccddeeeefffff"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /b{0,93}c/.exec("aaabbbbcccddeeeefffff"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /b{0,93}c/.exec("aaabbbbcccddeeeefffff"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T11.js index 2d3fdf6901de..89a51c5b7637 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T11.js @@ -15,26 +15,30 @@ var __expected = ["bc"]; __expected.index = 6; __expected.input = "aaabbbbcccddeeeefffff"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /bx{0,93}c/.exec("aaabbbbcccddeeeefffff"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /bx{0,93}c/.exec("aaabbbbcccddeeeefffff"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /bx{0,93}c/.exec("aaabbbbcccddeeeefffff"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /bx{0,93}c/.exec("aaabbbbcccddeeeefffff"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T12.js index 136bc7e79b12..6f01e3945205 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T12.js @@ -15,26 +15,30 @@ var __expected = ["weirwerdf"]; __expected.index = 0; __expected.input = "weirwerdf"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /.{0,93}/.exec("weirwerdf"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /.{0,93}/.exec("weirwerdf"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /.{0,93}/.exec("weirwerdf"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /.{0,93}/.exec("weirwerdf"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T2.js index 42325346a491..9f57db24d3a7 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T2.js @@ -11,9 +11,6 @@ description: Execute /\d{2,4}/.test("the 7 movie") and check results var __executed = /\d{2,4}/.test("the 7 movie"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /\\d{2,4}/.test("the 7 movie") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T3.js index 2008a6b0e4db..bd101cb36e5e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T3.js @@ -17,26 +17,30 @@ var __expected = ["2000"]; __expected.index = 4; __expected.input = "the 20000 Leagues Under the Sea book"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{2,4}/.exec("the 20000 Leagues Under the Sea book"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{2,4}/.exec("the 20000 Leagues Under the Sea book"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{2,4}/.exec("the 20000 Leagues Under the Sea book"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{2,4}/.exec("the 20000 Leagues Under the Sea book"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T4.js index 843ba6478332..f6fac80150ae 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T4.js @@ -15,26 +15,30 @@ var __expected = ["451"]; __expected.index = 15; __expected.input = "the Fahrenheit 451 book"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{2,4}/.exec("the Fahrenheit 451 book"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{2,4}/.exec("the Fahrenheit 451 book"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{2,4}/.exec("the Fahrenheit 451 book"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{2,4}/.exec("the Fahrenheit 451 book"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T5.js index 5f2969f82ec8..fa380832b645 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T5.js @@ -15,26 +15,30 @@ var __expected = ["1984"]; __expected.index = 4; __expected.input = "the 1984 novel"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{2,4}/.exec("the 1984 novel"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{2,4}/.exec("the 1984 novel"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{2,4}/.exec("the 1984 novel"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{2,4}/.exec("the 1984 novel"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T6.js index a554f862368e..1ea6f51f1100 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T6.js @@ -15,26 +15,30 @@ var __expected = ["011"]; __expected.index = 2; __expected.input = "0a011b"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{2,4}/.exec("0a0\\u0031\\u0031b"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{2,4}/.exec("0a0\\u0031\\u0031b"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{2,4}/.exec("0a0\\u0031\\u0031b"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{2,4}/.exec("0a0\\u0031\\u0031b"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T7.js index 0df33fe22a73..9c99440b792b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T7.js @@ -15,26 +15,30 @@ var __expected = ["0112"]; __expected.index = 2; __expected.input = "0a01122b"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{2,4}/.exec("0a0\\u0031\\u003122b"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{2,4}/.exec("0a0\\u0031\\u003122b"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{2,4}/.exec("0a0\\u0031\\u003122b"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{2,4}/.exec("0a0\\u0031\\u003122b"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T8.js index 885ef19db71a..e0bb7ef12187 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T8.js @@ -15,26 +15,30 @@ var __expected = ["bbbc"]; __expected.index = 4; __expected.input = "aaabbbbcccddeeeefffff"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /b{2,3}c/.exec("aaabbbbcccddeeeefffff"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /b{2,3}c/.exec("aaabbbbcccddeeeefffff"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /b{2,3}c/.exec("aaabbbbcccddeeeefffff"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /b{2,3}c/.exec("aaabbbbcccddeeeefffff"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T9.js index e2f5aecd6106..a6fab5cedb7e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A1_T9.js @@ -11,9 +11,6 @@ description: Execute /b{42,93}c/.exec("aaabbbbcccddeeeefffff") and check results var __executed = /b{42,93}c/.test("aaabbbbcccddeeeefffff"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /b{42,93}c/.test("aaabbbbcccddeeeefffff") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T1.js index 385bcb2348c4..f44569d91be9 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T1.js @@ -15,26 +15,30 @@ var __expected = ["box1"]; __expected.index = 5; __expected.input = "CE\uFFFFL\uFFDDbox127"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\w{3}\\d?/.exec("CE\\uFFFFL\\uFFDDbox127"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\w{3}\\d?/.exec("CE\\uFFFFL\\uFFDDbox127"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\w{3}\\d?/.exec("CE\\uFFFFL\\uFFDDbox127"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\w{3}\\d?/.exec("CE\\uFFFFL\\uFFDDbox127"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T2.js index 5e65c71aeda2..c32caec3cb88 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T2.js @@ -15,26 +15,30 @@ var __expected = ["CEL"]; __expected.index = 0; __expected.input = "CELL\uFFDDbox127"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\w{3}\\d?/.exec("CELL\\uFFDDbox127"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\w{3}\\d?/.exec("CELL\\uFFDDbox127"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\w{3}\\d?/.exec("CELL\\uFFDDbox127"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\w{3}\\d?/.exec("CELL\\uFFDDbox127"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T3.js index dd05806fbb37..e54ef037854d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T3.js @@ -15,26 +15,30 @@ var __expected = ["bbc"]; __expected.index = 5; __expected.input = "aaabbbbcccddeeeefffff"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /b{2}c/.exec("aaabbbbcccddeeeefffff"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /b{2}c/.exec("aaabbbbcccddeeeefffff"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /b{2}c/.exec("aaabbbbcccddeeeefffff"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /b{2}c/.exec("aaabbbbcccddeeeefffff"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T4.js index 2cc8b2ef1f57..e11162cc6ce4 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A2_T4.js @@ -11,9 +11,6 @@ description: Execute /b{8}c/.test("aaabbbbcccddeeeefffff") and check results var __executed = /b{8}/.test("aaabbbbcccddeeeefffff"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /b{8}/.test("aaabbbbcccddeeeefffff") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T1.js index bb1ee3ae2fab..072d08131820 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T1.js @@ -15,26 +15,30 @@ var __expected = [" java\n"]; __expected.index = 8; __expected.input = "language java\n"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\s+java\\s+/.exec("language java\\n"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\s+java\\s+/.exec("language java\\n"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\s+java\\s+/.exec("language java\\n"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\s+java\\s+/.exec("language java\\n"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T10.js index b0996c6d6a0d..4315cc7f54e2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T10.js @@ -11,9 +11,6 @@ description: Execute /o+/.test("abcdefg") and check results var __executed = /o+/.test("abcdefg"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /o+/.test("abcdefg") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T11.js index e36fa81c9942..c0f1d1ce9c27 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T11.js @@ -15,26 +15,30 @@ var __expected = ["d"]; __expected.index = 3; __expected.input = "abcdefg"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /d+/.exec("abcdefg"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /d+/.exec("abcdefg"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /d+/.exec("abcdefg"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /d+/.exec("abcdefg"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T12.js index d9aa1dae17e9..2e135ae15230 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T12.js @@ -15,26 +15,30 @@ var __expected = ["bbbbbbb","bbbbb","b","b"]; __expected.index = 1; __expected.input = "abbbbbbbc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(b+)(b+)(b+)/.exec("abbbbbbbc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(b+)(b+)(b+)/.exec("abbbbbbbc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(b+)(b+)(b+)/.exec("abbbbbbbc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(b+)(b+)(b+)/.exec("abbbbbbbc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T13.js index 8cc580697801..551536266769 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T13.js @@ -15,26 +15,30 @@ var __expected = ["bbbbbbb","bbbbbbb",""]; __expected.index = 1; __expected.input = "abbbbbbbc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(b+)(b*)/.exec("abbbbbbbc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(b+)(b*)/.exec("abbbbbbbc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(b+)(b*)/.exec("abbbbbbbc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(b+)(b*)/.exec("abbbbbbbc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T14.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T14.js index 4e85524e69dc..0b5fba3cc01e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T14.js @@ -15,26 +15,30 @@ var __expected = ["bbbbbbb"]; __expected.index = 1; __expected.input = "abbbbbbbc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /b*b+/.exec("abbbbbbbc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /b*b+/.exec("abbbbbbbc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /b*b+/.exec("abbbbbbbc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /b*b+/.exec("abbbbbbbc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T2.js index 6ca0fdbfb555..a39ca721cc68 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T2.js @@ -15,26 +15,30 @@ var __expected = ["\t java "]; __expected.index = 0; __expected.input = "\t java object"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\s+java\\s+/.exec("\\t java object"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\s+java\\s+/.exec("\\t java object"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\s+java\\s+/.exec("\\t java object"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\s+java\\s+/.exec("\\t java object"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T3.js index 5aca296d493d..1aeef1d1e57f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T3.js @@ -11,9 +11,6 @@ description: Execute /\s+java\s+/.test("\t javax package") and check results var __executed = /\s+java\s+/.test("\t javax package"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /\\s+java\\s+/.test("\\t javax package") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T4.js index 4f84ce994eca..31a6563c491f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T4.js @@ -11,9 +11,6 @@ description: Execute /\s+java\s+/.test("java\n\nobject") and check results var __executed = /\s+java\s+/.test("java\n\nobject"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /\\s+java\\s+/.test("java\\n\\nobject") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T5.js index 15551302374c..5470c8405626 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T5.js @@ -17,26 +17,30 @@ var __expected = ["x2"]; __expected.index = 10; __expected.input = "x 2 ff 55 x2 as1 z12 abc12.0"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[a-z]+\\d+/.exec("x 2 ff 55 x2 as1 z12 abc12.0"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[a-z]+\\d+/.exec("x 2 ff 55 x2 as1 z12 abc12.0"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[a-z]+\\d+/.exec("x 2 ff 55 x2 as1 z12 abc12.0"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[a-z]+\\d+/.exec("x 2 ff 55 x2 as1 z12 abc12.0"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T6.js index 9f8ff9820f2f..82fdad1ebb60 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T6.js @@ -15,26 +15,30 @@ var __expected = ["abc123"]; __expected.index = 2; __expected.input = "__abc123.0"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[a-z]+\\d+/.exec("__abc123.0"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[a-z]+\\d+/.exec("__abc123.0"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[a-z]+\\d+/.exec("__abc123.0"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[a-z]+\\d+/.exec("__abc123.0"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T7.js index 3e55d0ffd34c..5b40564801d1 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T7.js @@ -17,26 +17,30 @@ var __expected = ["x2","2"]; __expected.index = 10; __expected.input = "x 2 ff 55 x2 as1 z12 abc12.0"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[a-z]+(\\d+)/.exec("x 2 ff 55 x2 as1 z12 abc12.0"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[a-z]+(\\d+)/.exec("x 2 ff 55 x2 as1 z12 abc12.0"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[a-z]+(\\d+)/.exec("x 2 ff 55 x2 as1 z12 abc12.0"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[a-z]+(\\d+)/.exec("x 2 ff 55 x2 as1 z12 abc12.0"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T8.js index b4ab4e6bbf06..bac3261480d1 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T8.js @@ -15,26 +15,30 @@ var __expected = ["abc123","123"]; __expected.index = 2; __expected.input = "__abc123.0"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[a-z]+(\\d+)/.exec("__abc123.0"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[a-z]+(\\d+)/.exec("__abc123.0"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[a-z]+(\\d+)/.exec("__abc123.0"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[a-z]+(\\d+)/.exec("__abc123.0"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T9.js index f347ee11b65e..3b1079232385 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A3_T9.js @@ -15,26 +15,30 @@ var __expected = ["ddddd"]; __expected.index = 3; __expected.input = "abcdddddefg"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /d+/.exec("abcdddddefg"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /d+/.exec("abcdddddefg"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /d+/.exec("abcdddddefg"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /d+/.exec("abcdddddefg"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T1.js index 2d451a8cf10a..f0cd20dee5e6 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T1.js @@ -15,26 +15,30 @@ var __expected = [""]; __expected.index = 0; __expected.input = '"beast"-nickname'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^"]*/.exec(\'"beast"-nickname\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^"]*/.exec(\'"beast"-nickname\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^"]*/.exec(\'"beast"-nickname\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^"]*/.exec(\'"beast"-nickname\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T10.js index 1588cd414c24..948d57a34844 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T10.js @@ -15,26 +15,30 @@ var __expected = [""]; __expected.index = 0; __expected.input = 'abcddddefg'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /d*/.exec(\'abcddddefg\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /d*/.exec(\'abcddddefg\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /d*/.exec(\'abcddddefg\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /d*/.exec(\'abcddddefg\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T11.js index 97e1692c8d36..b681718210a6 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T11.js @@ -15,26 +15,30 @@ var __expected = ["cdddd"]; __expected.index = 2; __expected.input = 'abcddddefg'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /cd*/.exec(\'abcddddefg\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /cd*/.exec(\'abcddddefg\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /cd*/.exec(\'abcddddefg\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /cd*/.exec(\'abcddddefg\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T12.js index 01fa409c0ddf..395efeb782c3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T12.js @@ -15,26 +15,30 @@ var __expected = ["cd"]; __expected.index = 2; __expected.input = 'abcdefg'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /cx*d/.exec(\'abcdefg\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /cx*d/.exec(\'abcdefg\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /cx*d/.exec(\'abcdefg\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /cx*d/.exec(\'abcdefg\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T13.js index ff5a91d01014..3923e10ceafc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T13.js @@ -15,26 +15,30 @@ var __expected = ["xxxxxxx","xxxxxx","x"]; __expected.index = 0; __expected.input = 'xxxxxxx'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(x*)(x+)/.exec(\'xxxxxxx\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(x*)(x+)/.exec(\'xxxxxxx\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(x*)(x+)/.exec(\'xxxxxxx\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(x*)(x+)/.exec(\'xxxxxxx\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T14.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T14.js index fbcce8bf5f65..b2c67150d20f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T14.js @@ -15,26 +15,30 @@ var __expected = ["1234567890","123456789","0"]; __expected.index = 0; __expected.input = '1234567890'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(\\d*)(\\d+)/.exec(\'1234567890\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(\\d*)(\\d+)/.exec(\'1234567890\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(\\d*)(\\d+)/.exec(\'1234567890\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(\\d*)(\\d+)/.exec(\'1234567890\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T15.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T15.js index 21008b0196a8..17d1e7401182 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T15.js @@ -15,26 +15,30 @@ var __expected = ["1234567890","12345678","0"]; __expected.index = 0; __expected.input = '1234567890'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(\\d*)\\d(\\d+)/.exec(\'1234567890\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(\\d*)\\d(\\d+)/.exec(\'1234567890\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(\\d*)\\d(\\d+)/.exec(\'1234567890\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(\\d*)\\d(\\d+)/.exec(\'1234567890\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T16.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T16.js index 49a2a454900e..7a6fb47f5853 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T16.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T16.js @@ -15,26 +15,30 @@ var __expected = ["xxxxxxx","xxxxxxx",""]; __expected.index = 0; __expected.input = 'xxxxxxx'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(x+)(x*)/.exec(\'xxxxxxx\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(x+)(x*)/.exec(\'xxxxxxx\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(x+)(x*)/.exec(\'xxxxxxx\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(x+)(x*)/.exec(\'xxxxxxx\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T17.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T17.js index b5b6889c3f6d..3b101535fdd3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T17.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T17.js @@ -15,26 +15,30 @@ var __expected = ["xxxxxxyyyyyy"]; __expected.index = 0; __expected.input = 'xxxxxxyyyyyy'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /x*y+$/.exec(\'xxxxxxyyyyyy\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /x*y+$/.exec(\'xxxxxxyyyyyy\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /x*y+$/.exec(\'xxxxxxyyyyyy\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /x*y+$/.exec(\'xxxxxxyyyyyy\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T18.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T18.js index fde8bccf1ee8..7a0bc65cde94 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T18.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T18.js @@ -15,26 +15,30 @@ var __expected = ["bcd"]; __expected.index = 1; __expected.input = 'abcdef'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[\\d]*[\\s]*bc./.exec(\'abcdef\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[\\d]*[\\s]*bc./.exec(\'abcdef\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[\\d]*[\\s]*bc./.exec(\'abcdef\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[\\d]*[\\s]*bc./.exec(\'abcdef\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T19.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T19.js index 1e51be8da063..602e50140adf 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T19.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T19.js @@ -15,26 +15,30 @@ var __expected = ["bcde"]; __expected.index = 1; __expected.input = 'abcdef'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /bc..[\\d]*[\\s]*/.exec(\'abcdef\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /bc..[\\d]*[\\s]*/.exec(\'abcdef\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /bc..[\\d]*[\\s]*/.exec(\'abcdef\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /bc..[\\d]*[\\s]*/.exec(\'abcdef\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T2.js index bcf492f846b0..58d918c35220 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T2.js @@ -15,26 +15,30 @@ var __expected = ["alice said: "]; __expected.index = 0; __expected.input = 'alice said: "don\'t"'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^"]*/.exec(\'alice said: "don\'t"\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^"]*/.exec(\'alice said: "don\'t"\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^"]*/.exec(\'alice said: "don\'t"\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^"]*/.exec(\'alice said: "don\'t"\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T20.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T20.js index 289b44f8d435..63b815f24f07 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T20.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T20.js @@ -15,26 +15,30 @@ var __expected = ["a1b2c3"]; __expected.index = 0; __expected.input = 'a1b2c3'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /.*/.exec(\'a1b2c3\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /.*/.exec(\'a1b2c3\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /.*/.exec(\'a1b2c3\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /.*/.exec(\'a1b2c3\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T21.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T21.js index f8a24ca6591c..cf968dbe01bd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T21.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T21.js @@ -11,9 +11,6 @@ description: Execute /[xyz]*1/.test('a0.b2.c3') and check results var __executed = /[xyz]*1/.test('a0.b2.c3'); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /[xyz]*1/.test(\'a0.b2.c3\') === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T3.js index 4f13416b1eaf..52bacbcce1e5 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T3.js @@ -15,26 +15,30 @@ var __expected = ["before\'i\'start"]; __expected.index = 0; __expected.input = "before\'i\'start"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^"]*/.exec("before\'i\'start"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^"]*/.exec("before\'i\'start"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^"]*/.exec("before\'i\'start"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^"]*/.exec("before\'i\'start"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T4.js index 44bcefd20feb..2b5411872007 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T4.js @@ -17,26 +17,30 @@ var __expected = ["alice "]; __expected.index = 0; __expected.input = 'alice \"sweep\": "don\'t"'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^"]*/.exec(\'alice \\"sweep\\": "don\'t"\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^"]*/.exec(\'alice \\"sweep\\": "don\'t"\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^"]*/.exec(\'alice \\"sweep\\": "don\'t"\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^"]*/.exec(\'alice \\"sweep\\": "don\'t"\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T5.js index 07887399ae2c..23a729ff412e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T5.js @@ -17,26 +17,30 @@ var __expected = ["alice "]; __expected.index = 0; __expected.input = 'alice "sweep": "don\'t"'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[^"]*/.exec(\'alice \\u0022sweep\\u0022: "don\'t"\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[^"]*/.exec(\'alice \\u0022sweep\\u0022: "don\'t"\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[^"]*/.exec(\'alice \\u0022sweep\\u0022: "don\'t"\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[^"]*/.exec(\'alice \\u0022sweep\\u0022: "don\'t"\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T6.js index 3b04f1895494..c4a1af3672b9 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T6.js @@ -17,26 +17,30 @@ var __expected = ["\"sweep\""]; __expected.index = 6; __expected.input = 'alice "sweep": "don\'t"'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /["\'][^"\']*["\']/.exec(\'alice \\u0022sweep\\u0022: "don\'t"\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /["\'][^"\']*["\']/.exec(\'alice \\u0022sweep\\u0022: "don\'t"\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /["\'][^"\']*["\']/.exec(\'alice \\u0022sweep\\u0022: "don\'t"\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /["\'][^"\']*["\']/.exec(\'alice \\u0022sweep\\u0022: "don\'t"\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T7.js index 081ab50a68bf..da460ae8c451 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T7.js @@ -17,26 +17,30 @@ var __expected = ["\'don\'"]; __expected.index = 17; __expected.input = 'alice cries out: \'don\'t\''; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /["\'][^"\']*["\']/.exec(\'alice cries out: \'don\'t\'\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /["\'][^"\']*["\']/.exec(\'alice cries out: \'don\'t\'\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /["\'][^"\']*["\']/.exec(\'alice cries out: \'don\'t\'\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /["\'][^"\']*["\']/.exec(\'alice cries out: \'don\'t\'\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T8.js index 3346c257bcbc..e8c14f6abcfa 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T8.js @@ -13,9 +13,6 @@ description: > var __executed = /["'][^"']*["']/.test('alice cries out: don\'t'); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /["\'][^"\']*["\']/.test(\'alice cries out: don\'t\') === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T9.js index ca58f58ba9bc..fe9bb0967960 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A4_T9.js @@ -17,26 +17,30 @@ var __expected = ['\"\"']; __expected.index = 16; __expected.input = 'alice cries out:\"\"'; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /["\'][^"\']*["\']/.exec(\'alice cries out:\\"\\"\'); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /["\'][^"\']*["\']/.exec(\'alice cries out:\\"\\"\'); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /["\'][^"\']*["\']/.exec(\'alice cries out:\\"\\"\'); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /["\'][^"\']*["\']/.exec(\'alice cries out:\\"\\"\'); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T1.js index 37181c366552..5e3c767f9add 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T1.js @@ -17,26 +17,30 @@ var __expected = ["javascript", "script"]; __expected.index = 7; __expected.input = "state: javascript is extension of ecma script"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /java(script)?/.exec("state: javascript is extension of ecma script"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /java(script)?/.exec("state: javascript is extension of ecma script"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /java(script)?/.exec("state: javascript is extension of ecma script"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /java(script)?/.exec("state: javascript is extension of ecma script"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T10.js index 67cc610ea161..ef584ffdd523 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T10.js @@ -15,26 +15,30 @@ var __expected = ["az"]; __expected.index = 3; __expected.input = "123az789"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /ab?c?d?x?y?z/.exec("123az789"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /ab?c?d?x?y?z/.exec("123az789"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /ab?c?d?x?y?z/.exec("123az789"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /ab?c?d?x?y?z/.exec("123az789"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T11.js index 6aeb7a706a1a..ff6e848627dd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T11.js @@ -15,26 +15,30 @@ var __expected = ["?????"]; __expected.index = 0; __expected.input = "?????"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\??\\??\\??\\??\\??/.exec("?????"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\??\\??\\??\\??\\??/.exec("?????"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\??\\??\\??\\??\\??/.exec("?????"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\??\\??\\??\\??\\??/.exec("?????"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T12.js index b9dd7a895c40..26ea7cf5f8eb 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T12.js @@ -15,26 +15,30 @@ var __expected = ["test"]; __expected.index = 0; __expected.input = "test"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /.?.?.?.?.?.?.?/.exec("test"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /.?.?.?.?.?.?.?/.exec("test"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /.?.?.?.?.?.?.?/.exec("test"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /.?.?.?.?.?.?.?/.exec("test"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T2.js index d1c68597be30..c564977263cc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T2.js @@ -17,26 +17,30 @@ var __expected = ["java", undefined]; __expected.index = 7; __expected.input = "state: java and javascript are vastly different"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /java(script)?/.exec("state: java and javascript are vastly different"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /java(script)?/.exec("state: java and javascript are vastly different"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /java(script)?/.exec("state: java and javascript are vastly different"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /java(script)?/.exec("state: java and javascript are vastly different"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T3.js index e3f082df449c..e1ffbf274d50 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T3.js @@ -13,9 +13,6 @@ description: > var __executed = /java(script)?/.test("state: both Java and JavaScript used in web development"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /java(script)?/.test("state: both Java and JavaScript used in web development") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T4.js index 8a2f7d6a8ed0..2d92531837dd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T4.js @@ -15,26 +15,30 @@ var __expected = ["cde"]; __expected.index = 2; __expected.input = "abcdef"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /cd?e/.exec("abcdef"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /cd?e/.exec("abcdef"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /cd?e/.exec("abcdef"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /cd?e/.exec("abcdef"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T5.js index 1977c2aeb7bc..e82cf268ec32 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T5.js @@ -15,26 +15,30 @@ var __expected = ["cde"]; __expected.index = 2; __expected.input = "abcdef"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /cdx?e/.exec("abcdef"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /cdx?e/.exec("abcdef"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /cdx?e/.exec("abcdef"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /cdx?e/.exec("abcdef"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T6.js index 45f948398b94..866129d5ca07 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T6.js @@ -15,26 +15,30 @@ var __expected = ["pqrst"]; __expected.index = 0; __expected.input = "pqrstuvw"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /o?pqrst/.exec("pqrstuvw"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /o?pqrst/.exec("pqrstuvw"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /o?pqrst/.exec("pqrstuvw"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /o?pqrst/.exec("pqrstuvw"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T7.js index 989a648bf821..2744ff1d60a2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T7.js @@ -15,26 +15,30 @@ var __expected = [""]; __expected.index = 0; __expected.input = "abcd"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /x?y?z?/.exec("abcd"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /x?y?z?/.exec("abcd"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /x?y?z?/.exec("abcd"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /x?y?z?/.exec("abcd"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T8.js index ba6f8a779ad1..71981332795e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T8.js @@ -15,26 +15,30 @@ var __expected = ["abc"]; __expected.index = 0; __expected.input = "abcd"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /x?ay?bz?c/.exec("abcd"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /x?ay?bz?c/.exec("abcd"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /x?ay?bz?c/.exec("abcd"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /x?ay?bz?c/.exec("abcd"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T9.js index 7f7481830183..400828d58389 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A5_T9.js @@ -15,26 +15,30 @@ var __expected = ["bbbb"]; __expected.index = 1; __expected.input = "abbbbc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /b?b?b?b/.exec("abbbbc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /b?b?b?b/.exec("abbbbc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /b?b?b?b/.exec("abbbbc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /b?b?b?b/.exec("abbbbc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T1.js index 047e465ae681..54c1647ee710 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T1.js @@ -16,26 +16,30 @@ var __expected = ["bbbbc"]; __expected.index = 3; __expected.input = "aaabbbbcccddeeeefffff"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /b{2,}c/.exec("aaabbbbcccddeeeefffff"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /b{2,}c/.exec("aaabbbbcccddeeeefffff"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /b{2,}c/.exec("aaabbbbcccddeeeefffff"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /b{2,}c/.exec("aaabbbbcccddeeeefffff"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T2.js index 6430ba27c24d..92975448cf6e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T2.js @@ -12,9 +12,6 @@ description: Execute /b{8,}c/.test("aaabbbbcccddeeeefffff") and check results var __executed = /b{8,}c/.test("aaabbbbcccddeeeefffff"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /b{8,}c/.test("aaabbbbcccddeeeefffff") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T3.js index 2b59d18cc6a5..3262cab91e3d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T3.js @@ -16,26 +16,30 @@ var __expected = ["456646"]; __expected.index = 3; __expected.input = "wqe456646dsff"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\d{1,}/.exec("wqe456646dsff"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\d{1,}/.exec("wqe456646dsff"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\d{1,}/.exec("wqe456646dsff"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\d{1,}/.exec("wqe456646dsff"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T4.js index a99ac16e7b09..fad3bca88bad 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T4.js @@ -16,26 +16,30 @@ var __expected = ["123123","123"]; __expected.index = 0; __expected.input = "123123"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(123){1,}/.exec("123123"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(123){1,}/.exec("123123"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(123){1,}/.exec("123123"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(123){1,}/.exec("123123"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T5.js index dd2d2fddd408..96fa2c7f7917 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T5.js @@ -16,26 +16,30 @@ var __expected = ["123123x123","123"]; __expected.index = 0; __expected.input = "123123x123"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(123){1,}x\\1/.exec("123123x123"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(123){1,}x\\1/.exec("123123x123"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(123){1,}x\\1\\/.exec("123123x123"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(123){1,}x\\1/.exec("123123x123"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T6.js index dd5ad9d8c9c2..32ede9c0a72c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.7_A6_T6.js @@ -16,26 +16,30 @@ var __expected = ["xxxxxxx"]; __expected.index = 0; __expected.input = "xxxxxxx"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /x{1,2}x{1,}/.exec("xxxxxxx"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /x{1,2}x{1,}/.exec("xxxxxxx"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /x{1,2}x{1,}/.exec("xxxxxxx"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /x{1,2}x{1,}/.exec("xxxxxxx"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T1.js index f329f9755956..29b1ff56af5d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T1.js @@ -16,26 +16,30 @@ var __expected = ["", "aaa"]; __expected.index = 1; __expected.input = "baaabac"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(?=(a+))/.exec("baaabac"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(?=(a+))/.exec("baaabac"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(?=(a+))/.exec("baaabac"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(?=(a+))/.exec("baaabac"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T2.js index 67c153a65a9b..2b7bb21a440e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T2.js @@ -16,26 +16,30 @@ var __expected = ["aba", "a"]; __expected.index = 3; __expected.input = "baaabac"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(?=(a+))a*b\\1/.exec("baaabac"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(?=(a+))a*b\\1/.exec("baaabac"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(?=(a+))a*b\\1/.exec("baaabac"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(?=(a+))a*b\\1/.exec("baaabac"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T3.js index 690d1d824a36..1c016971a675 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T3.js @@ -18,26 +18,30 @@ var __expected = ["Javascript", "script"]; __expected.index = 5; __expected.input = "just Javascript: the way af jedi"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[Jj]ava([Ss]cript)?(?=\\:)/.exec("just Javascript: the way af jedi"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[Jj]ava([Ss]cript)?(?=\\:)/.exec("just Javascript: the way af jedi"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[Jj]ava([Ss]cript)?(?=\\:)/.exec("just Javascript: the way af jedi"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[Jj]ava([Ss]cript)?(?=\\:)/.exec("just Javascript: the way af jedi"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T4.js index a460e7aba858..250f19027ca5 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T4.js @@ -18,26 +18,30 @@ var __expected = ["java", undefined]; __expected.index = 9; __expected.input = "taste of java: the cookbook "; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[Jj]ava([Ss]cript)?(?=\\:)/.exec("taste of java: the cookbook "); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[Jj]ava([Ss]cript)?(?=\\:)/.exec("taste of java: the cookbook "); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[Jj]ava([Ss]cript)?(?=\\:)/.exec("taste of java: the cookbook "); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[Jj]ava([Ss]cript)?(?=\\:)/.exec("taste of java: the cookbook "); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T5.js index 1a6d9ad563e6..411525199812 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A1_T5.js @@ -14,9 +14,6 @@ description: > var __executed = /[Jj]ava([Ss]cript)?(?=\:)/.test("rhino is JavaScript engine"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /[Jj]ava([Ss]cript)?(?=\\:)/.test("rhino is JavaScript engine") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T1.js index 90dd912d388e..97af14fa673f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T1.js @@ -18,26 +18,30 @@ var __expected = ["baaabaac", "ba", undefined, "abaac"]; __expected.index = 0; __expected.input = "baaabaac"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(.*?)a(?!(a+)b\\2c)\\2(.*)/.exec("baaabaac"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(.*?)a(?!(a+)b\\2c)\\2(.*)/.exec("baaabaac"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(.*?)a(?!(a+)b\\2c)\\2(.*)/.exec("baaabaac"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(.*?)a(?!(a+)b\\2c)\\2(.*)/.exec("baaabaac"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T10.js index d4de33bf8a27..4bf35f2a06e0 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T10.js @@ -16,26 +16,30 @@ var __expected = [""]; __expected.index = 1; __expected.input = "bc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(?!a|b)|c/.exec("bc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(?!a|b)|c/.exec("bc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(?!a|b)|c/.exec("bc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(?!a|b)|c/.exec("bc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T11.js index c460334b2c0f..11ac98acbef8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T11.js @@ -16,26 +16,30 @@ var __expected = [""]; __expected.index = 0; __expected.input = "d"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(?!a|b)|c/.exec("d"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(?!a|b)|c/.exec("d"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(?!a|b)|c/.exec("d"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(?!a|b)|c/.exec("d"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T2.js index 4fea491548df..d6b8b49fde92 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T2.js @@ -18,26 +18,30 @@ var __expected = ["JavaBeans", "Beans"]; __expected.index = 9; __expected.input = "using of JavaBeans technology"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /Java(?!Script)([A-Z]\\w*)/.exec("using of JavaBeans technology"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /Java(?!Script)([A-Z]\\w*)/.exec("using of JavaBeans technology"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /Java(?!Script)([A-Z]\\w*)/.exec("using of JavaBeans technology"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /Java(?!Script)([A-Z]\\w*)/.exec("using of JavaBeans technology"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T3.js index edf58da53752..79cc4000a9d2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T3.js @@ -14,9 +14,6 @@ description: > var __executed = /Java(?!Script)([A-Z]\w*)/.test("using of Java language"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /Java(?!Script)([A-Z]\\w*)/.test("using of Java language") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T4.js index 02f275de3b21..1739ef884cbb 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T4.js @@ -14,9 +14,6 @@ description: > var __executed = /Java(?!Script)([A-Z]\w*)/.test("i'm a JavaScripter "); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /Java(?!Script)([A-Z]\\w*)/.test("i\'m a JavaScripter ") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T5.js index 38c242219775..19941de31198 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T5.js @@ -18,26 +18,30 @@ var __expected = ["JavaScr", "Scr"]; __expected.index = 0; __expected.input = "JavaScr oops ipt "; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /Java(?!Script)([A-Z]\\w*)/.exec("JavaScr oops ipt "); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /Java(?!Script)([A-Z]\\w*)/.exec("JavaScr oops ipt "); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /Java(?!Script)([A-Z]\\w*)/.exec("JavaScr oops ipt "); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /Java(?!Script)([A-Z]\\w*)/.exec("JavaScr oops ipt "); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T6.js index a6704cb076ba..6422a3f64176 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T6.js @@ -16,26 +16,30 @@ var __expected = ['.', '.']; __expected.index = 2; __expected.input = "ah.info"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(\\.(?!com|org)|\\/)/.exec("ah.info"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(\\.(?!com|org)|\\/)/.exec("ah.info"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(\\.(?!com|org)|\\/)/.exec("ah.info"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(\\.(?!com|org)|\\/)/.exec("ah.info"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T7.js index 8941733be216..50a6ab57b107 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T7.js @@ -16,26 +16,30 @@ var __expected = ['/', '/']; __expected.index = 2; __expected.input = "ah/info"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(\\.(?!com|org)|\\/)/.exec("ah/info"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(\\.(?!com|org)|\\/)/.exec("ah/info"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(\\.(?!com|org)|\\/)/.exec("ah/info"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(\\.(?!com|org)|\\/)/.exec("ah/info"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T8.js index 219fc2df473f..6ae39b2fd6c2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T8.js @@ -12,9 +12,6 @@ description: Execute /(\.(?!com|org)|\/)/.test("ah.com") and check results var __executed = /(\.(?!com|org)|\/)/.test("ah.com"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /(\\.(?!com|org)|\\/)/.test("ah.com") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T9.js index 02c94ac11a5d..5450143ebddb 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A2_T9.js @@ -16,26 +16,30 @@ var __expected = [""]; __expected.index = 0; __expected.input = ""; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(?!a|b)|c/.exec(""); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(?!a|b)|c/.exec(""); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(?!a|b)|c/.exec(""); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(?!a|b)|c/.exec(""); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T1.js index 64f96f8c809d..cf6d753d7533 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T1.js @@ -19,26 +19,30 @@ var __expected = ["javaScript is funny","javaScript","Script","funny"]; __expected.index = 9; __expected.input = "Learning javaScript is funny, really"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.exec("Learning javaScript is funny, really"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.exec("Learning javaScript is funny, really"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.exec("Learning javaScript is funny, really"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.exec("Learning javaScript is funny, really"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T10.js index e5d2aff732f3..5277cdb72125 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T10.js @@ -17,26 +17,30 @@ var __expected = ["123456123456","123","456"]; __expected.index = 0; __expected.input = "123456123456"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(\\d{3})(\\d{3})\\1\\2/.exec("123456123456"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(\\d{3})(\\d{3})\\1\\2/.exec("123456123456"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(\\d{3})(\\d{3})\\1\\2/.exec("123456123456"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(\\d{3})(\\d{3})\\1\\2/.exec("123456123456"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T11.js index 7ad4ab9a22f7..8ef2996ce663 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T11.js @@ -17,26 +17,30 @@ var __expected = ["abcdefg","bcdefg","de"]; __expected.index = 0; __expected.input = "abcdefgh"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a(..(..)..)/.exec("abcdefgh"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a(..(..)..)/.exec("abcdefgh"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a(..(..)..)/.exec("abcdefgh"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a(..(..)..)/.exec("abcdefgh"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T12.js index 7b859da454eb..ecd890165932 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T12.js @@ -17,26 +17,30 @@ var __expected = ["abcdef","abc","bc","c","def","ef","f"]; __expected.index = 1; __expected.input = "xabcdefg"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(a(b(c)))(d(e(f)))/.exec("xabcdefg"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(a(b(c)))(d(e(f)))/.exec("xabcdefg"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(a(b(c)))(d(e(f)))/.exec("xabcdefg"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(a(b(c)))(d(e(f)))/.exec("xabcdefg"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T13.js index b10ddf4ade21..c16fe9f704a3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T13.js @@ -19,26 +19,30 @@ var __expected = ["abcdefbcef","abc","bc","c","def","ef","f"]; __expected.index = 1; __expected.input = "xabcdefbcefg"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(a(b(c)))(d(e(f)))\\2\\5/.exec("xabcdefbcefg"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(a(b(c)))(d(e(f)))\\2\\5/.exec("xabcdefbcefg"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(a(b(c)))(d(e(f)))\\2\\5/.exec("xabcdefbcefg"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(a(b(c)))(d(e(f)))\\2\\5/.exec("xabcdefbcefg"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T14.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T14.js index f3ae85d3acb2..c0bfcf61277a 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T14.js @@ -17,26 +17,30 @@ var __expected = ["abcd",""]; __expected.index = 0; __expected.input = "abcd"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a(.?)b\\1c\\1d\\1/.exec("abcd"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a(.?)b\\1c\\1d\\1/.exec("abcd"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a(.?)b\\1c\\1d\\1/.exec("abcd"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a(.?)b\\1c\\1d\\1/.exec("abcd"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T15.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T15.js index fb89221b47cb..07133691c188 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T15.js @@ -16,15 +16,15 @@ var __openParen = '('; var __closeParen = ')'; var __pattern = ''; var numParens = 200; - + for (var i=0; iKibology for all

\n

All for Kibology

\n' __expected.index = 7; __expected.input = __html; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /((.*\\n?)*?)<\\/body>/i.exec(__html); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /((.*\\n?)*?)<\\/body>/i.exec(__html); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /((.*\\n?)*?)<\\/body>/i.exec(__html); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /((.*\\n?)*?)<\\/body>/i.exec(__html); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T18.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T18.js index f859c2a6ef94..d5a6abd51643 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T18.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T18.js @@ -15,9 +15,6 @@ var __replaced = "To sign up click |here|https:www.xxxx.org/subscribe.htm|".repl var __expected = 'To sign up click here'; -//CHECK#1 -if (__replaced !== __expected) { - throw new Test262Error('#1: __replaced = "To sign up click |here|https:www.xxxx.org/subscribe.htm|".replace(/(\\|)([\\w\\x81-\\xff ]*)(\\|)([\\/a-z][\\w:\\/\\.]*\\.[a-z]{3,4})(\\|)/ig, \'$2\'); __replaced === ' + __expected + '. Actual: ' + __replaced); -} +assert.sameValue(__replaced, __expected, 'The value of __replaced is expected to equal the value of __expected'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T19.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T19.js index 8e25d564f3b1..d4ceeb97496e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T19.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T19.js @@ -19,26 +19,30 @@ var __expected = ["Course_Creator = Test","Course_Creator",undefined]; __expected.index = 0; __expected.input = "Course_Creator = Test"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /([\\S]+([ \\t]+[\\S]+)*)[ \\t]*=[ \\t]*[\\S]+/.exec("Course_Creator = Test"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /([\\S]+([ \\t]+[\\S]+)*)[ \\t]*=[ \\t]*[\\S]+/.exec("Course_Creator = Test"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /([\\S]+([ \\t]+[\\S]+)*)[ \\t]*=[ \\t]*[\\S]+/.exec("Course_Creator = Test"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /([\\S]+([ \\t]+[\\S]+)*)[ \\t]*=[ \\t]*[\\S]+/.exec("Course_Creator = Test"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T2.js index 5c421b0eb8d0..370a1abc2691 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T2.js @@ -19,26 +19,30 @@ var __expected = ["Java is fun","Java",undefined,"fun"]; __expected.index = 16; __expected.input = "Developing with Java is fun, try it"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.exec("Developing with Java is fun, try it"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.exec("Developing with Java is fun, try it"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.exec("Developing with Java is fun, try it"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.exec("Developing with Java is fun, try it"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T20.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T20.js index b81fbdbf32b2..71c30023d159 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T20.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T20.js @@ -17,26 +17,30 @@ var __expected = ["AAA","A","AA"]; __expected.index = 0; __expected.input = "AAA"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^(A)?(A.*)$/.exec("AAA"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^(A)?(A.*)$/.exec("AAA"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^(A)?(A.*)$/.exec("AAA"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^(A)?(A.*)$/.exec("AAA"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T21.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T21.js index 37e21a4ba5a4..0d4447f05485 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T21.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T21.js @@ -17,26 +17,30 @@ var __expected = ["AA","A","A"]; __expected.index = 0; __expected.input = "AA"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^(A)?(A.*)$/.exec("AA"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^(A)?(A.*)$/.exec("AA"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^(A)?(A.*)$/.exec("AA"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^(A)?(A.*)$/.exec("AA"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T22.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T22.js index 8fe19e712588..4f1c2aad1de2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T22.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T22.js @@ -17,26 +17,30 @@ var __expected = ["A",undefined,"A"]; __expected.index = 0; __expected.input = "A"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /^(A)?(A.*)$/.exec("A"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /^(A)?(A.*)$/.exec("A"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /^(A)?(A.*)$/.exec("A"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /^(A)?(A.*)$/.exec("A"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T23.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T23.js index fb0556df1204..36fe0946a0c2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T23.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T23.js @@ -21,26 +21,30 @@ var __expected = ["AAAaaAAaaaf;lrlrzs","A","AAaaAAaaaf;lrlrzs"]; __expected.index = 13; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "zxcasd;fl\\\ ^AAAaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "zxcasd;fl\\\ ^AAAaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "zxcasd;fl\\\ ^AAAaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "zxcasd;fl\\\ ^AAAaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T24.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T24.js index 3f1f76a18193..f77fcd6d4bf3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T24.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T24.js @@ -21,26 +21,30 @@ var __expected = ["AAaaAAaaaf;lrlrzs","A","AaaAAaaaf;lrlrzs"]; __expected.index = 13; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "zxcasd;fl\\\ ^AAaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "zxcasd;fl\\\ ^AAaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "zxcasd;fl\\\ ^AAaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "zxcasd;fl\\\ ^AAaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T25.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T25.js index f1df4136c6d1..bb7309293bfc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T25.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T25.js @@ -21,26 +21,30 @@ var __expected = ["AaaAAaaaf;lrlrzs",undefined,"AaaAAaaaf;lrlrzs"]; __expected.index = 13; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "zxcasd;fl\\\ ^AaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "zxcasd;fl\\\ ^AaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "zxcasd;fl\\\ ^AaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "zxcasd;fl\\\ ^AaaAAaaaf;lrlrzs"; __executed = /(A)?(A.*)/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T26.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T26.js index 9edf3318435b..f87e8e9421fb 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T26.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T26.js @@ -19,26 +19,30 @@ var __expected = ["a",undefined]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "a"; __executed = /(a)?a/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "a"; __executed = /(a)?a/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "a"; __executed = /(a)?a/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "a"; __executed = /(a)?a/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T27.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T27.js index a63d54e35ac5..2cd86fb3e89a 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T27.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T27.js @@ -19,26 +19,30 @@ var __expected = ["a",undefined]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "a"; __executed = /a|(b)/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "a"; __executed = /a|(b)/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "a"; __executed = /a|(b)/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "a"; __executed = /a|(b)/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T28.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T28.js index b2543bc9672a..08d6919c8aa2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T28.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T28.js @@ -19,26 +19,30 @@ var __expected = ['a', undefined, 'a']; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "a"; __executed = /(a)?(a)/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "a"; __executed = /(a)?(a)/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "a"; __executed = /(a)?(a)/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "a"; __executed = /(a)?(a)/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T29.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T29.js index e0e1fd1ee7a8..b0e0906fe1d8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T29.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T29.js @@ -19,26 +19,30 @@ var __expected = ['a', undefined]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "a"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "a"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "a"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "a"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T3.js index bdd00961eff2..2a8065a982d7 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T3.js @@ -16,9 +16,6 @@ description: > var __executed = /([Jj]ava([Ss]cript)?)\sis\s(fun\w*)/.test("Developing with JavaScript is dangerous, do not try it without assistance"); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: /([Jj]ava([Ss]cript)?)\\sis\\s(fun\\w*)/.test("Developing with JavaScript is dangerous, do not try it without assistance") === false'); -} +assert(!__executed, 'The value of !__executed is expected to be true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T30.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T30.js index 61c13627d4a0..2eeccafe13c7 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T30.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T30.js @@ -19,26 +19,30 @@ var __expected = ['ab', "a"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "ab"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "ab"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "ab"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "ab"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T31.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T31.js index 8354167c9542..0ea67e654882 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T31.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T31.js @@ -19,26 +19,30 @@ var __expected = ['abc', "ab"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "abc"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "abc"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "abc"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "abc"; __executed = /^([a-z]+)*[a-z]$/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T32.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T32.js index 7e7c48280ee6..82df62b73211 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T32.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T32.js @@ -19,26 +19,30 @@ var __expected = ['www.netscape.com', 'netscape.', 'netscap']; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "www.netscape.com"; __executed = /^(([a-z]+)*[a-z]\\.)+[a-z]{2,}$/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "www.netscape.com"; __executed = /^(([a-z]+)*[a-z]\\.)+[a-z]{2,}$/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "www.netscape.com"; __executed = /^(([a-z]+)*[a-z]\\.)+[a-z]{2,}$/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "www.netscape.com"; __executed = /^(([a-z]+)*[a-z]\\.)+[a-z]{2,}$/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T33.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T33.js index 699050404e8a..8d4c4ca701f2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T33.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T33.js @@ -19,26 +19,30 @@ var __expected = ['www.netscape.com', 'netscape.', 'netscap', 'e']; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "www.netscape.com"; __executed = /^(([a-z]+)*([a-z])\\.)+[a-z]{2,}$/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "www.netscape.com"; __executed = /^(([a-z]+)*([a-z])\\.)+[a-z]{2,}$/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "www.netscape.com"; __executed = /^(([a-z]+)*([a-z])\\.)+[a-z]{2,}$/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "www.netscape.com"; __executed = /^(([a-z]+)*([a-z])\\.)+[a-z]{2,}$/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T4.js index 221eb109b8f2..c5cc745c4400 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T4.js @@ -17,26 +17,30 @@ var __expected = ["abc","abc"]; __expected.index = 0; __expected.input = "abc"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(abc)/.exec("abc"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(abc)/.exec("abc"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(abc)/.exec("abc"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(abc)/.exec("abc"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T5.js index 4d8c999e0113..c7653979c385 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T5.js @@ -17,26 +17,30 @@ var __expected = ["abcdefg","bc","ef"]; __expected.index = 0; __expected.input = "abcdefg"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a(bc)d(ef)g/.exec("abcdefg"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a(bc)d(ef)g/.exec("abcdefg"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a(bc)d(ef)g/.exec("abcdefg"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a(bc)d(ef)g/.exec("abcdefg"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T6.js index 3fb01f1b5f3e..ef359a9be90b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T6.js @@ -17,26 +17,30 @@ var __expected = ["abcdefg","abc","defg"]; __expected.index = 0; __expected.input = "abcdefgh"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(.{3})(.{4})/.exec("abcdefgh"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(.{3})(.{4})/.exec("abcdefgh"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(.{3})(.{4})/.exec("abcdefgh"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(.{3})(.{4})/.exec("abcdefgh"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T7.js index 5080ccc2565a..97ba72a59009 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T7.js @@ -17,26 +17,30 @@ var __expected = ["aabcdaa","aa"]; __expected.index = 0; __expected.input = "aabcdaabcd"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(aa)bcd\\1/.exec("aabcdaabcd"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(aa)bcd\\1/.exec("aabcdaabcd"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(aa)bcd\\1/.exec("aabcdaabcd"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(aa)bcd\\1/.exec("aabcdaabcd"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T8.js index 75e9b4b8b312..6432cbbec91d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T8.js @@ -17,26 +17,30 @@ var __expected = ["aabcdaa","aa"]; __expected.index = 0; __expected.input = "aabcdaabcd"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(aa).+\\1/.exec("aabcdaabcd"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(aa).+\\1/.exec("aabcdaabcd"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(aa).+\\1/.exec("aabcdaabcd"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(aa).+\\1/.exec("aabcdaabcd"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T9.js index 2a1bf2f8d0b4..5d59ba7bdf78 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A3_T9.js @@ -17,26 +17,30 @@ var __expected = ["aabcdaa","aa"]; __expected.index = 0; __expected.input = "aabcdaabcd"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(.{2}).+\\1/.exec("aabcdaabcd"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(.{2}).+\\1/.exec("aabcdaabcd"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(.{2}).+\\1/.exec("aabcdaabcd"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(.{2}).+\\1/.exec("aabcdaabcd"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T1.js index db0b50c77e2c..4553d6d26489 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T1.js @@ -17,26 +17,30 @@ var __expected = ["abcde"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "abcde"; __executed = /ab.de/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "abcde"; __executed = /ab.de/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "abcde"; __executed = /ab.de/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "abcde"; __executed = /ab.de/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T2.js index fec3edc1c397..d455db122670 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T2.js @@ -17,26 +17,30 @@ var __expected = ["line 1"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "line 1\nline 2"; __executed = /.+/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "line 1\nline 2"; __executed = /.+/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "line 1\nline 2"; __executed = /.+/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "line 1\nline 2"; __executed = /.+/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T3.js index 9ba86b46cc83..57a9cc0b9593 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T3.js @@ -17,26 +17,30 @@ var __expected = ["this is a test"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "this is a test"; __executed = /.*a.*/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "this is a test"; __executed = /.*a.*/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "this is a test"; __executed = /.*a.*/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "this is a test"; __executed = /.*a.*/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T4.js index e435f367ad5a..eb141a1878ce 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T4.js @@ -17,26 +17,30 @@ var __expected = ["this is a *&^%$# test"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "this is a *&^%$# test"; __executed = /.+/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "this is a *&^%$# test"; __executed = /.+/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "this is a *&^%$# test"; __executed = /.+/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "this is a *&^%$# test"; __executed = /.+/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T5.js index a39b25de0045..1beaa1ebad35 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T5.js @@ -17,26 +17,30 @@ var __expected = ["...."]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "...."; __executed = /.+/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "...."; __executed = /.+/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "...."; __executed = /.+/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "...."; __executed = /.+/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T6.js index 5f2338b332d9..eaa7d66da164 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T6.js @@ -17,26 +17,30 @@ var __expected = ["abcdefghijklmnopqrstuvwxyz"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "abcdefghijklmnopqrstuvwxyz"; __executed = /.+/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "abcdefghijklmnopqrstuvwxyz"; __executed = /.+/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "abcdefghijklmnopqrstuvwxyz"; __executed = /.+/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "abcdefghijklmnopqrstuvwxyz"; __executed = /.+/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T7.js index 6b2355c7fdd8..227a1d577cbb 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T7.js @@ -17,26 +17,30 @@ var __expected = ["ABCDEFGHIJKLMNOPQRSTUVWXYZ"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; __executed = /.+/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; __executed = /.+/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; __executed = /.+/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; __executed = /.+/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T8.js index 7b4104087760..8b94b062d034 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T8.js @@ -17,26 +17,30 @@ var __expected = ["`1234567890-=~!@#$%^&*()_+"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "`1234567890-=~!@#$%^&*()_+"; __executed = /.+/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "`1234567890-=~!@#$%^&*()_+"; __executed = /.+/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "`1234567890-=~!@#$%^&*()_+"; __executed = /.+/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "`1234567890-=~!@#$%^&*()_+"; __executed = /.+/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T9.js index eb06ecc05aee..3b5060ff54fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A4_T9.js @@ -17,26 +17,30 @@ var __expected = ["|\\[{]};:\"\',<>.?/"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "|\\[{]};:\"\',<>.?/"; __executed = /.+/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "|\\[{]};:\"\',<>.?/"; __executed = /.+/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "|\\[{]};:\"\',<>.?/"; __executed = /.+/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "|\\[{]};:\"\',<>.?/"; __executed = /.+/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A5_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A5_T1.js index 0093360b7189..f68b8c0ff928 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A5_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A5_T1.js @@ -16,26 +16,30 @@ var __expected = ["ABC"]; __expected.index = 0; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "ABC def ghi"; __executed = /[a-z]+/ig.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "ABC def ghi"; __executed = /[a-z]+/ig.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "ABC def ghi"; __executed = /[a-z]+/ig.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "ABC def ghi"; __executed = /[a-z]+/ig.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A5_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A5_T2.js index 7fe224a17c76..e193e1c6dc6e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A5_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.8_A5_T2.js @@ -16,26 +16,30 @@ var __expected = ["def"]; __expected.index = 4; __expected.input = __string; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __string = "ABC def ghi"; __executed = /[a-z]+/.exec(__string); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __string = "ABC def ghi"; __executed = /[a-z]+/.exec(__string); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __string = "ABC def ghi"; __executed = /[a-z]+/.exec(__string); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __string = "ABC def ghi"; __executed = /[a-z]+/.exec(__string); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T1.js index 9860f3d8dea2..dd3b69b5166b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T1.js @@ -18,26 +18,30 @@ var __expected = ["the the", "the"]; __expected.index = 14; __expected.input = "do you listen the the band"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\b(\\w+) \\1\\b/.exec("do you listen the the band"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\b(\\w+) \\1\\b/.exec("do you listen the the band"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\b(\\w+) \\1\\b/.exec("do you listen the the band"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\b(\\w+) \\1\\b/.exec("do you listen the the band"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T2.js index a6441a8ccbcf..cf1749de1b0f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T2.js @@ -19,26 +19,30 @@ var __expected = ["x01x01", "x01", undefined]; __expected.index = 6; __expected.input = "x09x12x01x01u00FFu00FFx04x04x23"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /([xu]\\d{2}([A-H]{2})?)\\1/.exec("x09x12x01x01u00FFu00FFx04x04x23"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /([xu]\\d{2}([A-H]{2})?)\\1/.exec("x09x12x01x01u00FFu00FFx04x04x23"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /([xu]\\d{2}([A-H]{2})?)\\1/.exec("x09x12x01x01u00FFu00FFx04x04x23"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /([xu]\\d{2}([A-H]{2})?)\\1/.exec("x09x12x01x01u00FFu00FFx04x04x23"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T3.js index ef492f3c8763..a85b267c4b7c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T3.js @@ -19,26 +19,30 @@ var __expected = ["u00FFu00FF", "u00FF", "FF"]; __expected.index = 12; __expected.input = "x09x12x01x05u00FFu00FFx04x04x23"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /([xu]\\d{2}([A-H]{2})?)\\1/.exec("x09x12x01x05u00FFu00FFx04x04x23"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /([xu]\\d{2}([A-H]{2})?)\\1/.exec("x09x12x01x05u00FFu00FFx04x04x23"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /([xu]\\d{2}([A-H]{2})?)\\1/.exec("x09x12x01x05u00FFu00FFx04x04x23"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /([xu]\\d{2}([A-H]{2})?)\\1/.exec("x09x12x01x05u00FFu00FFx04x04x23"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T5.js index 5825028d9157..b7b229137d1d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2.9_A1_T5.js @@ -16,26 +16,30 @@ var __expected = ["b", ""]; __expected.index = 0; __expected.input = "baaac"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(a*)b\\1+/.exec("baaac"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(a*)b\\1+/.exec("baaac"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(a*)b\\1+/.exec("baaac"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(a*)b\\1+/.exec("baaac"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.2_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.2_A1_T1.js index e127e44e6ce6..3e12893222a3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.2_A1_T1.js @@ -73,16 +73,17 @@ var __html=""+ ''; ////////////////////////////////////////////////////////////////////////////// -//CHECK#1 try { for(var index=0; index<__patterns.length; index++) { - var __re = new RegExp(__patterns[index]); - __re.test(__html); + var __re = new RegExp(__patterns[index]); + __re.test(__html); } } catch (e) { - throw new Test262Error('#'+index+": XML Shallow Parsing with Regular Expression: "+__patterns[index]); + throw new Test262Error('#'+index+": XML Shallow Parsing with Regular Expression: "+__patterns[index]); } // ////////////////////////////////////////////////////////////////////////////// +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T1.js index ed827d95dcd1..8f8f6684dbad 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T1.js @@ -13,9 +13,6 @@ var __re = /x/i; var __instance = RegExp(__re); __re.indicator = 1; -//CHECK#1 -if (__instance.indicator !== 1) { - throw new Test262Error('#1: __re = /x/i; __instance = RegExp(__re); __re.indicator = 1; __instance.indicator === 1. Actual: ' + (__instance.indicator)); -} +assert.sameValue(__instance.indicator, 1, 'The value of __instance.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T2.js index 90644417c33c..11475d948905 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T2.js @@ -13,9 +13,6 @@ var __re = new RegExp; var __instance = RegExp(__re, function(){}()); __re.indicator = 1; -//CHECK#1 -if (__instance.indicator !== 1) { - throw new Test262Error('#1: __re = new RegExp; __instance = RegExp(__re, function(){}()); __re.indicator = 1; __instance.indicator === 1. Actual: ' + (__instance.indicator)); -} +assert.sameValue(__instance.indicator, 1, 'The value of __instance.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T3.js index 39c6aea8b833..1a874b169ddf 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T3.js @@ -15,10 +15,7 @@ var __re = new RegExp(); var __instance = RegExp(__re, x); __re.indicator = 1; -//CHECK#1 -if (__instance.indicator !== 1) { - throw new Test262Error('#1: __re = new RegExp(); __instance = RegExp(__re, x); __re.indicator = 1; __instance.indicator === 1. Actual: ' + (__instance.indicator)); -} +assert.sameValue(__instance.indicator, 1, 'The value of __instance.indicator is expected to be 1'); var x; diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T4.js index fc76b423c972..8f8d32b5a4ad 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T4.js @@ -13,9 +13,6 @@ var __re = RegExp(); var __instance = RegExp(__re, void 0); __re.indicator = 1; -//CHECK#1 -if (__instance.indicator !== 1) { - throw new Test262Error('#1: __re = RegExp(); __instance = RegExp(__re, void 0); __re.indicator = 1; __instance.indicator === 1. Actual: ' + (__instance.indicator)); -} +assert.sameValue(__instance.indicator, 1, 'The value of __instance.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T5.js index 02fb24bdfd7a..cd727579eab1 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A1_T5.js @@ -13,9 +13,6 @@ var __re = /\b/m; var __instance = RegExp(__re, undefined); __re.indicator = 1; -//CHECK#1 -if (__instance.indicator !== 1) { - throw new Test262Error('#1: __re = /\\b/m; __instance = RegExp(__re, undefined); __re.indicator = 1; __instance.indicator === 1. Actual: ' + (__instance.indicator)); -} +assert.sameValue(__instance.indicator, 1, 'The value of __instance.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A2_T1.js index e943ed309ba6..c0665191da80 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A2_T1.js @@ -11,13 +11,16 @@ description: > exception ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: RegExp(new RegExp("\\d"), "1")) throw SyntaxError. Actual: ' + (RegExp(new RegExp("\d"), "1"))); + throw new Test262Error('#1.1: RegExp(new RegExp("\\d"), "1")) throw SyntaxError. Actual: ' + (RegExp(new RegExp("\d"), "1"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: RegExp(new RegExp("\\d"), "1")) throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A2_T2.js index 77a5358d57f1..9b4b4c8bc141 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A2_T2.js @@ -13,13 +13,16 @@ description: > var x = 1; -//CHECK#1 try { - throw new Test262Error('#1.1: var x = 1; RegExp(/[a-b]?/, x) throw SyntaxError. Actual: ' + (RegExp(/[a-b]?/, x))); + throw new Test262Error('#1.1: var x = 1; RegExp(/[a-b]?/, x) throw SyntaxError. Actual: ' + (RegExp(/[a-b]?/, x))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: var x = 1; RegExp(/[a-b]?/, x) throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A3_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A3_T1.js index 6c6613f896d9..cedc3e13e74c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A3_T1.js @@ -12,14 +12,12 @@ description: R is "d+" and instance is RegExp(R,"i") var __re = "d+"; var __instance = RegExp(__re, "i"); -//CHECK#1 -if (__instance.constructor !== RegExp) { - throw new Test262Error('#1: __re = "d+"; __instance = RegExp(__re, "i"); __instance.constructor === RegExp. Actual: ' + (__instance.constructor)); -} +assert.sameValue( + __instance.constructor, + RegExp, + 'The value of __instance.constructor is expected to equal the value of RegExp' +); -//CHECK#2 -if (__instance.source !== __re) { - throw new Test262Error('#2: __re = "d+"; __instance = RegExp(__re, "i"); __instance.source === __re. Actual: '+ (__instance.source)); -} +assert.sameValue(__instance.source, __re, 'The value of __instance.source is expected to equal the value of __re'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A3_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A3_T2.js index b9e1fdf4505a..85cc4f867b62 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.3.1_A3_T2.js @@ -13,14 +13,12 @@ description: > var __instance = RegExp({toString:function(){return "[a-c]*";}}, "gm"); -//CHECK#1 -if (__instance.constructor !== RegExp) { - throw new Test262Error('#1: __instance = RegExp({toString:function(){return "[a-c]*";}}, "gm"); __instance.constructor === RegExp. Actual: ' + (__instance.constructor)); -} +assert.sameValue( + __instance.constructor, + RegExp, + 'The value of __instance.constructor is expected to equal the value of RegExp' +); -//CHECK#2 -if (__instance.source !== "[a-c]*") { - throw new Test262Error('#2: __instance = RegExp({toString:function(){return "[a-c]*";}}, "gm"); __instance.source === "[a-c]*". Actual: '+ (__instance.source)); -} +assert.sameValue(__instance.source, "[a-c]*", 'The value of __instance.source is expected to be "[a-c]*"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T1.js index 430486faa6ad..ae28f243d3f5 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T1.js @@ -10,26 +10,30 @@ description: Pattern is /./i and RegExp is new RegExp(pattern) ---*/ var __pattern = /./i; -var __re = new RegExp(__pattern); +var __re = new RegExp(__pattern); -//CHECK#1 -if (__re.source !== __pattern.source) { - throw new Test262Error('#1: __pattern = /./i; __re = new RegExp(__pattern); __re.source === __pattern.source. Actual: '+ (__re.source)); -} +assert.sameValue( + __re.source, + __pattern.source, + 'The value of __re.source is expected to equal the value of __pattern.source' +); -//CHECK#2 -if (__re.multiline !== __pattern.multiline) { - throw new Test262Error('#2: __pattern = /./i; __re = new RegExp(__pattern); __re.multiline === __pattern.multiline. Actual: ' + (__re.multiline)); -} +assert.sameValue( + __re.multiline, + __pattern.multiline, + 'The value of __re.multiline is expected to equal the value of __pattern.multiline' +); -//CHECK#3 -if (__re.global !== __pattern.global) { - throw new Test262Error('#3: __pattern = /./i; __re = new RegExp(__pattern); __re.global === __pattern.global. Actual: ' + (__re.global)); -} +assert.sameValue( + __re.global, + __pattern.global, + 'The value of __re.global is expected to equal the value of __pattern.global' +); -//CHECK#4 -if (__re.ignoreCase !== __pattern.ignoreCase) { - throw new Test262Error('#4: __pattern = /./i; __re = new RegExp(__pattern); __re.ignoreCase === __pattern.ignoreCase. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue( + __re.ignoreCase, + __pattern.ignoreCase, + 'The value of __re.ignoreCase is expected to equal the value of __pattern.ignoreCase' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T2.js index 56c4c771be0d..00c78df977e0 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T2.js @@ -14,25 +14,29 @@ description: > var __pattern = /\t/m; var __re = new RegExp(__pattern, x); -//CHECK#1 -if (__re.source !== __pattern.source) { - throw new Test262Error('#1: __pattern = /\\t/m; _re = new RegExp(__pattern, x); var x; __re.source === __pattern.source. Actual: '+ (__re.source)); -} +assert.sameValue( + __re.source, + __pattern.source, + 'The value of __re.source is expected to equal the value of __pattern.source' +); -//CHECK#2 -if (__re.multiline !== __pattern.multiline) { - throw new Test262Error('#2: __pattern = /\\t/m; _re = new RegExp(__pattern, x); var x; __re.multiline === __pattern.multiline. Actual: ' + (__re.multiline)); -} +assert.sameValue( + __re.multiline, + __pattern.multiline, + 'The value of __re.multiline is expected to equal the value of __pattern.multiline' +); -//CHECK#3 -if (__re.global !== __pattern.global) { - throw new Test262Error('#3: __pattern = /\\t/m; _re = new RegExp(__pattern, x); var x; __re.global === __pattern.global. Actual: ' + (__re.global)); -} +assert.sameValue( + __re.global, + __pattern.global, + 'The value of __re.global is expected to equal the value of __pattern.global' +); -//CHECK#4 -if (__re.ignoreCase !== __pattern.ignoreCase) { - throw new Test262Error('#4: __pattern = /\\t/m; _re = new RegExp(__pattern, x); var x; __re.ignoreCase === __pattern.ignoreCase. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue( + __re.ignoreCase, + __pattern.ignoreCase, + 'The value of __re.ignoreCase is expected to equal the value of __pattern.ignoreCase' +); var x; diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T3.js index 26b78400b7d6..10162ef2820b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T3.js @@ -12,24 +12,28 @@ description: Pattern is /[a-b]/g and RegExp is new RegExp(pattern,void 0) var __pattern = /[a-b]/g; var __re = new RegExp(__pattern, void 0); -//CHECK#1 -if (__re.source !== __pattern.source) { - throw new Test262Error('#1: __pattern = /[a-b]/g; __re = new RegExp(__pattern, void 0); __re.source === __pattern.source. Actual: '+ (__re.source)); -} +assert.sameValue( + __re.source, + __pattern.source, + 'The value of __re.source is expected to equal the value of __pattern.source' +); -//CHECK#2 -if (__re.multiline !== __pattern.multiline) { - throw new Test262Error('#2: __pattern = /[a-b]/g; __re = new RegExp(__pattern, void 0); __re.multiline === __pattern.multiline. Actual: ' + (__re.multiline)); -} +assert.sameValue( + __re.multiline, + __pattern.multiline, + 'The value of __re.multiline is expected to equal the value of __pattern.multiline' +); -//CHECK#3 -if (__re.global !== __pattern.global) { - throw new Test262Error('#3: __pattern = /[a-b]/g; __re = new RegExp(__pattern, void 0); __re.global === __pattern.global. Actual: ' + (__re.global)); -} +assert.sameValue( + __re.global, + __pattern.global, + 'The value of __re.global is expected to equal the value of __pattern.global' +); -//CHECK#4 -if (__re.ignoreCase !== __pattern.ignoreCase) { - throw new Test262Error('#4: __pattern = /[a-b]/g; __re = new RegExp(__pattern, void 0); __re.ignoreCase === __pattern.ignoreCase. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue( + __re.ignoreCase, + __pattern.ignoreCase, + 'The value of __re.ignoreCase is expected to equal the value of __pattern.ignoreCase' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T4.js index 81b15e97289a..a66ead1e944b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T4.js @@ -12,24 +12,28 @@ description: Pattern is new RegExp and RegExp is new RegExp(pattern,undefined) var __pattern = new RegExp; var __re = new RegExp(__pattern, undefined); -//CHECK#1 -if (__re.source !== __pattern.source) { - throw new Test262Error('#1: __pattern = new RegExp; __re = new RegExp(__pattern, undefined); __re.source === __pattern.source. Actual: '+ (__re.source)); -} +assert.sameValue( + __re.source, + __pattern.source, + 'The value of __re.source is expected to equal the value of __pattern.source' +); -//CHECK#2 -if (__re.multiline !== __pattern.multiline) { - throw new Test262Error('#2: __pattern = new RegExp; __re = new RegExp(__pattern, undefined); __re.multiline === __pattern.multiline. Actual: ' + (__re.multiline)); -} +assert.sameValue( + __re.multiline, + __pattern.multiline, + 'The value of __re.multiline is expected to equal the value of __pattern.multiline' +); -//CHECK#3 -if (__re.global !== __pattern.global) { - throw new Test262Error('#3: __pattern = new RegExp; __re = new RegExp(__pattern, undefined); __re.global === __pattern.global. Actual: ' + (__re.global)); -} +assert.sameValue( + __re.global, + __pattern.global, + 'The value of __re.global is expected to equal the value of __pattern.global' +); -//CHECK#4 -if (__re.ignoreCase !== __pattern.ignoreCase) { - throw new Test262Error('#4: __pattern = new RegExp; __re = new RegExp(__pattern, undefined); __re.ignoreCase === __pattern.ignoreCase. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue( + __re.ignoreCase, + __pattern.ignoreCase, + 'The value of __re.ignoreCase is expected to equal the value of __pattern.ignoreCase' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T5.js index 86beedb3412e..226928eed86f 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A1_T5.js @@ -14,24 +14,28 @@ description: > var __pattern = RegExp("1?","mig"); var __re = new RegExp(__pattern, (function(){})()); -//CHECK#1 -if (__re.source !== __pattern.source) { - throw new Test262Error('#1: __pattern = RegExp("1?","mig"); __re = new RegExp(__pattern, (function(){})()); __re.source === __pattern.source. Actual: '+ (__re.source)); -} +assert.sameValue( + __re.source, + __pattern.source, + 'The value of __re.source is expected to equal the value of __pattern.source' +); -//CHECK#2 -if (__re.multiline !== __pattern.multiline) { - throw new Test262Error('#2: __pattern = RegExp("1?","mig"); __re = new RegExp(__pattern, (function(){})()); __re.multiline === __pattern.multiline. Actual: ' + (__re.multiline)); -} +assert.sameValue( + __re.multiline, + __pattern.multiline, + 'The value of __re.multiline is expected to equal the value of __pattern.multiline' +); -//CHECK#3 -if (__re.global !== __pattern.global) { - throw new Test262Error('#3: __pattern = RegExp("1?","mig"); __re = new RegExp(__pattern, (function(){})()); __re.global === __pattern.global. Actual: ' + (__re.global)); -} +assert.sameValue( + __re.global, + __pattern.global, + 'The value of __re.global is expected to equal the value of __pattern.global' +); -//CHECK#4 -if (__re.ignoreCase !== __pattern.ignoreCase) { - throw new Test262Error('#4: __pattern = RegExp("1?","mig"); __re = new RegExp(__pattern, (function(){})()); __re.ignoreCase === __pattern.ignoreCase. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue( + __re.ignoreCase, + __pattern.ignoreCase, + 'The value of __re.ignoreCase is expected to equal the value of __pattern.ignoreCase' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A2_T1.js index 54553b9595f2..87ebc9ab9a6b 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A2_T1.js @@ -11,7 +11,6 @@ description: > pattern is "/\u0042/i", does not fail ---*/ -//CHECK#1 var regExpObj = new RegExp(/\u0042/i, "i"); assert(regExpObj.ignoreCase); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A2_T2.js index 9fcb3d63be7a..16b8117f17a2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A2_T2.js @@ -12,13 +12,16 @@ description: > pattern is "/1?1/mig", fails ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: new RegExp(/1?1/mig, {}) throw SyntaxError. Actual: ' + (new RegExp(/1?1/mig, {}))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp(/1?1/mig, {}) throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T1.js index e2940f589d54..a183be27f86e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T1.js @@ -9,19 +9,8 @@ description: RegExp is new RegExp var __re = new RegExp; -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp; __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp; __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp; __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T2.js index 5efdcdc3d2ee..725d2df8f44e 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T2.js @@ -9,19 +9,8 @@ description: RegExp is new RegExp(void 0) var __re = new RegExp(void 0); -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(void 0); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp(void 0); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp(void 0); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T3.js index cdbc93ee5449..0e6d50a0542c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T3.js @@ -9,20 +9,9 @@ description: RegExp is new RegExp(x), where x is undefined variable var __re = new RegExp(x); -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(x); var x; __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp(x); var x; __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp(x); var x; __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); var x; diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T4.js index e6b8f12c1a2f..9e90bd2c8cbf 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T4.js @@ -9,19 +9,8 @@ description: RegExp is new RegExp(undefined) var __re = new RegExp(undefined); -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(undefined); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp(undefined); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp(undefined); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T5.js index fb7ac922690f..158ee29c55c5 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A3_T5.js @@ -9,19 +9,8 @@ description: RegExp is new RegExp((function(){})()) var __re = new RegExp((function(){})()); -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp((function(){})()); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp((function(){})()); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp((function(){})()); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T1.js index eebbdaa612c3..5a26e2eceee6 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T1.js @@ -9,24 +9,9 @@ description: RegExp is new RegExp(undefined) var __re = new RegExp(null, void 0); -//CHECK#1 -if (__re.source !== "null") { - throw new Test262Error('#1: __re = new RegExp(null, void 0); __re.source === "null". Actual: '+ (__re.source)); -} - -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(null, void 0); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp(null, void 0); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp(null, void 0); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.source, "null", 'The value of __re.source is expected to be "null"'); +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T2.js index cbbc3587e92d..260be26a6dfa 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T2.js @@ -9,19 +9,8 @@ description: RegExp is new RegExp(undefined,undefined) var __re = new RegExp(undefined, undefined); -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(undefined, undefined); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp(undefined, undefined); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp(undefined, undefined); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T3.js index 5fe5e2ac5d7c..18a1f4b2d539 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T3.js @@ -9,19 +9,8 @@ description: Use undefined properties of object as flags of RegExp var __re = new RegExp({}.p, {}.q); -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp({}.p, {}.q); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp({}.p, {}.q); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp({}.p, {}.q); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T4.js index 533b8e122ec7..49e69243ebbb 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T4.js @@ -9,24 +9,9 @@ description: RegExp is new RegExp(null,void 0) var __re = new RegExp(null, void 0); -//CHECK#1 -if (__re.source !== "null") { - throw new Test262Error('#1: __re = new RegExp(null, void 0); __re.source === "null". Actual: '+ (__re.source)); -} - -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(null, void 0); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp(null, void 0); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp(null, void 0); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.source, "null", 'The value of __re.source is expected to be "null"'); +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T5.js index 5a266bb36cef..b80072b70f0c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A4_T5.js @@ -9,19 +9,8 @@ description: RegExp is new RegExp("",(function(){})()) var __re = new RegExp("", (function(){})()); -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp("", (function(){})()); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp("", (function(){})()); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.ignoreCase !== false) { - throw new Test262Error('#4: __re = new RegExp("", (function(){})()); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T1.js index fdc09f48e3c6..9cf576d2e088 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T1.js @@ -9,13 +9,16 @@ es5id: 15.10.4.1_A5_T1 description: Checking if using "ii" as F leads to throwing the correct exception ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp(undefined,"ii") throw SyntaxError. Actual: ' + (new RegExp(undefined,"ii"))); + throw new Test262Error('#1.1: new RegExp(undefined,"ii") throw SyntaxError. Actual: ' + (new RegExp(undefined,"ii"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp(undefined,"ii") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T3.js index b6f9a495c34d..cd5f9408da4d 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T3.js @@ -9,13 +9,16 @@ es5id: 15.10.4.1_A5_T3 description: Checking by using eval, try to use eval("\"migr\"") as F ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("",eval("\\"migr\\"")) throw SyntaxError. Actual: ' + (new RegExp("",eval("\"migr\"")))); + throw new Test262Error('#1.1: new RegExp("",eval("\\"migr\\"")) throw SyntaxError. Actual: ' + (new RegExp("",eval("\"migr\"")))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("",eval("\\"migr\\"")) throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T4.js index de7d49eb607e..79a64437da37 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T4.js @@ -9,13 +9,16 @@ es5id: 15.10.4.1_A5_T4 description: Checking if using "z" as F leads to throwing the correct exception ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("a|b","z") throw SyntaxError. Actual: ' + (new RegExp("a|b","z"))); + throw new Test262Error('#1.1: new RegExp("a|b","z") throw SyntaxError. Actual: ' + (new RegExp("a|b","z"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("a|b","z") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T6.js index d4a7785c05c0..9fbf1e496f52 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T6.js @@ -11,13 +11,16 @@ description: > exception ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp(".",null) throw SyntaxError. Actual: ' + (new RegExp(".",null))); + throw new Test262Error('#1.1: new RegExp(".",null) throw SyntaxError. Actual: ' + (new RegExp(".",null))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp(".",null) throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T7.js index 5420a88b797a..af6bcd43c406 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T7.js @@ -9,13 +9,16 @@ es5id: 15.10.4.1_A5_T7 description: Checking if using 1.0 as F leads to throwing the correct exception ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("^",1.0) throw SyntaxError. Actual: ' + (new RegExp("^",1.0))); + throw new Test262Error('#1.1: new RegExp("^",1.0) throw SyntaxError. Actual: ' + (new RegExp("^",1.0))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("^",1.0) throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T8.js index bc5e97274e10..9457a6f641ea 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T8.js @@ -11,13 +11,16 @@ description: > exception ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("|",true) throw SyntaxError. Actual: ' + (new RegExp("|",true))); + throw new Test262Error('#1.1: new RegExp("|",true) throw SyntaxError. Actual: ' + (new RegExp("|",true))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("|",true) throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T9.js index 0a45dea18918..e752f8ffbf15 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A5_T9.js @@ -11,13 +11,16 @@ description: > the correct exception ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("$sup",{toString:function(){}}) throw SyntaxError. Actual: ' + (new RegExp("$sup",{toString:function(){}}))); + throw new Test262Error('#1.1: new RegExp("$sup",{toString:function(){}}) throw SyntaxError. Actual: ' + (new RegExp("$sup",{toString:function(){}}))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("$sup",{toString:function(){}}) throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A6_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A6_T1.js index 729fea722fa1..f69a1a04fd0a 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A6_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A6_T1.js @@ -10,9 +10,6 @@ description: Checking [[Class]] property of the newly constructed object var __re = new RegExp; __re.toString = Object.prototype.toString; -//CHECK#1 -if (__re.toString() !== "[object "+"RegExp"+"]") { - throw new Test262Error('#1: __re = new RegExp; __re.toString = Object.prototype.toString; __re.toString() === "[object "+"RegExp"+"]". Actual: ' + (__re.toString())); -} +assert.sameValue(__re.toString(), "[object "+"RegExp"+"]", '__re.toString() must return "[object "+"RegExp"+"]"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A7_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A7_T1.js index cd717f77920e..aaed68b46bf1 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A7_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A7_T1.js @@ -15,9 +15,6 @@ description: > var __re = new RegExp; RegExp.prototype.indicator = 1; -//CHECK#1 -if (__re.indicator !== 1) { - throw new Test262Error('#1: __re = new RegExp; RegExp.prototype.indicator = 1; __re.indicator === 1. Actual: ' + (__re.indicator)); -} +assert.sameValue(__re.indicator, 1, 'The value of __re.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A7_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A7_T2.js index f1799a46712e..d5e50cf780bc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A7_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A7_T2.js @@ -12,9 +12,10 @@ description: Checking [[Prototype]] property of the newly constructed object var __re = new RegExp(); -//CHECK#1 -if (RegExp.prototype.isPrototypeOf(__re) !== true) { - throw new Test262Error('#1: __re = new RegExp(); RegExp.prototype.isPrototypeOf(__re) === true. Actual: ' + (RegExp.prototype.isPrototypeOf(__re))); -} +assert.sameValue( + RegExp.prototype.isPrototypeOf(__re), + true, + 'RegExp.prototype.isPrototypeOf(new RegExp()) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T1.js index ef7c979eec0d..129f2f69737c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T1.js @@ -9,29 +9,10 @@ description: Pattern is "a|b" and flags is "i" var __re = new RegExp("a|b","i"); -//CHECK#1 -if (__re.ignoreCase !== true) { - throw new Test262Error('#1: __re = new RegExp("a|b","i"); __re.ignoreCase === true. Actual: ' + (__re.ignoreCase)); -} - -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp("a|b","i"); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp("a|b","i"); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.lastIndex !== 0) { - throw new Test262Error('#4: __re = new RegExp("a|b","i"); __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} - -//CHECK#5 -if (typeof __re.source === "undefined") { - throw new Test262Error('#5: __re = new RegExp("a|b","i"); typeof __re.source !== "undefined"'); -} +assert.sameValue(__re.ignoreCase, true, 'The value of __re.ignoreCase is expected to be true'); +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); +assert.notSameValue(typeof __re.source, "undefined", 'The value of typeof __re.source is not "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T10.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T10.js index 6f27311b236d..a7e4d64f09e2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T10.js @@ -9,29 +9,10 @@ description: Pattern is true and flags is "m" var __re = new RegExp(true,"m"); -//CHECK#1 -if (__re.ignoreCase !== false) { - throw new Test262Error('#1: __re = new RegExp(true,"m"); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} - -//CHECK#2 -if (__re.multiline !== true) { - throw new Test262Error('#2: __re = new RegExp(true,"m"); __re.multiline === true. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp(true,"m"); __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.lastIndex !== 0) { - throw new Test262Error('#4: __re = new RegExp(true,"m"); __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} - -//CHECK#5 -if (typeof __re.source === "undefined") { - throw new Test262Error('#5: __re = new RegExp(true,"m"); typeof __re.source !== "undefined"'); -} +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); +assert.sameValue(__re.multiline, true, 'The value of __re.multiline is expected to be true'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); +assert.notSameValue(typeof __re.source, "undefined", 'The value of typeof __re.source is not "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T11.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T11.js index a04c0169a2e1..fa3071355eed 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T11.js @@ -9,29 +9,10 @@ description: Checking by using eval, pattern is Math and flags is eval("\"g\"") var __re = new RegExp(Math,eval("\"g\"")); -//CHECK#1 -if (__re.ignoreCase !== false) { - throw new Test262Error('#1: __re = new RegExp(Math,eval("\\"g\\"")); __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} - -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(Math,eval("\\"g\\"")); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== true) { - throw new Test262Error('#3: __re = new RegExp(Math,eval("\\"g\\"")); __re.global === true. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.lastIndex !== 0) { - throw new Test262Error('#4: __re = new RegExp(Math,eval("\\"g\\"")); __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} - -//CHECK#5 -if (typeof __re.source === "undefined") { - throw new Test262Error('#5: __re = new RegExp(Math,eval("\\"g\\"")); typeof __re.source !== "undefined"'); -} +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, true, 'The value of __re.global is expected to be true'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); +assert.notSameValue(typeof __re.source, "undefined", 'The value of typeof __re.source is not "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T12.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T12.js index dbd4ad174d6c..a180108d15ac 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T12.js @@ -9,13 +9,12 @@ description: > valueOf:function(){throw "invalof";} } ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("\\u0042", {toString:void 0, valueOf:function(){throw "invalof";}}) throw "invalof". Actual: ' + (new RegExp("\u0042", {toString:void 0, valueOf:function(){throw "invalof";}}))); + throw new Test262Error('#1.1: new RegExp("\\u0042", {toString:void 0, valueOf:function(){throw "invalof";}}) throw "invalof". Actual: ' + (new RegExp("\u0042", {toString:void 0, valueOf:function(){throw "invalof";}}))); } catch (e) { - if (e !== "invalof" ) { - throw new Test262Error('#1.2: new RegExp("\\u0042", {toString:void 0, valueOf:function(){throw "invalof";}}) throw "invalof". Actual: ' + (e)); - } + assert.sameValue(e, "invalof", 'The value of e is expected to be "invalof"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T13.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T13.js index 062b456c345b..c61d99a95007 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T13.js @@ -9,13 +9,12 @@ description: > } ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("1", {toString:function(){throw "intostr";}}) throw "intostr". Actual: ' + (new RegExp("1", {toString:function(){throw "intostr";}}))); + throw new Test262Error('#1.1: new RegExp("1", {toString:function(){throw "intostr";}}) throw "intostr". Actual: ' + (new RegExp("1", {toString:function(){throw "intostr";}}))); } catch (e) { - if (e !== "intostr" ) { - throw new Test262Error('#1.2: new RegExp("1", {toString:function(){throw "intostr";}}) throw "intostr". Actual: ' + (e)); - } + assert.sameValue(e, "intostr", 'The value of e is expected to be "intostr"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T2.js index 2704a5e70027..dd91000ceb72 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T2.js @@ -9,29 +9,10 @@ description: Pattern is function(){return "a|b|[]";}() and flags is "ig" var __re = new RegExp(function(){return "a|b|[]";}(),"ig"); -//CHECK#1 -if (__re.ignoreCase !== true) { - throw new Test262Error('#1: __re = new RegExp(function(){return "a|b|[]"; __re.ignoreCase === true. Actual: ' + (__re.ignoreCase)); -} - -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(function(){return "a|b|[]"; __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== true) { - throw new Test262Error('#3: __re = new RegExp(function(){return "a|b|[]"; __re.global === true. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.lastIndex !== 0) { - throw new Test262Error('#4: __re = new RegExp(function(){return "a|b|[]"; __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} - -//CHECK#5 -if (typeof __re.source === "undefined") { - throw new Test262Error('#5: __re = new RegExp(function(){return "a|b|[]"; typeof __re.source !== "undefined"'); -} +assert.sameValue(__re.ignoreCase, true, 'The value of __re.ignoreCase is expected to be true'); +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, true, 'The value of __re.global is expected to be true'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); +assert.notSameValue(typeof __re.source, "undefined", 'The value of typeof __re.source is not "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T3.js index 67ce628bde7f..518410e0c6f8 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T3.js @@ -11,29 +11,10 @@ description: > var __re = new RegExp({toString:function(){return "[0-9]";}}, (function(){return "m";})()); -//CHECK#1 -if (__re.ignoreCase !== false) { - throw new Test262Error('#1: __re = new RegExp({toString:function(){return "[0-9]"; __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} - -//CHECK#2 -if (__re.multiline !== true) { - throw new Test262Error('#2: __re = new RegExp({toString:function(){return "[0-9]"; __re.multiline === true. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp({toString:function(){return "[0-9]"; __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.lastIndex !== 0) { - throw new Test262Error('#4: __re = new RegExp({toString:function(){return "[0-9]"; __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} - -//CHECK#5 -if (typeof __re.source === "undefined") { - throw new Test262Error('#5: __re = new RegExp({toString:function(){return "[0-9]"; typeof __re.source !== "undefined"'); -} +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); +assert.sameValue(__re.multiline, true, 'The value of __re.multiline is expected to be true'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); +assert.notSameValue(typeof __re.source, "undefined", 'The value of typeof __re.source is not "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T4.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T4.js index 91e343198e0f..1a69326139fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T4.js @@ -11,29 +11,10 @@ description: > var __re = new RegExp({toString:void 0,valueOf:function(){return "[z-z]";}}, {toString:void 0,valueOf:function(){return "mig";}}); -//CHECK#1 -if (__re.ignoreCase !== true) { - throw new Test262Error('#1: __re = new RegExp({toString:void 0,valueOf:function(){return "[z-z]"; __re.ignoreCase === true. Actual: ' + (__re.ignoreCase)); -} - -//CHECK#2 -if (__re.multiline !== true) { - throw new Test262Error('#2: __re = new RegExp({toString:void 0,valueOf:function(){return "[z-z]"; __re.multiline === true. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== true) { - throw new Test262Error('#3: __re = new RegExp({toString:void 0,valueOf:function(){return "[z-z]"; __re.global === true. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.lastIndex !== 0) { - throw new Test262Error('#4: __re = new RegExp({toString:void 0,valueOf:function(){return "[z-z]"; __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} - -//CHECK#5 -if (typeof __re.source === "undefined") { - throw new Test262Error('#5: __re = new RegExp({toString:void 0,valueOf:function(){return "[z-z]"; typeof __re.source !== "undefined"'); -} +assert.sameValue(__re.ignoreCase, true, 'The value of __re.ignoreCase is expected to be true'); +assert.sameValue(__re.multiline, true, 'The value of __re.multiline is expected to be true'); +assert.sameValue(__re.global, true, 'The value of __re.global is expected to be true'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); +assert.notSameValue(typeof __re.source, "undefined", 'The value of typeof __re.source is not "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T5.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T5.js index 0116eadacd1c..dee87d5e66f4 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T5.js @@ -11,29 +11,10 @@ description: > var __re = new RegExp(new Object("abc{1}"), {toString:function(){return "";}}); -//CHECK#1 -if (__re.ignoreCase !== false) { - throw new Test262Error('#1: __re = new RegExp(new Object("abc{1}"), {toString:function(){return ""; __re.ignoreCase === false. Actual: ' + (__re.ignoreCase)); -} - -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(new Object("abc{1}"), {toString:function(){return ""; __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== false) { - throw new Test262Error('#3: __re = new RegExp(new Object("abc{1}"), {toString:function(){return ""; __re.global === false. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.lastIndex !== 0) { - throw new Test262Error('#4: __re = new RegExp(new Object("abc{1}"), {toString:function(){return ""; __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} - -//CHECK#5 -if (typeof __re.source === "undefined") { - throw new Test262Error('#5: __re = new RegExp(new Object("abc{1}"), {toString:function(){return ""; typeof __re.source !== "undefined"'); -} +assert.sameValue(__re.ignoreCase, false, 'The value of __re.ignoreCase is expected to be false'); +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, false, 'The value of __re.global is expected to be false'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); +assert.notSameValue(typeof __re.source, "undefined", 'The value of typeof __re.source is not "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T6.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T6.js index 1636f74505ad..0a810c3d09a6 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T6.js @@ -9,13 +9,12 @@ description: > "i" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp({toString:function(){throw "intostr";}}, "i") throw "intostr". Actual: ' + (new RegExp({toString:function(){throw "intostr";}}, "i"))); + throw new Test262Error('#1.1: new RegExp({toString:function(){throw "intostr";}}, "i") throw "intostr". Actual: ' + (new RegExp({toString:function(){throw "intostr";}}, "i"))); } catch (e) { - if (e !== "intostr" ) { - throw new Test262Error('#1.2: new RegExp({toString:function(){throw "intostr";}}, "i") throw "intostr". Actual: ' + (e)); - } + assert.sameValue(e, "intostr", 'The value of e is expected to be "intostr"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T7.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T7.js index 8c517bed56b3..94265063dbb5 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T7.js @@ -9,13 +9,12 @@ description: > } and flags is "i" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp({toString:void 0, valueOf:function(){throw "invalof";}}) throw "invalof". Actual: ' + (new RegExp({toString:void 0, valueOf:function(){throw "invalof";}}))); + throw new Test262Error('#1.1: new RegExp({toString:void 0, valueOf:function(){throw "invalof";}}) throw "invalof". Actual: ' + (new RegExp({toString:void 0, valueOf:function(){throw "invalof";}}))); } catch (e) { - if (e !== "invalof" ) { - throw new Test262Error('#1.2: new RegExp({toString:void 0, valueOf:function(){throw "invalof";}}) throw "invalof". Actual: ' + (e)); - } + assert.sameValue(e, "invalof", 'The value of e is expected to be "invalof"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T8.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T8.js index 1b0d5dcaae84..f97e2c6f9c5c 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T8.js @@ -9,13 +9,12 @@ description: > "error" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp({toString:function(){throw "intostr";}}, "error") throw "intostr". Actual: ' + (new RegExp({toString:function(){throw "intostr";}}, "error"))); + throw new Test262Error('#1.1: new RegExp({toString:function(){throw "intostr";}}, "error") throw "intostr". Actual: ' + (new RegExp({toString:function(){throw "intostr";}}, "error"))); } catch (e) { - if (e !== "intostr" ) { - throw new Test262Error('#1.2: new RegExp({toString:function(){throw "intostr";}}, "error") throw "intostr". Actual: ' + (e)); - } + assert.sameValue(e, "intostr", 'The value of e is expected to be "intostr"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T9.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T9.js index 9c49b3e34fc6..c42f79e4c4b0 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A8_T9.js @@ -9,29 +9,10 @@ description: Pattern is 1 and flags is new Object("gi") var __re = new RegExp(1, new Object("gi")); -//CHECK#1 -if (__re.ignoreCase !== true) { - throw new Test262Error('#1: __re = new RegExp(1, new Object("gi")); __re.ignoreCase === true. Actual: ' + (__re.ignoreCase)); -} - -//CHECK#2 -if (__re.multiline !== false) { - throw new Test262Error('#2: __re = new RegExp(1, new Object("gi")); __re.multiline === false. Actual: ' + (__re.multiline)); -} - -//CHECK#3 -if (__re.global !== true) { - throw new Test262Error('#3: __re = new RegExp(1, new Object("gi")); __re.global === true. Actual: ' + (__re.global)); -} - -//CHECK#4 -if (__re.lastIndex !== 0) { - throw new Test262Error('#4: __re = new RegExp(1, new Object("gi")); __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} - -//CHECK#5 -if (typeof __re.source === "undefined") { - throw new Test262Error('#5: __re = new RegExp(1, new Object("gi")); typeof __re.source !== "undefined"'); -} +assert.sameValue(__re.ignoreCase, true, 'The value of __re.ignoreCase is expected to be true'); +assert.sameValue(__re.multiline, false, 'The value of __re.multiline is expected to be false'); +assert.sameValue(__re.global, true, 'The value of __re.global is expected to be true'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); +assert.notSameValue(typeof __re.source, "undefined", 'The value of typeof __re.source is not "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T1.js index b3865da8cba8..f8a44404daf3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T1.js @@ -9,13 +9,16 @@ es5id: 15.10.4.1_A9_T1 description: Pattern is "??" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("??") throw SyntaxError. Actual: ' + (new RegExp("??"))); + throw new Test262Error('#1.1: new RegExp("??") throw SyntaxError. Actual: ' + (new RegExp("??"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("??") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T2.js index 8f7fec3e833d..8b77e39b3519 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T2.js @@ -9,13 +9,16 @@ es5id: 15.10.4.1_A9_T2 description: Pattern is "[{-z]" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("[{-z]") throw SyntaxError. Actual: ' + (new RegExp("[{-z]"))); + throw new Test262Error('#1.1: new RegExp("[{-z]") throw SyntaxError. Actual: ' + (new RegExp("[{-z]"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("[{-z]") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T3.js b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T3.js index 629f155bdfa1..847ae1ab1bb5 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.4.1_A9_T3.js @@ -9,13 +9,16 @@ es5id: 15.10.4.1_A9_T3 description: Pattern is "[a--z]" ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: new RegExp("[a--z]") throw SyntaxError. Actual: ' + (new RegExp("[a--z]"))); + throw new Test262Error('#1.1: new RegExp("[a--z]") throw SyntaxError. Actual: ' + (new RegExp("[a--z]"))); } catch (e) { - if ((e instanceof SyntaxError) !== true) { - throw new Test262Error('#1.2: new RegExp("[a--z]") throw SyntaxError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof SyntaxError, + true, + 'The result of evaluating (e instanceof SyntaxError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.5_A1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.5_A1.js index 8e039974be0e..9288221078f3 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.5_A1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.5_A1.js @@ -6,10 +6,6 @@ info: RegExp constructor has length property whose value is 2 es5id: 15.10.5_A1 description: Checking RegExp.length property ---*/ - -//CHECK#1 -if (RegExp.length !== 2) { - throw new Test262Error('#1: RegExp.length === 2. Actual: ' + (RegExp.length)); -} +assert.sameValue(RegExp.length, 2, 'The value of RegExp.length is expected to be 2'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.5_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.5_A2_T1.js index 61fbac1e3564..c081cf7175a2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.5_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.5_A2_T1.js @@ -8,10 +8,10 @@ info: | es5id: 15.10.5_A2_T1 description: Checking Function.prototype.isPrototypeOf(RegExp) ---*/ - -//CHECK#1 -if (Function.prototype.isPrototypeOf(RegExp) !== true) { - throw new Test262Error('#1: Function.prototype.isPrototypeOf(RegExp) === true'); -} +assert.sameValue( + Function.prototype.isPrototypeOf(RegExp), + true, + 'Function.prototype.isPrototypeOf(RegExp) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.5_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.5_A2_T2.js index 9188c2da369a..d63649431a75 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.5_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.5_A2_T2.js @@ -13,9 +13,6 @@ description: > Function.prototype.indicator = 1; - //CHECK#1 -if (RegExp.indicator !== 1) { - throw new Test262Error('#1: Function.prototype.indicator = 1; RegExp.indicator === 1. Actual: ' + (RegExp.indicator)); -} +assert.sameValue(RegExp.indicator, 1, 'The value of RegExp.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A1_T1.js index 4d1f37dbf060..eb138e590ed7 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A1_T1.js @@ -7,13 +7,16 @@ es5id: 15.10.7_A1_T1 description: Checking if call of RegExp instance fails ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: /[^a]*/() throw TypeError. Actual: ' + (/[^a]*/())); + throw new Test262Error('#1.1: /[^a]*/() throw TypeError. Actual: ' + (/[^a]*/())); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: /[^a]*/() throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A1_T2.js index 2972ae1e14fc..5ae0061f9a83 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A1_T2.js @@ -7,13 +7,16 @@ es5id: 15.10.7_A1_T2 description: Checking if call of RegExp("a|b","g")() fails ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: RegExp("a|b","g")() throw TypeError. Actual: ' + (RegExp("a|b","g")())); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: RegExp("a|b","g")() throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A2_T1.js index 70d14570c884..b0df3705a2a2 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A2_T1.js @@ -7,13 +7,16 @@ es5id: 15.10.7_A2_T1 description: Checking if creating new RegExp instance fails ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: new /z/() throw TypeError. Actual: ' + (new /z/())); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new /z/() throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A2_T2.js index 1e38706f7ba6..e966a1421dbd 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A2_T2.js @@ -7,13 +7,16 @@ es5id: 15.10.7_A2_T2 description: Checking if creating "new RegExp" instance fails ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: new new RegExp throw TypeError. Actual: ' + (new new RegExp)); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new new RegExp throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A3_T1.js b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A3_T1.js index a1cf30a66d34..68d7c293f093 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A3_T1.js @@ -11,19 +11,13 @@ description: > var __re = /[^a]*/; -//CHECK#1 -if (typeof __re !== "object") { - throw new Test262Error('#1: __re = /[^a]*/; typeof __re === "object". Actual: ' + (typeof __re)); -} +assert.sameValue(typeof __re, "object", 'The value of `typeof __re` is expected to be "object"'); +assert.sameValue(__re.constructor, RegExp, 'The value of __re.constructor is expected to equal the value of RegExp'); -//CHECK#1 -if (__re.constructor !== RegExp) { - throw new Test262Error('#2: __re = /[^a]*/; __re.constructor === RegExp. Actual: ' + (__re.constructor)); -} - -//CHECK#3 -if ((__re instanceof RegExp) !== true) { - throw new Test262Error('#3: __re = /[^a]*/; (__re instanceof RegExp) === true'); -} +assert.sameValue( + __re instanceof RegExp, + true, + 'The result of evaluating (__re instanceof RegExp) is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A3_T2.js b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A3_T2.js index 2019812badeb..ad62441e4f74 100644 --- a/js/src/tests/test262/built-ins/RegExp/S15.10.7_A3_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/S15.10.7_A3_T2.js @@ -11,19 +11,13 @@ description: > var __re = new RegExp; -//CHECK#1 -if (typeof __re !== "object") { - throw new Test262Error('#1: __re = new RegExp; typeof __re === "object". Actual: ' + (typeof __re)); -} +assert.sameValue(typeof __re, "object", 'The value of `typeof __re` is expected to be "object"'); +assert.sameValue(__re.constructor, RegExp, 'The value of __re.constructor is expected to equal the value of RegExp'); -//CHECK#1 -if (__re.constructor !== RegExp) { - throw new Test262Error('#2: __re = new RegExp; __re.constructor === RegExp. Actual: ' + (__re.constructor)); -} - -//CHECK#3 -if ((__re instanceof RegExp) !== true) { - throw new Test262Error('#3: __re = new RegExp; (__re instanceof RegExp) === true'); -} +assert.sameValue( + __re instanceof RegExp, + true, + 'The result of evaluating (__re instanceof RegExp) is expected to be true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-non-unicode-match.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-non-unicode-match.js index fba28558290b..8e167d35b91f 100644 --- a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-non-unicode-match.js +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-non-unicode-match.js @@ -5,7 +5,7 @@ description: Basic matching cases with non-unicode matches. includes: [compareArray.js, propertyHelper.js, deepEqual.js] esid: sec-regexpbuiltinexec -features: [regexp-match-indices] +features: [regexp-named-groups, regexp-match-indices] info: | Runtime Semantics: RegExpBuiltinExec ( R, S ) ... diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-match.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-match.js index dc01e56d62fb..7b68980397d8 100644 --- a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-match.js +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-match.js @@ -5,7 +5,7 @@ description: Basic matching cases with non-unicode matches. includes: [compareArray.js, propertyHelper.js, deepEqual.js] esid: sec-regexpbuiltinexec -features: [regexp-match-indices] +features: [regexp-named-groups, regexp-match-indices] info: | Runtime Semantics: RegExpBuiltinExec ( R, S ) ... diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-property-names.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-property-names.js index ce1aa4bb0cb8..8eba7355d896 100644 --- a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-property-names.js +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-property-names.js @@ -5,7 +5,7 @@ description: Basic matching cases with non-unicode matches. includes: [compareArray.js] esid: sec-makeindicesarray -features: [regexp-match-indices] +features: [regexp-named-groups, regexp-match-indices] ---*/ assert.compareArray([1, 2], /(?<π>a)/du.exec("bab").indices.groups.π); diff --git a/js/src/tests/test262/built-ins/RegExp/named-groups/groups-properties.js b/js/src/tests/test262/built-ins/RegExp/named-groups/groups-properties.js index 2d0b18b66178..ce971cf0b59d 100644 --- a/js/src/tests/test262/built-ins/RegExp/named-groups/groups-properties.js +++ b/js/src/tests/test262/built-ins/RegExp/named-groups/groups-properties.js @@ -15,9 +15,8 @@ info: | ---*/ // Properties created on result.groups in textual order. -assert(compareArray(["fst", "snd"], - Object.getOwnPropertyNames( - /(?.)|(?.)/u.exec("abcd").groups))); +assert.compareArray(["fst", "snd"], Object.getOwnPropertyNames( + /(?.)|(?.)/u.exec("abcd").groups)); // Properties are created with Define, not Set let counter = 0; diff --git a/js/src/tests/test262/built-ins/RegExp/named-groups/lookbehind.js b/js/src/tests/test262/built-ins/RegExp/named-groups/lookbehind.js index 48d9c7f43732..470ff342cd7b 100644 --- a/js/src/tests/test262/built-ins/RegExp/named-groups/lookbehind.js +++ b/js/src/tests/test262/built-ins/RegExp/named-groups/lookbehind.js @@ -9,40 +9,39 @@ includes: [compareArray.js] ---*/ // Unicode mode -assert(compareArray(["f", "c"], "abcdef".match(/(?<=(?\w){3})f/u))); +assert.compareArray(["f", "c"], "abcdef".match(/(?<=(?\w){3})f/u)); assert.sameValue("c", "abcdef".match(/(?<=(?\w){3})f/u).groups.a); assert.sameValue("b", "abcdef".match(/(?<=(?\w){4})f/u).groups.a); assert.sameValue("a", "abcdef".match(/(?<=(?\w)+)f/u).groups.a); assert.sameValue(null, "abcdef".match(/(?<=(?\w){6})f/u)); -assert(compareArray(["f", ""], "abcdef".match(/((?<=\w{3}))f/u))); -assert(compareArray(["f", ""], "abcdef".match(/(?(?<=\w{3}))f/u))); +assert.compareArray(["f", ""], "abcdef".match(/((?<=\w{3}))f/u)); +assert.compareArray(["f", ""], "abcdef".match(/(?(?<=\w{3}))f/u)); -assert(compareArray(["f", undefined], "abcdef".match(/(?\d){3})f/u))); +assert.compareArray(["f", undefined], "abcdef".match(/(?\d){3})f/u)); assert.sameValue(null, "abcdef".match(/(?\D){3})f/u)); -assert(compareArray(["f", undefined], "abcdef".match(/(?\D){3})f|f/u))); -assert(compareArray(["f", undefined], "abcdef".match(/(?(?\D){3})f|f/u)); +assert.compareArray(["f", undefined], "abcdef".match(/(?(?\w){3})f/))); +assert.compareArray(["f", "c"], "abcdef".match(/(?<=(?\w){3})f/)); assert.sameValue("c", "abcdef".match(/(?<=(?\w){3})f/).groups.a); assert.sameValue("b", "abcdef".match(/(?<=(?\w){4})f/).groups.a); assert.sameValue("a", "abcdef".match(/(?<=(?\w)+)f/).groups.a); assert.sameValue(null, "abcdef".match(/(?<=(?\w){6})f/)); -assert(compareArray(["f", ""], "abcdef".match(/((?<=\w{3}))f/))); -assert(compareArray(["f", ""], "abcdef".match(/(?(?<=\w{3}))f/))); +assert.compareArray(["f", ""], "abcdef".match(/((?<=\w{3}))f/)); +assert.compareArray(["f", ""], "abcdef".match(/(?(?<=\w{3}))f/)); -assert(compareArray(["f", undefined], "abcdef".match(/(?\d){3})f/))); +assert.compareArray(["f", undefined], "abcdef".match(/(?\d){3})f/)); assert.sameValue(null, "abcdef".match(/(?\D){3})f/)); -assert(compareArray(["f", undefined], "abcdef".match(/(?\D){3})f|f/))); -assert(compareArray(["f", undefined], "abcdef".match(/(?(?\D){3})f|f/)); +assert.compareArray(["f", undefined], "abcdef".match(/(?(?.)|(?.))/u.exec("abcd").groups))); +assert.compareArray(["fst", "snd"], Object.getOwnPropertyNames( + /(?<=(?.)|(?.))/u.exec("abcd").groups)); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/named-groups/non-unicode-match.js b/js/src/tests/test262/built-ins/RegExp/named-groups/non-unicode-match.js index 3c1e9d3e730c..bc68c12bf892 100644 --- a/js/src/tests/test262/built-ins/RegExp/named-groups/non-unicode-match.js +++ b/js/src/tests/test262/built-ins/RegExp/named-groups/non-unicode-match.js @@ -8,38 +8,37 @@ features: [regexp-named-groups] includes: [compareArray.js] ---*/ -assert(compareArray(["a", "a"], "bab".match(/(?a)/))); -assert(compareArray(["a", "a"], "bab".match(/(?a)/))); -assert(compareArray(["a", "a"], "bab".match(/(?<_>a)/))); -assert(compareArray(["a", "a"], "bab".match(/(?<$>a)/))); -assert(compareArray(["bab", "a"], "bab".match(/.(?<$>a)./))); -assert(compareArray(["bab", "a", "b"], "bab".match(/.(?a)(.)/))); -assert(compareArray(["bab", "a", "b"], "bab".match(/.(?a)(?.)/))); -assert(compareArray(["bab", "ab"], "bab".match(/.(?\w\w)/))); -assert(compareArray(["bab", "bab"], "bab".match(/(?\w\w\w)/))); -assert(compareArray(["bab", "ba", "b"], "bab".match(/(?\w\w)(?\w)/))); +assert.compareArray(["a", "a"], "bab".match(/(?a)/)); +assert.compareArray(["a", "a"], "bab".match(/(?a)/)); +assert.compareArray(["a", "a"], "bab".match(/(?<_>a)/)); +assert.compareArray(["a", "a"], "bab".match(/(?<$>a)/)); +assert.compareArray(["bab", "a"], "bab".match(/.(?<$>a)./)); +assert.compareArray(["bab", "a", "b"], "bab".match(/.(?a)(.)/)); +assert.compareArray(["bab", "a", "b"], "bab".match(/.(?a)(?.)/)); +assert.compareArray(["bab", "ab"], "bab".match(/.(?\w\w)/)); +assert.compareArray(["bab", "bab"], "bab".match(/(?\w\w\w)/)); +assert.compareArray(["bab", "ba", "b"], "bab".match(/(?\w\w)(?\w)/)); let {a, b, c} = /(?.)(?.)(?.)\k\k\k/.exec("abccba").groups; assert.sameValue(a, "a"); assert.sameValue(b, "b"); assert.sameValue(c, "c"); -assert(compareArray("bab".match(/(a)/), "bab".match(/(?a)/))); -assert(compareArray("bab".match(/(a)/), "bab".match(/(?a)/))); -assert(compareArray("bab".match(/(a)/), "bab".match(/(?<_>a)/))); -assert(compareArray("bab".match(/(a)/), "bab".match(/(?<$>a)/))); -assert(compareArray("bab".match(/.(a)./), "bab".match(/.(?<$>a)./))); -assert(compareArray("bab".match(/.(a)(.)/), "bab".match(/.(?a)(.)/))); -assert(compareArray("bab".match(/.(a)(.)/), "bab".match(/.(?a)(?.)/))); -assert(compareArray("bab".match(/.(\w\w)/), "bab".match(/.(?\w\w)/))); -assert(compareArray("bab".match(/(\w\w\w)/), "bab".match(/(?\w\w\w)/))); -assert(compareArray("bab".match(/(\w\w)(\w)/), "bab".match(/(?\w\w)(?\w)/))); +assert.compareArray("bab".match(/(a)/), "bab".match(/(?a)/)); +assert.compareArray("bab".match(/(a)/), "bab".match(/(?a)/)); +assert.compareArray("bab".match(/(a)/), "bab".match(/(?<_>a)/)); +assert.compareArray("bab".match(/(a)/), "bab".match(/(?<$>a)/)); +assert.compareArray("bab".match(/.(a)./), "bab".match(/.(?<$>a)./)); +assert.compareArray("bab".match(/.(a)(.)/), "bab".match(/.(?a)(.)/)); +assert.compareArray("bab".match(/.(a)(.)/), "bab".match(/.(?a)(?.)/)); +assert.compareArray("bab".match(/.(\w\w)/), "bab".match(/.(?\w\w)/)); +assert.compareArray("bab".match(/(\w\w\w)/), "bab".match(/(?\w\w\w)/)); +assert.compareArray("bab".match(/(\w\w)(\w)/), "bab".match(/(?\w\w)(?\w)/)); -assert(compareArray(["bab", "b"], "bab".match(/(?b).\1/))); -assert(compareArray(["baba", "b", "a"], "baba".match(/(.)(?a)\1\2/))); -assert(compareArray(["baba", "b", "a", "b", "a"], - "baba".match(/(.)(?a)(?\1)(\2)/))); -assert(compareArray(["<)a/))); -assert(compareArray([">a", ">"], ">a".match(/(?>)a/))); +assert.compareArray(["bab", "b"], "bab".match(/(?b).\1/)); +assert.compareArray(["baba", "b", "a"], "baba".match(/(.)(?a)\1\2/)); +assert.compareArray(["baba", "b", "a", "b", "a"], "baba".match(/(.)(?a)(?\1)(\2)/)); +assert.compareArray(["<)a/)); +assert.compareArray([">a", ">"], ">a".match(/(?>)a/)); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/named-groups/non-unicode-references.js b/js/src/tests/test262/built-ins/RegExp/named-groups/non-unicode-references.js index 36cc95f480cf..3f8f8c4ab365 100644 --- a/js/src/tests/test262/built-ins/RegExp/named-groups/non-unicode-references.js +++ b/js/src/tests/test262/built-ins/RegExp/named-groups/non-unicode-references.js @@ -9,23 +9,23 @@ includes: [compareArray.js] ---*/ // Named references. -assert(compareArray(["bab", "b"], "bab".match(/(?.).\k/))); +assert.compareArray(["bab", "b"], "bab".match(/(?.).\k/)); assert.sameValue(null, "baa".match(/(?.).\k/)); // Reference inside group. -assert(compareArray(["bab", "b"], "bab".match(/(?\k\w)../))); +assert.compareArray(["bab", "b"], "bab".match(/(?\k\w)../)); assert.sameValue("b", "bab".match(/(?\k\w)../).groups.a); // Reference before group. -assert(compareArray(["bab", "b"], "bab".match(/\k(?b)\w\k/))); +assert.compareArray(["bab", "b"], "bab".match(/\k(?b)\w\k/)); assert.sameValue("b", "bab".match(/\k(?b)\w\k/).groups.a); -assert(compareArray(["bab", "b", "a"], "bab".match(/(?b)\k(?a)\k/))); +assert.compareArray(["bab", "b", "a"], "bab".match(/(?b)\k(?a)\k/)); let {a, b} = "bab".match(/(?b)\k(?a)\k/).groups; assert.sameValue(a, "a"); assert.sameValue(b, "b"); -assert(compareArray(["bab", "b"], "bab".match(/\k(?b)\w\k/))); -assert(compareArray(["bab", "b", "a"], "bab".match(/(?b)\k(?a)\k/))); +assert.compareArray(["bab", "b"], "bab".match(/\k(?b)\w\k/)); +assert.compareArray(["bab", "b", "a"], "bab".match(/(?b)\k(?a)\k/)); // Reference properties. assert.sameValue("a", /(?a)(?b)\k/.exec("aba").groups.a); diff --git a/js/src/tests/test262/built-ins/RegExp/named-groups/unicode-match.js b/js/src/tests/test262/built-ins/RegExp/named-groups/unicode-match.js index d86b6e61f92b..0e8717809180 100644 --- a/js/src/tests/test262/built-ins/RegExp/named-groups/unicode-match.js +++ b/js/src/tests/test262/built-ins/RegExp/named-groups/unicode-match.js @@ -8,43 +8,41 @@ features: [regexp-named-groups] includes: [compareArray.js] ---*/ -assert(compareArray(["a", "a"], "bab".match(/(?a)/u))); -assert(compareArray(["a", "a"], "bab".match(/(?a)/u))); -assert(compareArray(["a", "a"], "bab".match(/(?<_>a)/u))); -assert(compareArray(["a", "a"], "bab".match(/(?<$>a)/u))); -assert(compareArray(["bab", "a"], "bab".match(/.(?<$>a)./u))); -assert(compareArray(["bab", "a", "b"], "bab".match(/.(?a)(.)/u))); -assert(compareArray(["bab", "a", "b"], "bab".match(/.(?a)(?.)/u))); -assert(compareArray(["bab", "ab"], "bab".match(/.(?\w\w)/u))); -assert(compareArray(["bab", "bab"], "bab".match(/(?\w\w\w)/u))); -assert(compareArray(["bab", "ba", "b"], "bab".match(/(?\w\w)(?\w)/u))); +assert.compareArray(["a", "a"], "bab".match(/(?a)/u)); +assert.compareArray(["a", "a"], "bab".match(/(?a)/u)); +assert.compareArray(["a", "a"], "bab".match(/(?<_>a)/u)); +assert.compareArray(["a", "a"], "bab".match(/(?<$>a)/u)); +assert.compareArray(["bab", "a"], "bab".match(/.(?<$>a)./u)); +assert.compareArray(["bab", "a", "b"], "bab".match(/.(?a)(.)/u)); +assert.compareArray(["bab", "a", "b"], "bab".match(/.(?a)(?.)/u)); +assert.compareArray(["bab", "ab"], "bab".match(/.(?\w\w)/u)); +assert.compareArray(["bab", "bab"], "bab".match(/(?\w\w\w)/u)); +assert.compareArray(["bab", "ba", "b"], "bab".match(/(?\w\w)(?\w)/u)); let {a, b, c} = /(?.)(?.)(?.)\k\k\k/u.exec("abccba").groups; assert.sameValue(a, "a"); assert.sameValue(b, "b"); assert.sameValue(c, "c"); -assert(compareArray("bab".match(/(a)/u), "bab".match(/(?a)/u))); -assert(compareArray("bab".match(/(a)/u), "bab".match(/(?a)/u))); -assert(compareArray("bab".match(/(a)/u), "bab".match(/(?<_>a)/u))); -assert(compareArray("bab".match(/(a)/u), "bab".match(/(?<$>a)/u))); -assert(compareArray("bab".match(/.(a)./u), "bab".match(/.(?<$>a)./u))); -assert(compareArray("bab".match(/.(a)(.)/u), "bab".match(/.(?a)(.)/u))); -assert(compareArray("bab".match(/.(a)(.)/u), "bab".match(/.(?a)(?.)/u))); -assert(compareArray("bab".match(/.(\w\w)/u), "bab".match(/.(?\w\w)/u))); -assert(compareArray("bab".match(/(\w\w\w)/u), "bab".match(/(?\w\w\w)/u))); -assert(compareArray("bab".match(/(\w\w)(\w)/u), "bab".match(/(?\w\w)(?\w)/u))); +assert.compareArray("bab".match(/(a)/u), "bab".match(/(?a)/u)); +assert.compareArray("bab".match(/(a)/u), "bab".match(/(?a)/u)); +assert.compareArray("bab".match(/(a)/u), "bab".match(/(?<_>a)/u)); +assert.compareArray("bab".match(/(a)/u), "bab".match(/(?<$>a)/u)); +assert.compareArray("bab".match(/.(a)./u), "bab".match(/.(?<$>a)./u)); +assert.compareArray("bab".match(/.(a)(.)/u), "bab".match(/.(?a)(.)/u)); +assert.compareArray("bab".match(/.(a)(.)/u), "bab".match(/.(?a)(?.)/u)); +assert.compareArray("bab".match(/.(\w\w)/u), "bab".match(/.(?\w\w)/u)); +assert.compareArray("bab".match(/(\w\w\w)/u), "bab".match(/(?\w\w\w)/u)); +assert.compareArray("bab".match(/(\w\w)(\w)/u), "bab".match(/(?\w\w)(?\w)/u)); -assert(compareArray(["bab", "b"], "bab".match(/(?b).\1/u))); -assert(compareArray(["baba", "b", "a"], "baba".match(/(.)(?a)\1\2/u))); -assert(compareArray(["baba", "b", "a", "b", "a"], - "baba".match(/(.)(?a)(?\1)(\2)/u))); -assert(compareArray(["<)a/u))); -assert(compareArray([">a", ">"], ">a".match(/(?>)a/u))); +assert.compareArray(["bab", "b"], "bab".match(/(?b).\1/u)); +assert.compareArray(["baba", "b", "a"], "baba".match(/(.)(?a)\1\2/u)); +assert.compareArray(["baba", "b", "a", "b", "a"], "baba".match(/(.)(?a)(?\1)(\2)/u)); +assert.compareArray(["<)a/u)); +assert.compareArray([">a", ">"], ">a".match(/(?>)a/u)); // Nested groups. -assert(compareArray(["bab", "bab", "ab", "b"], "bab".match(/(?.(?.(?.)))/u))); -assert(compareArray({a: "bab", b: "ab", c: "b"}, - "bab".match(/(?.(?.(?.)))/u).groups)); +assert.compareArray(["bab", "bab", "ab", "b"], "bab".match(/(?.(?.(?.)))/u)); +assert.compareArray({a: "bab", b: "ab", c: "b"}, "bab".match(/(?.(?.(?.)))/u).groups); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/named-groups/unicode-references.js b/js/src/tests/test262/built-ins/RegExp/named-groups/unicode-references.js index c7f481b7acc5..30d70ad11277 100644 --- a/js/src/tests/test262/built-ins/RegExp/named-groups/unicode-references.js +++ b/js/src/tests/test262/built-ins/RegExp/named-groups/unicode-references.js @@ -22,23 +22,23 @@ includes: [compareArray.js] ---*/ // Named references. -assert(compareArray(["bab", "b"], "bab".match(/(?.).\k/u))); +assert.compareArray(["bab", "b"], "bab".match(/(?.).\k/u)); assert.sameValue(null, "baa".match(/(?.).\k/u)); // Reference inside group. -assert(compareArray(["bab", "b"], "bab".match(/(?\k\w)../u))); +assert.compareArray(["bab", "b"], "bab".match(/(?\k\w)../u)); assert.sameValue("b", "bab".match(/(?\k\w)../u).groups.a); // Reference before group. -assert(compareArray(["bab", "b"], "bab".match(/\k(?b)\w\k/u))); +assert.compareArray(["bab", "b"], "bab".match(/\k(?b)\w\k/u)); assert.sameValue("b", "bab".match(/\k(?b)\w\k/u).groups.a); -assert(compareArray(["bab", "b", "a"], "bab".match(/(?b)\k(?a)\k/u))); +assert.compareArray(["bab", "b", "a"], "bab".match(/(?b)\k(?a)\k/u)); let {a, b} = "bab".match(/(?b)\k(?a)\k/u).groups; assert.sameValue(a, "a"); assert.sameValue(b, "b"); -assert(compareArray(["bab", "b"], "bab".match(/\k(?b)\w\k/))); -assert(compareArray(["bab", "b", "a"], "bab".match(/(?b)\k(?a)\k/))); +assert.compareArray(["bab", "b"], "bab".match(/\k(?b)\w\k/)); +assert.compareArray(["bab", "b", "a"], "bab".match(/(?b)\k(?a)\k/)); // Reference properties. assert.sameValue("a", /(?a)(?b)\k/u.exec("aba").groups.a); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII.js index e217e15a4e8c..0aca3a8a9241 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `ASCII` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII_Hex_Digit.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII_Hex_Digit.js index 9c5b712e6120..a96216e8b262 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII_Hex_Digit.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII_Hex_Digit.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `ASCII_Hex_Digit` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Alphabetic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Alphabetic.js index fbc3ccfeeb7b..8a1ce623947b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Alphabetic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Alphabetic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Alphabetic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -40,7 +40,7 @@ const matchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000BD7, - 0x000CDE, + 0x000C5D, 0x000D4E, 0x000DBD, 0x000DD6, @@ -76,6 +76,7 @@ const matchSymbols = buildString({ 0x002D2D, 0x002D6F, 0x002E2F, + 0x00A7D3, 0x00A8C5, 0x00A8FB, 0x00A9CF, @@ -85,6 +86,7 @@ const matchSymbols = buildString({ 0x010808, 0x01083C, 0x010F27, + 0x0110C2, 0x011176, 0x0111DA, 0x0111DC, @@ -169,8 +171,9 @@ const matchSymbols = buildString({ [0x00081A, 0x00082C], [0x000840, 0x000858], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], + [0x000870, 0x000887], + [0x000889, 0x00088E], + [0x0008A0, 0x0008C9], [0x0008D4, 0x0008DF], [0x0008E3, 0x0008E9], [0x0008F0, 0x00093B], @@ -260,6 +263,7 @@ const matchSymbols = buildString({ [0x000CC6, 0x000CC8], [0x000CCA, 0x000CCC], [0x000CD5, 0x000CD6], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE3], [0x000CF1, 0x000CF2], [0x000D00, 0x000D0C], @@ -321,9 +325,8 @@ const matchSymbols = buildString({ [0x001681, 0x00169A], [0x0016A0, 0x0016EA], [0x0016EE, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001713], - [0x001720, 0x001733], + [0x001700, 0x001713], + [0x00171F, 0x001733], [0x001740, 0x001753], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -344,9 +347,10 @@ const matchSymbols = buildString({ [0x001A20, 0x001A5E], [0x001A61, 0x001A74], [0x001ABF, 0x001AC0], + [0x001ACC, 0x001ACE], [0x001B00, 0x001B33], [0x001B35, 0x001B43], - [0x001B45, 0x001B4B], + [0x001B45, 0x001B4C], [0x001B80, 0x001BA9], [0x001BAC, 0x001BAF], [0x001BBA, 0x001BE5], @@ -386,9 +390,7 @@ const matchSymbols = buildString({ [0x002145, 0x002149], [0x002160, 0x002188], [0x0024B6, 0x0024E9], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CE4], + [0x002C00, 0x002CE4], [0x002CEB, 0x002CEE], [0x002CF2, 0x002CF3], [0x002D00, 0x002D25], @@ -416,8 +418,7 @@ const matchSymbols = buildString({ [0x0031A0, 0x0031BF], [0x0031F0, 0x0031FF], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], - [0x00A000, 0x00A48C], + [0x004E00, 0x00A48C], [0x00A4D0, 0x00A4FD], [0x00A500, 0x00A60C], [0x00A610, 0x00A61F], @@ -427,9 +428,10 @@ const matchSymbols = buildString({ [0x00A67F, 0x00A6EF], [0x00A717, 0x00A71F], [0x00A722, 0x00A788], - [0x00A78B, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A805], + [0x00A78B, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A805], [0x00A807, 0x00A827], [0x00A840, 0x00A873], [0x00A880, 0x00A8C3], @@ -505,9 +507,20 @@ const matchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -542,9 +555,11 @@ const matchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F1C], [0x010F30, 0x010F45], + [0x010F70, 0x010F81], [0x010FB0, 0x010FC4], [0x010FE0, 0x010FF6], [0x011000, 0x011045], + [0x011071, 0x011075], [0x011082, 0x0110B8], [0x0110D0, 0x0110E8], [0x011100, 0x011132], @@ -584,6 +599,7 @@ const matchSymbols = buildString({ [0x011680, 0x0116B5], [0x011700, 0x01171A], [0x01171D, 0x01172A], + [0x011740, 0x011746], [0x011800, 0x011838], [0x0118A0, 0x0118DF], [0x0118FF, 0x011906], @@ -600,7 +616,7 @@ const matchSymbols = buildString({ [0x011A00, 0x011A32], [0x011A35, 0x011A3E], [0x011A50, 0x011A97], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C36], [0x011C38, 0x011C3E], @@ -622,10 +638,12 @@ const matchSymbols = buildString({ [0x012000, 0x012399], [0x012400, 0x01246E], [0x012480, 0x012543], + [0x012F90, 0x012FF0], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], + [0x016A70, 0x016ABE], [0x016AD0, 0x016AED], [0x016B00, 0x016B2F], [0x016B40, 0x016B43], @@ -640,7 +658,10 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -675,6 +696,7 @@ const matchSymbols = buildString({ [0x01D78A, 0x01D7A8], [0x01D7AA, 0x01D7C2], [0x01D7C4, 0x01D7CB], + [0x01DF00, 0x01DF1E], [0x01E000, 0x01E006], [0x01E008, 0x01E018], [0x01E01B, 0x01E021], @@ -682,7 +704,12 @@ const matchSymbols = buildString({ [0x01E026, 0x01E02A], [0x01E100, 0x01E12C], [0x01E137, 0x01E13D], + [0x01E290, 0x01E2AD], [0x01E2C0, 0x01E2EB], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E900, 0x01E943], [0x01EE00, 0x01EE03], @@ -705,8 +732,8 @@ const matchSymbols = buildString({ [0x01F130, 0x01F149], [0x01F150, 0x01F169], [0x01F170, 0x01F189], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -744,7 +771,7 @@ const nonMatchSymbols = buildString({ 0x0005C6, 0x000658, 0x0006D4, - 0x0008B5, + 0x000888, 0x00093C, 0x00094D, 0x000984, @@ -824,7 +851,6 @@ const nonMatchSymbols = buildString({ 0x0012D7, 0x001311, 0x001680, - 0x00170D, 0x00176D, 0x001771, 0x00191F, @@ -846,8 +872,6 @@ const nonMatchSymbols = buildString({ 0x002127, 0x002129, 0x00212E, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -860,6 +884,8 @@ const nonMatchSymbols = buildString({ 0x0030A0, 0x0030FB, 0x003130, + 0x00A7D2, + 0x00A7D4, 0x00A806, 0x00A8C4, 0x00A8FC, @@ -882,6 +908,15 @@ const nonMatchSymbols = buildString({ 0x01003B, 0x01003E, 0x0103D0, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x0108F3, @@ -925,6 +960,9 @@ const nonMatchSymbols = buildString({ 0x011D92, 0x011D97, 0x016FE2, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -951,6 +989,10 @@ const nonMatchSymbols = buildString({ 0x01E007, 0x01E022, 0x01E025, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -1015,8 +1057,9 @@ const nonMatchSymbols = buildString({ [0x000818, 0x000819], [0x00082D, 0x00083F], [0x000859, 0x00085F], - [0x00086B, 0x00089F], - [0x0008C8, 0x0008D3], + [0x00086B, 0x00086F], + [0x00088F, 0x00089F], + [0x0008CA, 0x0008D3], [0x0008E0, 0x0008E2], [0x0008EA, 0x0008EF], [0x000951, 0x000954], @@ -1067,11 +1110,12 @@ const nonMatchSymbols = buildString({ [0x000BD8, 0x000BFF], [0x000C3A, 0x000C3C], [0x000C4D, 0x000C54], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C64, 0x000C7F], [0x000CBA, 0x000CBC], [0x000CCD, 0x000CD4], - [0x000CD7, 0x000CDD], + [0x000CD7, 0x000CDC], [0x000CE4, 0x000CF0], [0x000CF3, 0x000CFF], [0x000D3B, 0x000D3C], @@ -1114,7 +1158,7 @@ const nonMatchSymbols = buildString({ [0x00169B, 0x00169F], [0x0016EB, 0x0016ED], [0x0016F9, 0x0016FF], - [0x001714, 0x00171F], + [0x001714, 0x00171E], [0x001734, 0x00173F], [0x001754, 0x00175F], [0x001774, 0x00177F], @@ -1135,8 +1179,9 @@ const nonMatchSymbols = buildString({ [0x001A5F, 0x001A60], [0x001A75, 0x001AA6], [0x001AA8, 0x001ABE], - [0x001AC1, 0x001AFF], - [0x001B4C, 0x001B7F], + [0x001AC1, 0x001ACB], + [0x001ACF, 0x001AFF], + [0x001B4D, 0x001B7F], [0x001BAA, 0x001BAB], [0x001BB0, 0x001BB9], [0x001BF2, 0x001BFF], @@ -1194,7 +1239,6 @@ const nonMatchSymbols = buildString({ [0x0031C0, 0x0031EF], [0x003200, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A4CF], [0x00A4FE, 0x00A4FF], [0x00A60D, 0x00A60F], @@ -1205,8 +1249,8 @@ const nonMatchSymbols = buildString({ [0x00A6F0, 0x00A716], [0x00A720, 0x00A721], [0x00A789, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A828, 0x00A83F], [0x00A874, 0x00A87F], [0x00A8C6, 0x00A8F1], @@ -1267,10 +1311,12 @@ const nonMatchSymbols = buildString({ [0x0104D4, 0x0104D7], [0x0104FC, 0x0104FF], [0x010528, 0x01052F], - [0x010564, 0x0105FF], + [0x010564, 0x01056F], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -1299,11 +1345,14 @@ const nonMatchSymbols = buildString({ [0x010EB2, 0x010EFF], [0x010F1D, 0x010F26], [0x010F28, 0x010F2F], - [0x010F46, 0x010FAF], + [0x010F46, 0x010F6F], + [0x010F82, 0x010FAF], [0x010FC5, 0x010FDF], [0x010FF7, 0x010FFF], - [0x011046, 0x011081], - [0x0110B9, 0x0110CF], + [0x011046, 0x011070], + [0x011076, 0x011081], + [0x0110B9, 0x0110C1], + [0x0110C3, 0x0110CF], [0x0110E9, 0x0110FF], [0x011133, 0x011143], [0x011148, 0x01114F], @@ -1338,7 +1387,8 @@ const nonMatchSymbols = buildString({ [0x0116B6, 0x0116B7], [0x0116B9, 0x0116FF], [0x01171B, 0x01171C], - [0x01172B, 0x0117FF], + [0x01172B, 0x01173F], + [0x011747, 0x0117FF], [0x011839, 0x01189F], [0x0118E0, 0x0118FE], [0x011907, 0x011908], @@ -1352,7 +1402,7 @@ const nonMatchSymbols = buildString({ [0x011A33, 0x011A34], [0x011A3F, 0x011A4F], [0x011A98, 0x011A9C], - [0x011A9E, 0x011ABF], + [0x011A9E, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C41, 0x011C71], [0x011C90, 0x011C91], @@ -1365,11 +1415,13 @@ const nonMatchSymbols = buildString({ [0x011FB1, 0x011FFF], [0x01239A, 0x0123FF], [0x01246F, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF1, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], - [0x016A5F, 0x016ACF], + [0x016A5F, 0x016A6F], + [0x016ABF, 0x016ACF], [0x016AEE, 0x016AFF], [0x016B30, 0x016B3F], [0x016B44, 0x016B62], @@ -1383,8 +1435,8 @@ const nonMatchSymbols = buildString({ [0x016FF2, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -1399,13 +1451,15 @@ const nonMatchSymbols = buildString({ [0x01D50B, 0x01D50C], [0x01D547, 0x01D549], [0x01D6A6, 0x01D6A7], - [0x01D7CC, 0x01DFFF], + [0x01D7CC, 0x01DEFF], + [0x01DF1F, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E0FF], [0x01E12D, 0x01E136], [0x01E13E, 0x01E14D], - [0x01E14F, 0x01E2BF], - [0x01E2EC, 0x01E7FF], + [0x01E14F, 0x01E28F], + [0x01E2AE, 0x01E2BF], + [0x01E2EC, 0x01E7DF], [0x01E8C5, 0x01E8FF], [0x01E944, 0x01E946], [0x01E948, 0x01E94A], @@ -1420,8 +1474,8 @@ const nonMatchSymbols = buildString({ [0x01F14A, 0x01F14F], [0x01F16A, 0x01F16F], [0x01F18A, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Any.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Any.js index 67df69083fa2..6cb25cbf5f2e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Any.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Any.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Any` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Assigned.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Assigned.js index 683e674a081a..becaec4d93ee 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Assigned.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Assigned.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Assigned` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -26,7 +26,7 @@ const matchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000BD7, - 0x000CDE, + 0x000C5D, 0x000DBD, 0x000DCA, 0x000DD6, @@ -43,10 +43,11 @@ const matchSymbols = buildString({ 0x001F5D, 0x002D27, 0x002D2D, + 0x00A7D3, 0x00FB3E, + 0x00FDCF, 0x00FEFF, 0x0101A0, - 0x01056F, 0x010808, 0x01083C, 0x01093F, @@ -77,6 +78,7 @@ const matchSymbols = buildString({ 0x01EE5F, 0x01EE64, 0x01EE7E, + 0x01F7F0, 0x0E0001 ], ranges: [ @@ -92,8 +94,7 @@ const matchSymbols = buildString({ [0x000591, 0x0005C7], [0x0005D0, 0x0005EA], [0x0005EF, 0x0005F4], - [0x000600, 0x00061C], - [0x00061E, 0x00070D], + [0x000600, 0x00070D], [0x00070F, 0x00074A], [0x00074D, 0x0007B1], [0x0007C0, 0x0007FA], @@ -101,9 +102,9 @@ const matchSymbols = buildString({ [0x000830, 0x00083E], [0x000840, 0x00085B], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], - [0x0008D3, 0x000983], + [0x000870, 0x00088E], + [0x000890, 0x000891], + [0x000898, 0x000983], [0x000985, 0x00098C], [0x00098F, 0x000990], [0x000993, 0x0009A8], @@ -172,7 +173,7 @@ const matchSymbols = buildString({ [0x000C0E, 0x000C10], [0x000C12, 0x000C28], [0x000C2A, 0x000C39], - [0x000C3D, 0x000C44], + [0x000C3C, 0x000C44], [0x000C46, 0x000C48], [0x000C4A, 0x000C4D], [0x000C55, 0x000C56], @@ -188,6 +189,7 @@ const matchSymbols = buildString({ [0x000CC6, 0x000CC8], [0x000CCA, 0x000CCD], [0x000CD5, 0x000CD6], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE3], [0x000CE6, 0x000CEF], [0x000CF1, 0x000CF2], @@ -244,9 +246,8 @@ const matchSymbols = buildString({ [0x0013F8, 0x0013FD], [0x001400, 0x00169C], [0x0016A0, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001714], - [0x001720, 0x001736], + [0x001700, 0x001715], + [0x00171F, 0x001736], [0x001740, 0x001753], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -254,8 +255,7 @@ const matchSymbols = buildString({ [0x001780, 0x0017DD], [0x0017E0, 0x0017E9], [0x0017F0, 0x0017F9], - [0x001800, 0x00180E], - [0x001810, 0x001819], + [0x001800, 0x001819], [0x001820, 0x001878], [0x001880, 0x0018AA], [0x0018B0, 0x0018F5], @@ -273,9 +273,9 @@ const matchSymbols = buildString({ [0x001A7F, 0x001A89], [0x001A90, 0x001A99], [0x001AA0, 0x001AAD], - [0x001AB0, 0x001AC0], - [0x001B00, 0x001B4B], - [0x001B50, 0x001B7C], + [0x001AB0, 0x001ACE], + [0x001B00, 0x001B4C], + [0x001B50, 0x001B7E], [0x001B80, 0x001BF3], [0x001BFC, 0x001C37], [0x001C3B, 0x001C49], @@ -283,8 +283,7 @@ const matchSymbols = buildString({ [0x001C90, 0x001CBA], [0x001CBD, 0x001CC7], [0x001CD0, 0x001CFA], - [0x001D00, 0x001DF9], - [0x001DFB, 0x001F15], + [0x001D00, 0x001F15], [0x001F18, 0x001F1D], [0x001F20, 0x001F45], [0x001F48, 0x001F4D], @@ -301,16 +300,14 @@ const matchSymbols = buildString({ [0x002066, 0x002071], [0x002074, 0x00208E], [0x002090, 0x00209C], - [0x0020A0, 0x0020BF], + [0x0020A0, 0x0020C0], [0x0020D0, 0x0020F0], [0x002100, 0x00218B], [0x002190, 0x002426], [0x002440, 0x00244A], [0x002460, 0x002B73], [0x002B76, 0x002B95], - [0x002B97, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CF3], + [0x002B97, 0x002CF3], [0x002CF9, 0x002D25], [0x002D30, 0x002D67], [0x002D6F, 0x002D70], @@ -323,7 +320,7 @@ const matchSymbols = buildString({ [0x002DC8, 0x002DCE], [0x002DD0, 0x002DD6], [0x002DD8, 0x002DDE], - [0x002DE0, 0x002E52], + [0x002DE0, 0x002E5D], [0x002E80, 0x002E99], [0x002E9B, 0x002EF3], [0x002F00, 0x002FD5], @@ -335,14 +332,14 @@ const matchSymbols = buildString({ [0x003131, 0x00318E], [0x003190, 0x0031E3], [0x0031F0, 0x00321E], - [0x003220, 0x009FFC], - [0x00A000, 0x00A48C], + [0x003220, 0x00A48C], [0x00A490, 0x00A4C6], [0x00A4D0, 0x00A62B], [0x00A640, 0x00A6F7], - [0x00A700, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A82C], + [0x00A700, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A82C], [0x00A830, 0x00A839], [0x00A840, 0x00A877], [0x00A880, 0x00A8C5], @@ -377,12 +374,10 @@ const matchSymbols = buildString({ [0x00FB38, 0x00FB3C], [0x00FB40, 0x00FB41], [0x00FB43, 0x00FB44], - [0x00FB46, 0x00FBC1], - [0x00FBD3, 0x00FD3F], - [0x00FD50, 0x00FD8F], + [0x00FB46, 0x00FBC2], + [0x00FBD3, 0x00FD8F], [0x00FD92, 0x00FDC7], - [0x00FDF0, 0x00FDFD], - [0x00FE00, 0x00FE19], + [0x00FDF0, 0x00FE19], [0x00FE20, 0x00FE52], [0x00FE54, 0x00FE66], [0x00FE68, 0x00FE6B], @@ -423,9 +418,20 @@ const matchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x01056F, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -466,11 +472,12 @@ const matchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F27], [0x010F30, 0x010F59], + [0x010F70, 0x010F89], [0x010FB0, 0x010FCB], [0x010FE0, 0x010FF6], [0x011000, 0x01104D], - [0x011052, 0x01106F], - [0x01107F, 0x0110C1], + [0x011052, 0x011075], + [0x01107F, 0x0110C2], [0x0110D0, 0x0110E8], [0x0110F0, 0x0110F9], [0x011100, 0x011134], @@ -508,11 +515,11 @@ const matchSymbols = buildString({ [0x011600, 0x011644], [0x011650, 0x011659], [0x011660, 0x01166C], - [0x011680, 0x0116B8], + [0x011680, 0x0116B9], [0x0116C0, 0x0116C9], [0x011700, 0x01171A], [0x01171D, 0x01172B], - [0x011730, 0x01173F], + [0x011730, 0x011746], [0x011800, 0x01183B], [0x0118A0, 0x0118F2], [0x0118FF, 0x011906], @@ -527,7 +534,7 @@ const matchSymbols = buildString({ [0x0119DA, 0x0119E4], [0x011A00, 0x011A47], [0x011A50, 0x011AA2], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C36], [0x011C38, 0x011C45], @@ -553,13 +560,15 @@ const matchSymbols = buildString({ [0x012400, 0x01246E], [0x012470, 0x012474], [0x012480, 0x012543], + [0x012F90, 0x012FF2], [0x013000, 0x01342E], [0x013430, 0x013438], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], [0x016A60, 0x016A69], - [0x016A6E, 0x016A6F], + [0x016A6E, 0x016ABE], + [0x016AC0, 0x016AC9], [0x016AD0, 0x016AED], [0x016AF0, 0x016AF5], [0x016B00, 0x016B45], @@ -576,7 +585,10 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -585,9 +597,12 @@ const matchSymbols = buildString({ [0x01BC80, 0x01BC88], [0x01BC90, 0x01BC99], [0x01BC9C, 0x01BCA3], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], + [0x01CF50, 0x01CFC3], [0x01D000, 0x01D0F5], [0x01D100, 0x01D126], - [0x01D129, 0x01D1E8], + [0x01D129, 0x01D1EA], [0x01D200, 0x01D245], [0x01D2E0, 0x01D2F3], [0x01D300, 0x01D356], @@ -612,6 +627,7 @@ const matchSymbols = buildString({ [0x01D7CE, 0x01DA8B], [0x01DA9B, 0x01DA9F], [0x01DAA1, 0x01DAAF], + [0x01DF00, 0x01DF1E], [0x01E000, 0x01E006], [0x01E008, 0x01E018], [0x01E01B, 0x01E021], @@ -621,7 +637,12 @@ const matchSymbols = buildString({ [0x01E130, 0x01E13D], [0x01E140, 0x01E149], [0x01E14E, 0x01E14F], + [0x01E290, 0x01E2AE], [0x01E2C0, 0x01E2F9], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E8C7, 0x01E8D6], [0x01E900, 0x01E94B], @@ -660,7 +681,7 @@ const matchSymbols = buildString({ [0x01F250, 0x01F251], [0x01F260, 0x01F265], [0x01F300, 0x01F6D7], - [0x01F6E0, 0x01F6EC], + [0x01F6DD, 0x01F6EC], [0x01F6F0, 0x01F6FC], [0x01F700, 0x01F773], [0x01F780, 0x01F7D8], @@ -671,22 +692,22 @@ const matchSymbols = buildString({ [0x01F860, 0x01F887], [0x01F890, 0x01F8AD], [0x01F8B0, 0x01F8B1], - [0x01F900, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01FA53], + [0x01F900, 0x01FA53], [0x01FA60, 0x01FA6D], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6], + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6], [0x01FB00, 0x01FB92], [0x01FB94, 0x01FBCA], [0x01FBF0, 0x01FBF9], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -711,11 +732,10 @@ const nonMatchSymbols = buildString({ 0x0003A2, 0x000530, 0x000590, - 0x00061D, 0x00070E, 0x00083F, 0x00085F, - 0x0008B5, + 0x00088F, 0x000984, 0x0009A9, 0x0009B1, @@ -791,13 +811,11 @@ const nonMatchSymbols = buildString({ 0x0012C1, 0x0012D7, 0x001311, - 0x00170D, 0x00176D, 0x001771, - 0x00180F, 0x00191F, 0x001A5F, - 0x001DFA, + 0x001B7F, 0x001F58, 0x001F5A, 0x001F5C, @@ -810,8 +828,6 @@ const nonMatchSymbols = buildString({ 0x002065, 0x00208F, 0x002B96, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -826,6 +842,8 @@ const nonMatchSymbols = buildString({ 0x003130, 0x00318F, 0x00321F, + 0x00A7D2, + 0x00A7D4, 0x00A9CE, 0x00A9FF, 0x00AB27, @@ -846,6 +864,15 @@ const nonMatchSymbols = buildString({ 0x01003E, 0x01018F, 0x01039E, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x010856, @@ -885,8 +912,12 @@ const nonMatchSymbols = buildString({ 0x01246F, 0x01342F, 0x016A5F, + 0x016ABF, 0x016B5A, 0x016B62, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -904,6 +935,10 @@ const nonMatchSymbols = buildString({ 0x01E007, 0x01E022, 0x01E025, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -932,8 +967,6 @@ const nonMatchSymbols = buildString({ 0x01EEAA, 0x01F0C0, 0x01F0D0, - 0x01F979, - 0x01F9CC, 0x01FB93 ], ranges: [ @@ -949,8 +982,8 @@ const nonMatchSymbols = buildString({ [0x0007FB, 0x0007FC], [0x00082E, 0x00082F], [0x00085C, 0x00085D], - [0x00086B, 0x00089F], - [0x0008C8, 0x0008D2], + [0x00086B, 0x00086F], + [0x000892, 0x000897], [0x00098D, 0x00098E], [0x000991, 0x000992], [0x0009B3, 0x0009B5], @@ -995,14 +1028,15 @@ const nonMatchSymbols = buildString({ [0x000BD1, 0x000BD6], [0x000BD8, 0x000BE5], [0x000BFB, 0x000BFF], - [0x000C3A, 0x000C3C], + [0x000C3A, 0x000C3B], [0x000C4E, 0x000C54], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C64, 0x000C65], [0x000C70, 0x000C76], [0x000CBA, 0x000CBB], [0x000CCE, 0x000CD4], - [0x000CD7, 0x000CDD], + [0x000CD7, 0x000CDC], [0x000CE4, 0x000CE5], [0x000CF3, 0x000CFF], [0x000D50, 0x000D53], @@ -1037,7 +1071,7 @@ const nonMatchSymbols = buildString({ [0x0013FE, 0x0013FF], [0x00169D, 0x00169F], [0x0016F9, 0x0016FF], - [0x001715, 0x00171F], + [0x001716, 0x00171E], [0x001737, 0x00173F], [0x001754, 0x00175F], [0x001774, 0x00177F], @@ -1061,9 +1095,8 @@ const nonMatchSymbols = buildString({ [0x001A8A, 0x001A8F], [0x001A9A, 0x001A9F], [0x001AAE, 0x001AAF], - [0x001AC1, 0x001AFF], - [0x001B4C, 0x001B4F], - [0x001B7D, 0x001B7F], + [0x001ACF, 0x001AFF], + [0x001B4D, 0x001B4F], [0x001BF4, 0x001BFB], [0x001C38, 0x001C3A], [0x001C4A, 0x001C4C], @@ -1080,7 +1113,7 @@ const nonMatchSymbols = buildString({ [0x001FF0, 0x001FF1], [0x002072, 0x002073], [0x00209D, 0x00209F], - [0x0020C0, 0x0020CF], + [0x0020C1, 0x0020CF], [0x0020F1, 0x0020FF], [0x00218C, 0x00218F], [0x002427, 0x00243F], @@ -1092,20 +1125,19 @@ const nonMatchSymbols = buildString({ [0x002D68, 0x002D6E], [0x002D71, 0x002D7E], [0x002D97, 0x002D9F], - [0x002E53, 0x002E7F], + [0x002E5E, 0x002E7F], [0x002EF4, 0x002EFF], [0x002FD6, 0x002FEF], [0x002FFC, 0x002FFF], [0x003097, 0x003098], [0x003100, 0x003104], [0x0031E4, 0x0031EF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A48F], [0x00A4C7, 0x00A4CF], [0x00A62C, 0x00A63F], [0x00A6F8, 0x00A6FF], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A82D, 0x00A82F], [0x00A83A, 0x00A83F], [0x00A878, 0x00A87F], @@ -1132,11 +1164,10 @@ const nonMatchSymbols = buildString({ [0x00FADA, 0x00FAFF], [0x00FB07, 0x00FB12], [0x00FB18, 0x00FB1C], - [0x00FBC2, 0x00FBD2], - [0x00FD40, 0x00FD4F], + [0x00FBC3, 0x00FBD2], [0x00FD90, 0x00FD91], - [0x00FDC8, 0x00FDEF], - [0x00FDFE, 0x00FDFF], + [0x00FDC8, 0x00FDCE], + [0x00FDD0, 0x00FDEF], [0x00FE1A, 0x00FE1F], [0x00FE6C, 0x00FE6F], [0x00FEFD, 0x00FEFE], @@ -1169,10 +1200,11 @@ const nonMatchSymbols = buildString({ [0x0104FC, 0x0104FF], [0x010528, 0x01052F], [0x010564, 0x01056E], - [0x010570, 0x0105FF], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -1206,12 +1238,13 @@ const nonMatchSymbols = buildString({ [0x010EAE, 0x010EAF], [0x010EB2, 0x010EFF], [0x010F28, 0x010F2F], - [0x010F5A, 0x010FAF], + [0x010F5A, 0x010F6F], + [0x010F8A, 0x010FAF], [0x010FCC, 0x010FDF], [0x010FF7, 0x010FFF], [0x01104E, 0x011051], - [0x011070, 0x01107E], - [0x0110C2, 0x0110CC], + [0x011076, 0x01107E], + [0x0110C3, 0x0110CC], [0x0110CE, 0x0110CF], [0x0110E9, 0x0110EF], [0x0110FA, 0x0110FF], @@ -1240,11 +1273,11 @@ const nonMatchSymbols = buildString({ [0x011645, 0x01164F], [0x01165A, 0x01165F], [0x01166D, 0x01167F], - [0x0116B9, 0x0116BF], + [0x0116BA, 0x0116BF], [0x0116CA, 0x0116FF], [0x01171B, 0x01171C], [0x01172C, 0x01172F], - [0x011740, 0x0117FF], + [0x011747, 0x0117FF], [0x01183C, 0x01189F], [0x0118F3, 0x0118FE], [0x011907, 0x011908], @@ -1256,7 +1289,7 @@ const nonMatchSymbols = buildString({ [0x0119D8, 0x0119D9], [0x0119E5, 0x0119FF], [0x011A48, 0x011A4F], - [0x011AA3, 0x011ABF], + [0x011AA3, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C46, 0x011C4F], [0x011C6D, 0x011C6F], @@ -1272,12 +1305,13 @@ const nonMatchSymbols = buildString({ [0x011FF2, 0x011FFE], [0x01239A, 0x0123FF], [0x012475, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF3, 0x012FFF], [0x013439, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], [0x016A6A, 0x016A6D], - [0x016A70, 0x016ACF], + [0x016ACA, 0x016ACF], [0x016AEE, 0x016AEF], [0x016AF6, 0x016AFF], [0x016B46, 0x016B4F], @@ -1291,8 +1325,8 @@ const nonMatchSymbols = buildString({ [0x016FF2, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -1300,10 +1334,13 @@ const nonMatchSymbols = buildString({ [0x01BC7D, 0x01BC7F], [0x01BC89, 0x01BC8F], [0x01BC9A, 0x01BC9B], - [0x01BCA4, 0x01CFFF], + [0x01BCA4, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01CF4F], + [0x01CFC4, 0x01CFFF], [0x01D0F6, 0x01D0FF], [0x01D127, 0x01D128], - [0x01D1E9, 0x01D1FF], + [0x01D1EB, 0x01D1FF], [0x01D246, 0x01D2DF], [0x01D2F4, 0x01D2FF], [0x01D357, 0x01D35F], @@ -1316,15 +1353,17 @@ const nonMatchSymbols = buildString({ [0x01D6A6, 0x01D6A7], [0x01D7CC, 0x01D7CD], [0x01DA8C, 0x01DA9A], - [0x01DAB0, 0x01DFFF], + [0x01DAB0, 0x01DEFF], + [0x01DF1F, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E0FF], [0x01E12D, 0x01E12F], [0x01E13E, 0x01E13F], [0x01E14A, 0x01E14D], - [0x01E150, 0x01E2BF], + [0x01E150, 0x01E28F], + [0x01E2AF, 0x01E2BF], [0x01E2FA, 0x01E2FE], - [0x01E300, 0x01E7FF], + [0x01E300, 0x01E7DF], [0x01E8C5, 0x01E8C6], [0x01E8D7, 0x01E8FF], [0x01E94C, 0x01E94F], @@ -1350,12 +1389,13 @@ const nonMatchSymbols = buildString({ [0x01F249, 0x01F24F], [0x01F252, 0x01F25F], [0x01F266, 0x01F2FF], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6ED, 0x01F6EF], [0x01F6FD, 0x01F6FF], [0x01F774, 0x01F77F], [0x01F7D9, 0x01F7DF], - [0x01F7EC, 0x01F7FF], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F7FF], [0x01F80C, 0x01F80F], [0x01F848, 0x01F84F], [0x01F85A, 0x01F85F], @@ -1365,16 +1405,18 @@ const nonMatchSymbols = buildString({ [0x01FA54, 0x01FA5F], [0x01FA6E, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x01FAFF], + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x01FAFF], [0x01FBCB, 0x01FBEF], [0x01FBFA, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Control.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Control.js index 0d6ed8b693b2..11405fdf36f6 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Control.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Control.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Bidi_Control` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Mirrored.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Mirrored.js index 66e5bd635b2b..79280b37325c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Mirrored.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Mirrored.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Bidi_Mirrored` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -123,6 +123,7 @@ const matchSymbols = buildString({ [0x002E0C, 0x002E0D], [0x002E1C, 0x002E1D], [0x002E20, 0x002E29], + [0x002E55, 0x002E5C], [0x003008, 0x003011], [0x003014, 0x00301B], [0x00FE59, 0x00FE5E], @@ -248,7 +249,8 @@ const nonMatchSymbols = buildString({ [0x002E06, 0x002E08], [0x002E0E, 0x002E1B], [0x002E1E, 0x002E1F], - [0x002E2A, 0x003007], + [0x002E2A, 0x002E54], + [0x002E5D, 0x003007], [0x003012, 0x003013], [0x00301C, 0x00DBFF], [0x00E000, 0x00FE58], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Case_Ignorable.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Case_Ignorable.js index 00e22de64656..21d9473a2c13 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Case_Ignorable.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Case_Ignorable.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Case_Ignorable` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -38,6 +38,7 @@ const matchSymbols = buildString({ 0x000711, 0x0007FA, 0x0007FD, + 0x000888, 0x00093A, 0x00093C, 0x00094D, @@ -60,6 +61,7 @@ const matchSymbols = buildString({ 0x000BCD, 0x000C00, 0x000C04, + 0x000C3C, 0x000C81, 0x000CBC, 0x000CBF, @@ -147,7 +149,9 @@ const matchSymbols = buildString({ 0x0102E0, 0x010A3F, 0x011001, + 0x011070, 0x0110BD, + 0x0110C2, 0x0110CD, 0x011173, 0x0111CF, @@ -174,6 +178,7 @@ const matchSymbols = buildString({ 0x016F4F, 0x01DA75, 0x01DA84, + 0x01E2AE, 0x0E0001 ], ranges: [ @@ -196,7 +201,9 @@ const matchSymbols = buildString({ [0x0007EB, 0x0007F5], [0x000816, 0x00082D], [0x000859, 0x00085B], - [0x0008D3, 0x000902], + [0x000890, 0x000891], + [0x000898, 0x00089F], + [0x0008C9, 0x000902], [0x000941, 0x000948], [0x000951, 0x000957], [0x000962, 0x000963], @@ -247,13 +254,13 @@ const matchSymbols = buildString({ [0x001085, 0x001086], [0x00135D, 0x00135F], [0x001712, 0x001714], - [0x001732, 0x001734], + [0x001732, 0x001733], [0x001752, 0x001753], [0x001772, 0x001773], [0x0017B4, 0x0017B5], [0x0017B7, 0x0017BD], [0x0017C9, 0x0017D3], - [0x00180B, 0x00180E], + [0x00180B, 0x00180F], [0x001885, 0x001886], [0x001920, 0x001922], [0x001927, 0x001928], @@ -262,7 +269,7 @@ const matchSymbols = buildString({ [0x001A58, 0x001A5E], [0x001A65, 0x001A6C], [0x001A73, 0x001A7C], - [0x001AB0, 0x001AC0], + [0x001AB0, 0x001ACE], [0x001B00, 0x001B03], [0x001B36, 0x001B3A], [0x001B6B, 0x001B73], @@ -280,8 +287,7 @@ const matchSymbols = buildString({ [0x001CE2, 0x001CE8], [0x001CF8, 0x001CF9], [0x001D2C, 0x001D6A], - [0x001D9B, 0x001DF9], - [0x001DFB, 0x001DFF], + [0x001D9B, 0x001DFF], [0x001FBF, 0x001FC1], [0x001FCD, 0x001FCF], [0x001FDD, 0x001FDF], @@ -308,6 +314,7 @@ const matchSymbols = buildString({ [0x00A6F0, 0x00A6F1], [0x00A700, 0x00A721], [0x00A788, 0x00A78A], + [0x00A7F2, 0x00A7F4], [0x00A7F8, 0x00A7F9], [0x00A825, 0x00A826], [0x00A8C4, 0x00A8C5], @@ -328,12 +335,15 @@ const matchSymbols = buildString({ [0x00AAF3, 0x00AAF4], [0x00AB5B, 0x00AB5F], [0x00AB69, 0x00AB6B], - [0x00FBB2, 0x00FBC1], + [0x00FBB2, 0x00FBC2], [0x00FE00, 0x00FE0F], [0x00FE20, 0x00FE2F], [0x00FF9E, 0x00FF9F], [0x00FFF9, 0x00FFFB], [0x010376, 0x01037A], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010A01, 0x010A03], [0x010A05, 0x010A06], [0x010A0C, 0x010A0F], @@ -342,7 +352,9 @@ const matchSymbols = buildString({ [0x010D24, 0x010D27], [0x010EAB, 0x010EAC], [0x010F46, 0x010F50], + [0x010F82, 0x010F85], [0x011038, 0x011046], + [0x011073, 0x011074], [0x01107F, 0x011081], [0x0110B3, 0x0110B6], [0x0110B9, 0x0110BA], @@ -404,8 +416,13 @@ const matchSymbols = buildString({ [0x016F8F, 0x016F9F], [0x016FE0, 0x016FE1], [0x016FE3, 0x016FE4], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], [0x01BC9D, 0x01BC9E], [0x01BCA0, 0x01BCA3], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D167, 0x01D169], [0x01D173, 0x01D182], [0x01D185, 0x01D18B], @@ -457,6 +474,7 @@ const nonMatchSymbols = buildString({ 0x000AC6, 0x000B00, 0x000B40, + 0x000C3D, 0x000C49, 0x000DD5, 0x000EC7, @@ -478,7 +496,6 @@ const nonMatchSymbols = buildString({ 0x001BEE, 0x001CD3, 0x001CE1, - 0x001DFA, 0x001FBE, 0x002065, 0x002070, @@ -488,6 +505,8 @@ const nonMatchSymbols = buildString({ 0x00AAC0, 0x00AAF5, 0x00FF3F, + 0x010786, + 0x0107B1, 0x010A04, 0x01112C, 0x011235, @@ -511,6 +530,8 @@ const nonMatchSymbols = buildString({ 0x011D46, 0x011D96, 0x016FE2, + 0x01AFF4, + 0x01AFFC, 0x01BC9F, 0x01DAA0, 0x01E007, @@ -550,7 +571,10 @@ const nonMatchSymbols = buildString({ [0x0007FB, 0x0007FC], [0x0007FE, 0x000815], [0x00082E, 0x000858], - [0x00085C, 0x0008D2], + [0x00085C, 0x000887], + [0x000889, 0x00088F], + [0x000892, 0x000897], + [0x0008A0, 0x0008C8], [0x000903, 0x000939], [0x00093D, 0x000940], [0x000949, 0x00094C], @@ -587,7 +611,7 @@ const nonMatchSymbols = buildString({ [0x000BC1, 0x000BCC], [0x000BCE, 0x000BFF], [0x000C01, 0x000C03], - [0x000C05, 0x000C3D], + [0x000C05, 0x000C3B], [0x000C41, 0x000C45], [0x000C4E, 0x000C54], [0x000C57, 0x000C61], @@ -629,7 +653,7 @@ const nonMatchSymbols = buildString({ [0x0010FD, 0x00135C], [0x001360, 0x001711], [0x001715, 0x001731], - [0x001735, 0x001751], + [0x001734, 0x001751], [0x001754, 0x001771], [0x001774, 0x0017B3], [0x0017BE, 0x0017C5], @@ -637,7 +661,7 @@ const nonMatchSymbols = buildString({ [0x0017D4, 0x0017D6], [0x0017D8, 0x0017DC], [0x0017DE, 0x00180A], - [0x00180F, 0x001842], + [0x001810, 0x001842], [0x001844, 0x001884], [0x001887, 0x0018A8], [0x0018AA, 0x00191F], @@ -652,7 +676,7 @@ const nonMatchSymbols = buildString({ [0x001A7D, 0x001A7E], [0x001A80, 0x001AA6], [0x001AA8, 0x001AAF], - [0x001AC1, 0x001AFF], + [0x001ACF, 0x001AFF], [0x001B04, 0x001B33], [0x001B3D, 0x001B41], [0x001B43, 0x001B6A], @@ -706,7 +730,8 @@ const nonMatchSymbols = buildString({ [0x00A6F2, 0x00A6FF], [0x00A722, 0x00A76F], [0x00A771, 0x00A787], - [0x00A78B, 0x00A7F7], + [0x00A78B, 0x00A7F1], + [0x00A7F5, 0x00A7F7], [0x00A7FA, 0x00A801], [0x00A803, 0x00A805], [0x00A807, 0x00A80A], @@ -744,7 +769,7 @@ const nonMatchSymbols = buildString({ [0x00ABEE, 0x00DBFF], [0x00E000, 0x00FB1D], [0x00FB1F, 0x00FBB1], - [0x00FBC2, 0x00FDFF], + [0x00FBC3, 0x00FDFF], [0x00FE10, 0x00FE12], [0x00FE14, 0x00FE1F], [0x00FE30, 0x00FE51], @@ -761,7 +786,8 @@ const nonMatchSymbols = buildString({ [0x00FFFC, 0x0101FC], [0x0101FE, 0x0102DF], [0x0102E1, 0x010375], - [0x01037B, 0x010A00], + [0x01037B, 0x01077F], + [0x0107BB, 0x010A00], [0x010A07, 0x010A0B], [0x010A10, 0x010A37], [0x010A3B, 0x010A3E], @@ -769,13 +795,17 @@ const nonMatchSymbols = buildString({ [0x010AE7, 0x010D23], [0x010D28, 0x010EAA], [0x010EAD, 0x010F45], - [0x010F51, 0x011000], + [0x010F51, 0x010F81], + [0x010F86, 0x011000], [0x011002, 0x011037], - [0x011047, 0x01107E], + [0x011047, 0x01106F], + [0x011071, 0x011072], + [0x011075, 0x01107E], [0x011082, 0x0110B2], [0x0110B7, 0x0110B8], [0x0110BB, 0x0110BC], - [0x0110BE, 0x0110CC], + [0x0110BE, 0x0110C1], + [0x0110C3, 0x0110CC], [0x0110CE, 0x0110FF], [0x011103, 0x011126], [0x011135, 0x011172], @@ -835,8 +865,11 @@ const nonMatchSymbols = buildString({ [0x016B44, 0x016F4E], [0x016F50, 0x016F8E], [0x016FA0, 0x016FDF], - [0x016FE5, 0x01BC9C], - [0x01BCA4, 0x01D166], + [0x016FE5, 0x01AFEF], + [0x01AFFF, 0x01BC9C], + [0x01BCA4, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D166], [0x01D16A, 0x01D172], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], @@ -849,7 +882,8 @@ const nonMatchSymbols = buildString({ [0x01DAB0, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E12F], - [0x01E13E, 0x01E2EB], + [0x01E13E, 0x01E2AD], + [0x01E2AF, 0x01E2EB], [0x01E2F0, 0x01E8CF], [0x01E8D7, 0x01E943], [0x01E94C, 0x01F3FA], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Cased.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Cased.js index 3891f89ccf05..1e75254fa3bc 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Cased.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Cased.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Cased` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -40,6 +40,8 @@ const matchSymbols = buildString({ 0x00214E, 0x002D27, 0x002D2D, + 0x00A7D3, + 0x010780, 0x01D4A2, 0x01D4BB, 0x01D546 @@ -99,9 +101,7 @@ const matchSymbols = buildString({ [0x002160, 0x00217F], [0x002183, 0x002184], [0x0024B6, 0x0024E9], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CE4], + [0x002C00, 0x002CE4], [0x002CEB, 0x002CEE], [0x002CF2, 0x002CF3], [0x002D00, 0x002D25], @@ -109,8 +109,9 @@ const matchSymbols = buildString({ [0x00A680, 0x00A69D], [0x00A722, 0x00A787], [0x00A78B, 0x00A78E], - [0x00A790, 0x00A7BF], - [0x00A7C2, 0x00A7CA], + [0x00A790, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], [0x00A7F5, 0x00A7F6], [0x00A7F8, 0x00A7FA], [0x00AB30, 0x00AB5A], @@ -123,6 +124,17 @@ const matchSymbols = buildString({ [0x010400, 0x01044F], [0x0104B0, 0x0104D3], [0x0104D8, 0x0104FB], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], + [0x010783, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010C80, 0x010CB2], [0x010CC0, 0x010CF2], [0x0118A0, 0x0118DF], @@ -154,6 +166,8 @@ const matchSymbols = buildString({ [0x01D78A, 0x01D7A8], [0x01D7AA, 0x01D7C2], [0x01D7C4, 0x01D7CB], + [0x01DF00, 0x01DF09], + [0x01DF0B, 0x01DF1E], [0x01E900, 0x01E943], [0x01F130, 0x01F149], [0x01F150, 0x01F169], @@ -193,12 +207,21 @@ const nonMatchSymbols = buildString({ 0x002127, 0x002129, 0x00212E, - 0x002C2F, - 0x002C5F, 0x002D26, 0x00A78F, + 0x00A7D2, + 0x00A7D4, 0x00A7F7, 0x00AB5B, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x01D455, 0x01D49D, 0x01D4AD, @@ -221,7 +244,8 @@ const nonMatchSymbols = buildString({ 0x01D76F, 0x01D789, 0x01D7A9, - 0x01D7C3 + 0x01D7C3, + 0x01DF0A ], ranges: [ [0x00DC00, 0x00DFFF], @@ -286,8 +310,8 @@ const nonMatchSymbols = buildString({ [0x00A66E, 0x00A67F], [0x00A69E, 0x00A721], [0x00A788, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F4], [0x00A7FB, 0x00AB2F], [0x00AB69, 0x00AB6F], [0x00ABC0, 0x00DBFF], @@ -298,7 +322,10 @@ const nonMatchSymbols = buildString({ [0x00FF5B, 0x0103FF], [0x010450, 0x0104AF], [0x0104D4, 0x0104D7], - [0x0104FC, 0x010C7F], + [0x0104FC, 0x01056F], + [0x0105BD, 0x01077F], + [0x010781, 0x010782], + [0x0107BB, 0x010C7F], [0x010CB3, 0x010CBF], [0x010CF3, 0x01189F], [0x0118E0, 0x016E3F], @@ -309,7 +336,8 @@ const nonMatchSymbols = buildString({ [0x01D50B, 0x01D50C], [0x01D547, 0x01D549], [0x01D6A6, 0x01D6A7], - [0x01D7CC, 0x01E8FF], + [0x01D7CC, 0x01DEFF], + [0x01DF1F, 0x01E8FF], [0x01E944, 0x01F12F], [0x01F14A, 0x01F14F], [0x01F16A, 0x01F16F], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casefolded.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casefolded.js index b5bed20fe1fe..74a4dcb39bdf 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casefolded.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casefolded.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Changes_When_Casefolded` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -547,8 +547,12 @@ const matchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, + 0x00A7C0, 0x00A7C2, 0x00A7C9, + 0x00A7D0, + 0x00A7D6, + 0x00A7D8, 0x00A7F5 ], ranges: [ @@ -613,7 +617,7 @@ const matchSymbols = buildString({ [0x00212A, 0x00212B], [0x002160, 0x00216F], [0x0024B6, 0x0024CF], - [0x002C00, 0x002C2E], + [0x002C00, 0x002C2F], [0x002C62, 0x002C64], [0x002C6D, 0x002C70], [0x002C7E, 0x002C80], @@ -627,6 +631,10 @@ const matchSymbols = buildString({ [0x00FF21, 0x00FF3A], [0x010400, 0x010427], [0x0104B0, 0x0104D3], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], [0x010C80, 0x010CB2], [0x0118A0, 0x0118BF], [0x016E40, 0x016E5F], @@ -1171,8 +1179,14 @@ const nonMatchSymbols = buildString({ 0x00A7B9, 0x00A7BB, 0x00A7BD, + 0x00A7BF, + 0x00A7C1, 0x00A7C3, - 0x00A7C8 + 0x00A7C8, + 0x00A7D7, + 0x01057B, + 0x01058B, + 0x010593 ], ranges: [ [0x00DC00, 0x00DFFF], @@ -1237,7 +1251,7 @@ const nonMatchSymbols = buildString({ [0x002170, 0x002182], [0x002184, 0x0024B5], [0x0024D0, 0x002BFF], - [0x002C2F, 0x002C5F], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002C73, 0x002C74], [0x002C76, 0x002C7D], @@ -1251,8 +1265,9 @@ const nonMatchSymbols = buildString({ [0x00A787, 0x00A78A], [0x00A78E, 0x00A78F], [0x00A793, 0x00A795], - [0x00A7BF, 0x00A7C1], - [0x00A7CA, 0x00A7F4], + [0x00A7CA, 0x00A7CF], + [0x00A7D1, 0x00A7D5], + [0x00A7D9, 0x00A7F4], [0x00A7F6, 0x00AB6F], [0x00ABC0, 0x00DBFF], [0x00E000, 0x00FAFF], @@ -1260,7 +1275,8 @@ const nonMatchSymbols = buildString({ [0x00FB18, 0x00FF20], [0x00FF3B, 0x0103FF], [0x010428, 0x0104AF], - [0x0104D4, 0x010C7F], + [0x0104D4, 0x01056F], + [0x010596, 0x010C7F], [0x010CB3, 0x01189F], [0x0118C0, 0x016E3F], [0x016E60, 0x01E8FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casemapped.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casemapped.js index 166d831e5fcc..a406d08d8a2f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casemapped.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casemapped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Changes_When_Casemapped` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -108,9 +108,7 @@ const matchSymbols = buildString({ [0x002160, 0x00217F], [0x002183, 0x002184], [0x0024B6, 0x0024E9], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002C70], + [0x002C00, 0x002C70], [0x002C72, 0x002C73], [0x002C75, 0x002C76], [0x002C7E, 0x002CE3], @@ -125,8 +123,9 @@ const matchSymbols = buildString({ [0x00A78B, 0x00A78D], [0x00A790, 0x00A794], [0x00A796, 0x00A7AE], - [0x00A7B0, 0x00A7BF], - [0x00A7C2, 0x00A7CA], + [0x00A7B0, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D6, 0x00A7D9], [0x00A7F5, 0x00A7F6], [0x00AB70, 0x00ABBF], [0x00FB00, 0x00FB06], @@ -136,6 +135,14 @@ const matchSymbols = buildString({ [0x010400, 0x01044F], [0x0104B0, 0x0104D3], [0x0104D8, 0x0104FB], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010C80, 0x010CB2], [0x010CC0, 0x010CF2], [0x0118A0, 0x0118DF], @@ -189,13 +196,18 @@ const nonMatchSymbols = buildString({ 0x001FBD, 0x001FC5, 0x001FF5, - 0x002C2F, - 0x002C5F, 0x002C71, 0x002C74, 0x002D26, 0x00A795, - 0x00A7AF + 0x00A7AF, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA ], ranges: [ [0x00DC00, 0x00DFFF], @@ -267,8 +279,9 @@ const nonMatchSymbols = buildString({ [0x00A770, 0x00A778], [0x00A788, 0x00A78A], [0x00A78E, 0x00A78F], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7D2, 0x00A7D5], + [0x00A7DA, 0x00A7F4], [0x00A7F7, 0x00AB52], [0x00AB54, 0x00AB6F], [0x00ABC0, 0x00DBFF], @@ -279,7 +292,8 @@ const nonMatchSymbols = buildString({ [0x00FF5B, 0x0103FF], [0x010450, 0x0104AF], [0x0104D4, 0x0104D7], - [0x0104FC, 0x010C7F], + [0x0104FC, 0x01056F], + [0x0105BD, 0x010C7F], [0x010CB3, 0x010CBF], [0x010CF3, 0x01189F], [0x0118E0, 0x016E3F], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Lowercased.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Lowercased.js index ed9169d23a2e..40a658e02f00 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Lowercased.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Lowercased.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Changes_When_Lowercased` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -545,8 +545,12 @@ const matchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, + 0x00A7C0, 0x00A7C2, 0x00A7C9, + 0x00A7D0, + 0x00A7D6, + 0x00A7D8, 0x00A7F5 ], ranges: [ @@ -603,7 +607,7 @@ const matchSymbols = buildString({ [0x00212A, 0x00212B], [0x002160, 0x00216F], [0x0024B6, 0x0024CF], - [0x002C00, 0x002C2E], + [0x002C00, 0x002C2F], [0x002C62, 0x002C64], [0x002C6D, 0x002C70], [0x002C7E, 0x002C80], @@ -614,6 +618,10 @@ const matchSymbols = buildString({ [0x00FF21, 0x00FF3A], [0x010400, 0x010427], [0x0104B0, 0x0104D3], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], [0x010C80, 0x010CB2], [0x0118A0, 0x0118BF], [0x016E40, 0x016E5F], @@ -1152,8 +1160,14 @@ const nonMatchSymbols = buildString({ 0x00A7B9, 0x00A7BB, 0x00A7BD, + 0x00A7BF, + 0x00A7C1, 0x00A7C3, - 0x00A7C8 + 0x00A7C8, + 0x00A7D7, + 0x01057B, + 0x01058B, + 0x010593 ], ranges: [ [0x00DC00, 0x00DFFF], @@ -1214,7 +1228,7 @@ const nonMatchSymbols = buildString({ [0x002170, 0x002182], [0x002184, 0x0024B5], [0x0024D0, 0x002BFF], - [0x002C2F, 0x002C5F], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002C73, 0x002C74], [0x002C76, 0x002C7D], @@ -1228,13 +1242,15 @@ const nonMatchSymbols = buildString({ [0x00A787, 0x00A78A], [0x00A78E, 0x00A78F], [0x00A793, 0x00A795], - [0x00A7BF, 0x00A7C1], - [0x00A7CA, 0x00A7F4], + [0x00A7CA, 0x00A7CF], + [0x00A7D1, 0x00A7D5], + [0x00A7D9, 0x00A7F4], [0x00A7F6, 0x00DBFF], [0x00E000, 0x00FF20], [0x00FF3B, 0x0103FF], [0x010428, 0x0104AF], - [0x0104D4, 0x010C7F], + [0x0104D4, 0x01056F], + [0x010596, 0x010C7F], [0x010CB3, 0x01189F], [0x0118C0, 0x016E3F], [0x016E60, 0x01E8FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_NFKC_Casefolded.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_NFKC_Casefolded.js index 96ee771f120d..65681ce7f1a0 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_NFKC_Casefolded.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_NFKC_Casefolded.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Changes_When_NFKC_Casefolded` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -596,9 +596,12 @@ const matchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, + 0x00A7C0, 0x00A7C2, 0x00A7C9, - 0x00A7F5, + 0x00A7D0, + 0x00A7D6, + 0x00A7D8, 0x00AB69, 0x00FA10, 0x00FA12, @@ -686,7 +689,7 @@ const matchSymbols = buildString({ [0x00115F, 0x001160], [0x0013F8, 0x0013FD], [0x0017B4, 0x0017B5], - [0x00180B, 0x00180E], + [0x00180B, 0x00180F], [0x001C80, 0x001C88], [0x001C90, 0x001CBA], [0x001CBD, 0x001CBF], @@ -736,7 +739,7 @@ const matchSymbols = buildString({ [0x002329, 0x00232A], [0x002460, 0x0024EA], [0x002A74, 0x002A76], - [0x002C00, 0x002C2E], + [0x002C00, 0x002C2F], [0x002C62, 0x002C64], [0x002C6D, 0x002C70], [0x002C7C, 0x002C80], @@ -754,6 +757,7 @@ const matchSymbols = buildString({ [0x00A7AA, 0x00A7AE], [0x00A7B0, 0x00A7B4], [0x00A7C4, 0x00A7C7], + [0x00A7F2, 0x00A7F5], [0x00A7F8, 0x00A7F9], [0x00AB5C, 0x00AB5F], [0x00AB70, 0x00ABBF], @@ -790,6 +794,13 @@ const matchSymbols = buildString({ [0x00FFF0, 0x00FFF8], [0x010400, 0x010427], [0x0104B0, 0x0104D3], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010781, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010C80, 0x010CB2], [0x0118A0, 0x0118BF], [0x016E40, 0x016E5F], @@ -1418,8 +1429,11 @@ const nonMatchSymbols = buildString({ 0x00A7B9, 0x00A7BB, 0x00A7BD, + 0x00A7BF, + 0x00A7C1, 0x00A7C3, 0x00A7C8, + 0x00A7D7, 0x00FA11, 0x00FA1F, 0x00FA21, @@ -1436,6 +1450,11 @@ const nonMatchSymbols = buildString({ 0x00FF00, 0x00FFE7, 0x00FFEF, + 0x01057B, + 0x01058B, + 0x010593, + 0x010786, + 0x0107B1, 0x01D455, 0x01D49D, 0x01D4AD, @@ -1547,7 +1566,7 @@ const nonMatchSymbols = buildString({ [0x001161, 0x0013F7], [0x0013FE, 0x0017B3], [0x0017B6, 0x00180A], - [0x00180F, 0x001C7F], + [0x001810, 0x001C7F], [0x001C89, 0x001C8F], [0x001CBB, 0x001CBC], [0x001CC0, 0x001D2B], @@ -1597,7 +1616,7 @@ const nonMatchSymbols = buildString({ [0x002A0D, 0x002A73], [0x002A77, 0x002ADB], [0x002ADD, 0x002BFF], - [0x002C2F, 0x002C5F], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002C73, 0x002C74], [0x002C76, 0x002C7B], @@ -1624,8 +1643,9 @@ const nonMatchSymbols = buildString({ [0x00A787, 0x00A78A], [0x00A78E, 0x00A78F], [0x00A793, 0x00A795], - [0x00A7BF, 0x00A7C1], - [0x00A7CA, 0x00A7F4], + [0x00A7CA, 0x00A7CF], + [0x00A7D1, 0x00A7D5], + [0x00A7D9, 0x00A7F1], [0x00A7F6, 0x00A7F7], [0x00A7FA, 0x00AB5B], [0x00AB60, 0x00AB68], @@ -1656,7 +1676,9 @@ const nonMatchSymbols = buildString({ [0x00FFDD, 0x00FFDF], [0x00FFF9, 0x0103FF], [0x010428, 0x0104AF], - [0x0104D4, 0x010C7F], + [0x0104D4, 0x01056F], + [0x010596, 0x010780], + [0x0107BB, 0x010C7F], [0x010CB3, 0x01189F], [0x0118C0, 0x016E3F], [0x016E60, 0x01BC9F], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Titlecased.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Titlecased.js index 0db60b5a6b21..80e0123b524b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Titlecased.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Titlecased.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Changes_When_Titlecased` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -560,9 +560,13 @@ const matchSymbols = buildString({ 0x00A7BB, 0x00A7BD, 0x00A7BF, + 0x00A7C1, 0x00A7C3, 0x00A7C8, 0x00A7CA, + 0x00A7D1, + 0x00A7D7, + 0x00A7D9, 0x00A7F6, 0x00AB53 ], @@ -621,7 +625,7 @@ const matchSymbols = buildString({ [0x001FF6, 0x001FF7], [0x002170, 0x00217F], [0x0024D0, 0x0024E9], - [0x002C30, 0x002C5E], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002D00, 0x002D25], [0x00A793, 0x00A794], @@ -631,6 +635,10 @@ const matchSymbols = buildString({ [0x00FF41, 0x00FF5A], [0x010428, 0x01044F], [0x0104D8, 0x0104FB], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010CC0, 0x010CF2], [0x0118C0, 0x0118DF], [0x016E60, 0x016E7F], @@ -1014,6 +1022,7 @@ const nonMatchSymbols = buildString({ 0x001FB5, 0x001FC5, 0x001FF5, + 0x002C60, 0x002C67, 0x002C69, 0x002C6B, @@ -1159,7 +1168,13 @@ const nonMatchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, - 0x00A7C9 + 0x00A7C0, + 0x00A7C2, + 0x00A7C9, + 0x00A7D8, + 0x0105A2, + 0x0105B2, + 0x0105BA ], ranges: [ [0x00DC00, 0x00DFFF], @@ -1238,7 +1253,6 @@ const nonMatchSymbols = buildString({ [0x002180, 0x002183], [0x002185, 0x0024CF], [0x0024EA, 0x002C2F], - [0x002C5F, 0x002C60], [0x002C62, 0x002C64], [0x002C6D, 0x002C72], [0x002C74, 0x002C75], @@ -1257,9 +1271,10 @@ const nonMatchSymbols = buildString({ [0x00A78D, 0x00A790], [0x00A795, 0x00A796], [0x00A7AA, 0x00A7B4], - [0x00A7C0, 0x00A7C2], [0x00A7C4, 0x00A7C7], - [0x00A7CB, 0x00A7F5], + [0x00A7CB, 0x00A7D0], + [0x00A7D2, 0x00A7D6], + [0x00A7DA, 0x00A7F5], [0x00A7F7, 0x00AB52], [0x00AB54, 0x00AB6F], [0x00ABC0, 0x00DBFF], @@ -1268,7 +1283,8 @@ const nonMatchSymbols = buildString({ [0x00FB18, 0x00FF40], [0x00FF5B, 0x010427], [0x010450, 0x0104D7], - [0x0104FC, 0x010CBF], + [0x0104FC, 0x010596], + [0x0105BD, 0x010CBF], [0x010CF3, 0x0118BF], [0x0118E0, 0x016E5F], [0x016E80, 0x01E921], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Uppercased.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Uppercased.js index 8f4deb9764fe..c0dffe3c4bcf 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Uppercased.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Uppercased.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Changes_When_Uppercased` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -560,9 +560,13 @@ const matchSymbols = buildString({ 0x00A7BB, 0x00A7BD, 0x00A7BF, + 0x00A7C1, 0x00A7C3, 0x00A7C8, 0x00A7CA, + 0x00A7D1, + 0x00A7D7, + 0x00A7D9, 0x00A7F6, 0x00AB53 ], @@ -622,7 +626,7 @@ const matchSymbols = buildString({ [0x001FF6, 0x001FF7], [0x002170, 0x00217F], [0x0024D0, 0x0024E9], - [0x002C30, 0x002C5E], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002D00, 0x002D25], [0x00A793, 0x00A794], @@ -632,6 +636,10 @@ const matchSymbols = buildString({ [0x00FF41, 0x00FF5A], [0x010428, 0x01044F], [0x0104D8, 0x0104FB], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010CC0, 0x010CF2], [0x0118C0, 0x0118DF], [0x016E60, 0x016E7F], @@ -1015,6 +1023,7 @@ const nonMatchSymbols = buildString({ 0x001FBD, 0x001FC5, 0x001FF5, + 0x002C60, 0x002C67, 0x002C69, 0x002C6B, @@ -1160,7 +1169,13 @@ const nonMatchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, - 0x00A7C9 + 0x00A7C0, + 0x00A7C2, + 0x00A7C9, + 0x00A7D8, + 0x0105A2, + 0x0105B2, + 0x0105BA ], ranges: [ [0x00DC00, 0x00DFFF], @@ -1240,7 +1255,6 @@ const nonMatchSymbols = buildString({ [0x002180, 0x002183], [0x002185, 0x0024CF], [0x0024EA, 0x002C2F], - [0x002C5F, 0x002C60], [0x002C62, 0x002C64], [0x002C6D, 0x002C72], [0x002C74, 0x002C75], @@ -1259,9 +1273,10 @@ const nonMatchSymbols = buildString({ [0x00A78D, 0x00A790], [0x00A795, 0x00A796], [0x00A7AA, 0x00A7B4], - [0x00A7C0, 0x00A7C2], [0x00A7C4, 0x00A7C7], - [0x00A7CB, 0x00A7F5], + [0x00A7CB, 0x00A7D0], + [0x00A7D2, 0x00A7D6], + [0x00A7DA, 0x00A7F5], [0x00A7F7, 0x00AB52], [0x00AB54, 0x00AB6F], [0x00ABC0, 0x00DBFF], @@ -1270,7 +1285,8 @@ const nonMatchSymbols = buildString({ [0x00FB18, 0x00FF40], [0x00FF5B, 0x010427], [0x010450, 0x0104D7], - [0x0104FC, 0x010CBF], + [0x0104FC, 0x010596], + [0x0105BD, 0x010CBF], [0x010CF3, 0x0118BF], [0x0118E0, 0x016E5F], [0x016E80, 0x01E921], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Dash.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Dash.js index f3d8d3020361..5f7dbd9c1eb0 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Dash.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Dash.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Dash` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -27,6 +27,7 @@ const matchSymbols = buildString({ 0x002E17, 0x002E1A, 0x002E40, + 0x002E5D, 0x00301C, 0x003030, 0x0030A0, @@ -65,7 +66,8 @@ const nonMatchSymbols = buildString({ [0x002E18, 0x002E19], [0x002E1B, 0x002E39], [0x002E3C, 0x002E3F], - [0x002E41, 0x00301B], + [0x002E41, 0x002E5C], + [0x002E5E, 0x00301B], [0x00301D, 0x00302F], [0x003031, 0x00309F], [0x0030A1, 0x00DBFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Default_Ignorable_Code_Point.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Default_Ignorable_Code_Point.js index 34967377af6a..f01bb163b9a2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Default_Ignorable_Code_Point.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Default_Ignorable_Code_Point.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Default_Ignorable_Code_Point` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -25,7 +25,7 @@ const matchSymbols = buildString({ ranges: [ [0x00115F, 0x001160], [0x0017B4, 0x0017B5], - [0x00180B, 0x00180E], + [0x00180B, 0x00180F], [0x00200B, 0x00200F], [0x00202A, 0x00202E], [0x002060, 0x00206F], @@ -57,7 +57,7 @@ const nonMatchSymbols = buildString({ [0x00061D, 0x00115E], [0x001161, 0x0017B3], [0x0017B6, 0x00180A], - [0x00180F, 0x00200A], + [0x001810, 0x00200A], [0x002010, 0x002029], [0x00202F, 0x00205F], [0x002070, 0x003163], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Deprecated.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Deprecated.js index 6d61282eb2f2..ca7062801aa2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Deprecated.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Deprecated.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Deprecated` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Diacritic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Diacritic.js index e8ec927911ff..17b01c58efca 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Diacritic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Diacritic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Diacritic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -37,6 +37,7 @@ const matchSymbols = buildString({ 0x000B4D, 0x000B55, 0x000BCD, + 0x000C3C, 0x000C4D, 0x000CBC, 0x000CCD, @@ -73,6 +74,8 @@ const matchSymbols = buildString({ 0x00FF70, 0x00FFE3, 0x0102E0, + 0x011046, + 0x011070, 0x011173, 0x0111C0, 0x01133C, @@ -88,7 +91,8 @@ const matchSymbols = buildString({ 0x011A99, 0x011C3F, 0x011D42, - 0x011D97 + 0x011D97, + 0x01E2AE ], ranges: [ [0x0000B7, 0x0000B8], @@ -110,6 +114,8 @@ const matchSymbols = buildString({ [0x0007A6, 0x0007B0], [0x0007EB, 0x0007F5], [0x000818, 0x000819], + [0x000898, 0x00089F], + [0x0008C9, 0x0008D2], [0x0008E3, 0x0008FE], [0x000951, 0x000954], [0x000AFD, 0x000AFF], @@ -126,10 +132,12 @@ const matchSymbols = buildString({ [0x001087, 0x00108D], [0x00109A, 0x00109B], [0x00135D, 0x00135F], + [0x001714, 0x001715], [0x0017C9, 0x0017D3], [0x001939, 0x00193B], [0x001A75, 0x001A7C], - [0x001AB0, 0x001ABD], + [0x001AB0, 0x001ABE], + [0x001AC1, 0x001ACB], [0x001B6B, 0x001B73], [0x001BAA, 0x001BAB], [0x001C36, 0x001C37], @@ -138,8 +146,7 @@ const matchSymbols = buildString({ [0x001CF7, 0x001CF9], [0x001D2C, 0x001D6A], [0x001DC4, 0x001DCF], - [0x001DF5, 0x001DF9], - [0x001DFD, 0x001DFF], + [0x001DF5, 0x001DFF], [0x001FBF, 0x001FC1], [0x001FCD, 0x001FCF], [0x001FDD, 0x001FDF], @@ -163,9 +170,13 @@ const matchSymbols = buildString({ [0x00ABEC, 0x00ABED], [0x00FE20, 0x00FE2F], [0x00FF9E, 0x00FF9F], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010AE5, 0x010AE6], [0x010D22, 0x010D27], [0x010F46, 0x010F50], + [0x010F82, 0x010F85], [0x0110B9, 0x0110BA], [0x011133, 0x011134], [0x0111CA, 0x0111CC], @@ -183,6 +194,11 @@ const matchSymbols = buildString({ [0x016B30, 0x016B36], [0x016F8F, 0x016F9F], [0x016FF0, 0x016FF1], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D167, 0x01D169], [0x01D16D, 0x01D172], [0x01D17B, 0x01D182], @@ -223,7 +239,11 @@ const nonMatchSymbols = buildString({ 0x001FBE, 0x00A67E, 0x00FF3F, + 0x010786, + 0x0107B1, 0x011D43, + 0x01AFF4, + 0x01AFFC, 0x01E947 ], ranges: [ @@ -250,7 +270,9 @@ const nonMatchSymbols = buildString({ [0x00074B, 0x0007A5], [0x0007B1, 0x0007EA], [0x0007F6, 0x000817], - [0x00081A, 0x0008E2], + [0x00081A, 0x000897], + [0x0008A0, 0x0008C8], + [0x0008D3, 0x0008E2], [0x0008FF, 0x00093B], [0x00093D, 0x00094C], [0x00094E, 0x000950], @@ -266,7 +288,8 @@ const nonMatchSymbols = buildString({ [0x000B3D, 0x000B4C], [0x000B4E, 0x000B54], [0x000B56, 0x000BCC], - [0x000BCE, 0x000C4C], + [0x000BCE, 0x000C3B], + [0x000C3D, 0x000C4C], [0x000C4E, 0x000CBB], [0x000CBD, 0x000CCC], [0x000CCE, 0x000D3A], @@ -286,13 +309,15 @@ const nonMatchSymbols = buildString({ [0x00106E, 0x001086], [0x001090, 0x001099], [0x00109C, 0x00135C], - [0x001360, 0x0017C8], + [0x001360, 0x001713], + [0x001716, 0x0017C8], [0x0017D4, 0x0017DC], [0x0017DE, 0x001938], [0x00193C, 0x001A74], [0x001A7D, 0x001A7E], [0x001A80, 0x001AAF], - [0x001ABE, 0x001B33], + [0x001ABF, 0x001AC0], + [0x001ACC, 0x001B33], [0x001B35, 0x001B43], [0x001B45, 0x001B6A], [0x001B74, 0x001BA9], @@ -305,7 +330,6 @@ const nonMatchSymbols = buildString({ [0x001CFA, 0x001D2B], [0x001D6B, 0x001DC3], [0x001DD0, 0x001DF4], - [0x001DFA, 0x001DFC], [0x001E00, 0x001FBC], [0x001FC2, 0x001FCC], [0x001FD0, 0x001FDC], @@ -344,10 +368,14 @@ const nonMatchSymbols = buildString({ [0x00FF71, 0x00FF9D], [0x00FFA0, 0x00FFE2], [0x00FFE4, 0x0102DF], - [0x0102E1, 0x010AE4], + [0x0102E1, 0x01077F], + [0x0107BB, 0x010AE4], [0x010AE7, 0x010D21], [0x010D28, 0x010F45], - [0x010F51, 0x0110B8], + [0x010F51, 0x010F81], + [0x010F86, 0x011045], + [0x011047, 0x01106F], + [0x011071, 0x0110B8], [0x0110BB, 0x011132], [0x011135, 0x011172], [0x011174, 0x0111BF], @@ -379,13 +407,17 @@ const nonMatchSymbols = buildString({ [0x016AF5, 0x016B2F], [0x016B37, 0x016F8E], [0x016FA0, 0x016FEF], - [0x016FF2, 0x01D166], + [0x016FF2, 0x01AFEF], + [0x01AFFF, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D166], [0x01D16A, 0x01D16C], [0x01D173, 0x01D17A], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], [0x01D1AE, 0x01E12F], - [0x01E137, 0x01E2EB], + [0x01E137, 0x01E2AD], + [0x01E2AF, 0x01E2EB], [0x01E2F0, 0x01E8CF], [0x01E8D7, 0x01E943], [0x01E94B, 0x10FFFF] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji.js index 0bf6f9f8ec08..cf62b5652fd9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Emoji` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -83,7 +83,8 @@ const matchSymbols = buildString({ 0x01F5EF, 0x01F5F3, 0x01F6E9, - 0x01F6F0 + 0x01F6F0, + 0x01F7F0 ], ranges: [ [0x000030, 0x000039], @@ -153,22 +154,22 @@ const matchSymbols = buildString({ [0x01F680, 0x01F6C5], [0x01F6CB, 0x01F6D2], [0x01F6D5, 0x01F6D7], - [0x01F6E0, 0x01F6E5], + [0x01F6DD, 0x01F6E5], [0x01F6EB, 0x01F6EC], [0x01F6F3, 0x01F6FC], [0x01F7E0, 0x01F7EB], [0x01F90C, 0x01F93A], [0x01F93C, 0x01F945], - [0x01F947, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01F9FF], + [0x01F947, 0x01F9FF], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6] + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6] ] }); testPropertyEscapes( @@ -203,9 +204,7 @@ const nonMatchSymbols = buildString({ 0x01F5E2, 0x01F6EA, 0x01F93B, - 0x01F946, - 0x01F979, - 0x01F9CC + 0x01F946 ], ranges: [ [0x00DC00, 0x00DFFF], @@ -322,20 +321,23 @@ const nonMatchSymbols = buildString({ [0x01F650, 0x01F67F], [0x01F6C6, 0x01F6CA], [0x01F6D3, 0x01F6D4], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6E6, 0x01F6E8], [0x01F6ED, 0x01F6EF], [0x01F6F1, 0x01F6F2], [0x01F6FD, 0x01F7DF], - [0x01F7EC, 0x01F90B], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F90B], [0x01FA00, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x10FFFF] + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Component.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Component.js index a10b3037b40f..5362365cb516 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Component.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Component.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Emoji_Component` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier.js index 6b6cd916ba00..07bde0bd6dd7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Emoji_Modifier` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier_Base.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier_Base.js index 203f6ef8e0d9..727eb4beca67 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier_Base.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier_Base.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Emoji_Modifier_Base` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -54,7 +54,9 @@ const matchSymbols = buildString({ [0x01F9B5, 0x01F9B6], [0x01F9B8, 0x01F9B9], [0x01F9CD, 0x01F9CF], - [0x01F9D1, 0x01F9DD] + [0x01F9D1, 0x01F9DD], + [0x01FAC3, 0x01FAC5], + [0x01FAF0, 0x01FAF6] ] }); testPropertyEscapes( @@ -112,7 +114,9 @@ const nonMatchSymbols = buildString({ [0x01F93F, 0x01F976], [0x01F978, 0x01F9B4], [0x01F9BC, 0x01F9CC], - [0x01F9DE, 0x10FFFF] + [0x01F9DE, 0x01FAC2], + [0x01FAC6, 0x01FAEF], + [0x01FAF7, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Presentation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Presentation.js index b1c14220e452..9f3778ae5b8e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Presentation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Presentation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Emoji_Presentation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -45,7 +45,8 @@ const matchSymbols = buildString({ 0x01F440, 0x01F57A, 0x01F5A4, - 0x01F6CC + 0x01F6CC, + 0x01F7F0 ], ranges: [ [0x00231A, 0x00231B], @@ -83,21 +84,22 @@ const matchSymbols = buildString({ [0x01F680, 0x01F6C5], [0x01F6D0, 0x01F6D2], [0x01F6D5, 0x01F6D7], + [0x01F6DD, 0x01F6DF], [0x01F6EB, 0x01F6EC], [0x01F6F4, 0x01F6FC], [0x01F7E0, 0x01F7EB], [0x01F90C, 0x01F93A], [0x01F93C, 0x01F945], - [0x01F947, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01F9FF], + [0x01F947, 0x01F9FF], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6] + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6] ] }); testPropertyEscapes( @@ -124,9 +126,7 @@ const nonMatchSymbols = buildString({ 0x01F441, 0x01F54F, 0x01F93B, - 0x01F946, - 0x01F979, - 0x01F9CC + 0x01F946 ], ranges: [ [0x00DC00, 0x00DFFF], @@ -187,18 +187,22 @@ const nonMatchSymbols = buildString({ [0x01F6C6, 0x01F6CB], [0x01F6CD, 0x01F6CF], [0x01F6D3, 0x01F6D4], - [0x01F6D8, 0x01F6EA], + [0x01F6D8, 0x01F6DC], + [0x01F6E0, 0x01F6EA], [0x01F6ED, 0x01F6F3], [0x01F6FD, 0x01F7DF], - [0x01F7EC, 0x01F90B], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F90B], [0x01FA00, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x10FFFF] + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extended_Pictographic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extended_Pictographic.js index f004987a6150..ee0fb2c88f3a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extended_Pictographic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extended_Pictographic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Extended_Pictographic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extender.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extender.js index 8aefb5fb198f..d58cefab1f33 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extender.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extender.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Extender` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -44,6 +44,7 @@ const matchSymbols = buildString({ [0x00309D, 0x00309E], [0x0030FC, 0x0030FE], [0x00AAF3, 0x00AAF4], + [0x010781, 0x010782], [0x0115C6, 0x0115C8], [0x016B42, 0x016B43], [0x016FE0, 0x016FE1], @@ -93,7 +94,8 @@ const nonMatchSymbols = buildString({ [0x00AADE, 0x00AAF2], [0x00AAF5, 0x00DBFF], [0x00E000, 0x00FF6F], - [0x00FF71, 0x01135C], + [0x00FF71, 0x010780], + [0x010783, 0x01135C], [0x01135E, 0x0115C5], [0x0115C9, 0x011A97], [0x011A99, 0x016B41], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Cased_Letter.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Cased_Letter.js index e0c098f7ca2a..ba4a4034769f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Cased_Letter.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Cased_Letter.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Cased_Letter` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -35,6 +35,7 @@ const matchSymbols = buildString({ 0x00214E, 0x002D27, 0x002D2D, + 0x00A7D3, 0x00A7FA, 0x01D4A2, 0x01D4BB, @@ -92,9 +93,7 @@ const matchSymbols = buildString({ [0x00213C, 0x00213F], [0x002145, 0x002149], [0x002183, 0x002184], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002C7B], + [0x002C00, 0x002C7B], [0x002C7E, 0x002CE4], [0x002CEB, 0x002CEE], [0x002CF2, 0x002CF3], @@ -104,8 +103,9 @@ const matchSymbols = buildString({ [0x00A722, 0x00A76F], [0x00A771, 0x00A787], [0x00A78B, 0x00A78E], - [0x00A790, 0x00A7BF], - [0x00A7C2, 0x00A7CA], + [0x00A790, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], [0x00A7F5, 0x00A7F6], [0x00AB30, 0x00AB5A], [0x00AB60, 0x00AB68], @@ -117,6 +117,14 @@ const matchSymbols = buildString({ [0x010400, 0x01044F], [0x0104B0, 0x0104D3], [0x0104D8, 0x0104FB], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010C80, 0x010CB2], [0x010CC0, 0x010CF2], [0x0118A0, 0x0118DF], @@ -148,6 +156,8 @@ const matchSymbols = buildString({ [0x01D78A, 0x01D7A8], [0x01D7AA, 0x01D7C2], [0x01D7C4, 0x01D7CB], + [0x01DF00, 0x01DF09], + [0x01DF0B, 0x01DF1E], [0x01E900, 0x01E943] ] }); @@ -210,11 +220,18 @@ const nonMatchSymbols = buildString({ 0x002127, 0x002129, 0x00212E, - 0x002C2F, - 0x002C5F, 0x002D26, 0x00A770, 0x00A78F, + 0x00A7D2, + 0x00A7D4, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, 0x01D455, 0x01D49D, 0x01D4AD, @@ -237,7 +254,8 @@ const nonMatchSymbols = buildString({ 0x01D76F, 0x01D789, 0x01D7A9, - 0x01D7C3 + 0x01D7C3, + 0x01DF0A ], ranges: [ [0x00DC00, 0x00DFFF], @@ -294,8 +312,8 @@ const nonMatchSymbols = buildString({ [0x00A66E, 0x00A67F], [0x00A69C, 0x00A721], [0x00A788, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F4], [0x00A7F7, 0x00A7F9], [0x00A7FB, 0x00AB2F], [0x00AB5B, 0x00AB5F], @@ -308,7 +326,8 @@ const nonMatchSymbols = buildString({ [0x00FF5B, 0x0103FF], [0x010450, 0x0104AF], [0x0104D4, 0x0104D7], - [0x0104FC, 0x010C7F], + [0x0104FC, 0x01056F], + [0x0105BD, 0x010C7F], [0x010CB3, 0x010CBF], [0x010CF3, 0x01189F], [0x0118E0, 0x016E3F], @@ -319,7 +338,8 @@ const nonMatchSymbols = buildString({ [0x01D50B, 0x01D50C], [0x01D547, 0x01D549], [0x01D6A6, 0x01D6A7], - [0x01D7CC, 0x01E8FF], + [0x01D7CC, 0x01DEFF], + [0x01DF1F, 0x01E8FF], [0x01E944, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Close_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Close_Punctuation.js index 5904aada1719..f5698036bef7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Close_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Close_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Close_Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -58,6 +58,10 @@ const matchSymbols = buildString({ 0x002E25, 0x002E27, 0x002E29, + 0x002E56, + 0x002E58, + 0x002E5A, + 0x002E5C, 0x003009, 0x00300B, 0x00300D, @@ -150,6 +154,9 @@ const nonMatchSymbols = buildString({ 0x002E24, 0x002E26, 0x002E28, + 0x002E57, + 0x002E59, + 0x002E5B, 0x00300A, 0x00300C, 0x00300E, @@ -186,7 +193,8 @@ const nonMatchSymbols = buildString({ [0x002999, 0x0029D8], [0x0029DC, 0x0029FC], [0x0029FE, 0x002E22], - [0x002E2A, 0x003008], + [0x002E2A, 0x002E55], + [0x002E5D, 0x003008], [0x003012, 0x003014], [0x00301C, 0x00301D], [0x003020, 0x00DBFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Connector_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Connector_Punctuation.js index 8967644bcc59..1f16b08868d8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Connector_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Connector_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Connector_Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Control.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Control.js index cc3814a0a5f5..b6bfe13a052a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Control.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Control.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Control` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Currency_Symbol.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Currency_Symbol.js index 67ea74b66ec0..37095252c1f6 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Currency_Symbol.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Currency_Symbol.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Currency_Symbol` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -34,7 +34,7 @@ const matchSymbols = buildString({ [0x0000A2, 0x0000A5], [0x0007FE, 0x0007FF], [0x0009F2, 0x0009F3], - [0x0020A0, 0x0020BF], + [0x0020A0, 0x0020C0], [0x00FFE0, 0x00FFE1], [0x00FFE5, 0x00FFE6], [0x011FDD, 0x011FE0] @@ -87,7 +87,7 @@ const nonMatchSymbols = buildString({ [0x000BFA, 0x000E3E], [0x000E40, 0x0017DA], [0x0017DC, 0x00209F], - [0x0020C0, 0x00A837], + [0x0020C1, 0x00A837], [0x00A839, 0x00DBFF], [0x00E000, 0x00FDFB], [0x00FDFD, 0x00FE68], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Dash_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Dash_Punctuation.js index e8b4990b6dd1..d6b7c780ecea 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Dash_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Dash_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Dash_Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -23,6 +23,7 @@ const matchSymbols = buildString({ 0x002E17, 0x002E1A, 0x002E40, + 0x002E5D, 0x00301C, 0x003030, 0x0030A0, @@ -82,7 +83,8 @@ const nonMatchSymbols = buildString({ [0x002E18, 0x002E19], [0x002E1B, 0x002E39], [0x002E3C, 0x002E3F], - [0x002E41, 0x00301B], + [0x002E41, 0x002E5C], + [0x002E5E, 0x00301B], [0x00301D, 0x00302F], [0x003031, 0x00309F], [0x0030A1, 0x00DBFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js index 754cf2307c05..27cf4db6dd60 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Decimal_Number` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -71,6 +71,7 @@ const matchSymbols = buildString({ [0x011D50, 0x011D59], [0x011DA0, 0x011DA9], [0x016A60, 0x016A69], + [0x016AC0, 0x016AC9], [0x016B50, 0x016B59], [0x01D7CE, 0x01D7FF], [0x01E140, 0x01E149], @@ -185,7 +186,8 @@ const nonMatchSymbols = buildString({ [0x011C5A, 0x011D4F], [0x011D5A, 0x011D9F], [0x011DAA, 0x016A5F], - [0x016A6A, 0x016B4F], + [0x016A6A, 0x016ABF], + [0x016ACA, 0x016B4F], [0x016B5A, 0x01D7CD], [0x01D800, 0x01E13F], [0x01E14A, 0x01E2EF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Enclosing_Mark.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Enclosing_Mark.js index 3939e8081518..33f0a331fb7d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Enclosing_Mark.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Enclosing_Mark.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Enclosing_Mark` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Final_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Final_Punctuation.js index e137c3a41044..3e7e51a1d1c7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Final_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Final_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Final_Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Format.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Format.js index b3e3cfdfadfa..89a4c3916dac 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Format.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Format.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Format` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -28,6 +28,7 @@ const matchSymbols = buildString({ ], ranges: [ [0x000600, 0x000605], + [0x000890, 0x000891], [0x00200B, 0x00200F], [0x00202A, 0x00202E], [0x002060, 0x002064], @@ -81,7 +82,8 @@ const nonMatchSymbols = buildString({ [0x000606, 0x00061B], [0x00061D, 0x0006DC], [0x0006DE, 0x00070E], - [0x000710, 0x0008E1], + [0x000710, 0x00088F], + [0x000892, 0x0008E1], [0x0008E3, 0x00180D], [0x00180F, 0x00200A], [0x002010, 0x002029], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Initial_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Initial_Punctuation.js index 044a6764609b..1c079b17a01b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Initial_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Initial_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Initial_Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter.js index b67f9739dc76..0cd495b27765 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Letter` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -48,9 +48,9 @@ const matchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000C3D, + 0x000C5D, 0x000C80, 0x000CBD, - 0x000CDE, 0x000D3D, 0x000D4E, 0x000DBD, @@ -88,6 +88,7 @@ const matchSymbols = buildString({ 0x002D2D, 0x002D6F, 0x002E2F, + 0x00A7D3, 0x00A8FB, 0x00A9CF, 0x00AA7A, @@ -100,6 +101,7 @@ const matchSymbols = buildString({ 0x01083C, 0x010A00, 0x010F27, + 0x011075, 0x011144, 0x011147, 0x011176, @@ -181,8 +183,9 @@ const matchSymbols = buildString({ [0x000800, 0x000815], [0x000840, 0x000858], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], + [0x000870, 0x000887], + [0x000889, 0x00088E], + [0x0008A0, 0x0008C9], [0x000904, 0x000939], [0x000958, 0x000961], [0x000971, 0x000980], @@ -237,6 +240,7 @@ const matchSymbols = buildString({ [0x000C92, 0x000CA8], [0x000CAA, 0x000CB3], [0x000CB5, 0x000CB9], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE1], [0x000CF1, 0x000CF2], [0x000D04, 0x000D0C], @@ -292,9 +296,8 @@ const matchSymbols = buildString({ [0x001681, 0x00169A], [0x0016A0, 0x0016EA], [0x0016F1, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001711], - [0x001720, 0x001731], + [0x001700, 0x001711], + [0x00171F, 0x001731], [0x001740, 0x001751], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -311,7 +314,7 @@ const matchSymbols = buildString({ [0x001A00, 0x001A16], [0x001A20, 0x001A54], [0x001B05, 0x001B33], - [0x001B45, 0x001B4B], + [0x001B45, 0x001B4C], [0x001B83, 0x001BA0], [0x001BAE, 0x001BAF], [0x001BBA, 0x001BE5], @@ -348,9 +351,7 @@ const matchSymbols = buildString({ [0x00213C, 0x00213F], [0x002145, 0x002149], [0x002183, 0x002184], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CE4], + [0x002C00, 0x002CE4], [0x002CEB, 0x002CEE], [0x002CF2, 0x002CF3], [0x002D00, 0x002D25], @@ -376,8 +377,7 @@ const matchSymbols = buildString({ [0x0031A0, 0x0031BF], [0x0031F0, 0x0031FF], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], - [0x00A000, 0x00A48C], + [0x004E00, 0x00A48C], [0x00A4D0, 0x00A4FD], [0x00A500, 0x00A60C], [0x00A610, 0x00A61F], @@ -387,9 +387,10 @@ const matchSymbols = buildString({ [0x00A6A0, 0x00A6E5], [0x00A717, 0x00A71F], [0x00A722, 0x00A788], - [0x00A78B, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A801], + [0x00A78B, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A801], [0x00A803, 0x00A805], [0x00A807, 0x00A80A], [0x00A80C, 0x00A822], @@ -469,9 +470,20 @@ const matchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -503,9 +515,11 @@ const matchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F1C], [0x010F30, 0x010F45], + [0x010F70, 0x010F81], [0x010FB0, 0x010FC4], [0x010FE0, 0x010FF6], [0x011003, 0x011037], + [0x011071, 0x011072], [0x011083, 0x0110AF], [0x0110D0, 0x0110E8], [0x011103, 0x011126], @@ -536,6 +550,7 @@ const matchSymbols = buildString({ [0x011600, 0x01162F], [0x011680, 0x0116AA], [0x011700, 0x01171A], + [0x011740, 0x011746], [0x011800, 0x01182B], [0x0118A0, 0x0118DF], [0x0118FF, 0x011906], @@ -546,7 +561,7 @@ const matchSymbols = buildString({ [0x0119AA, 0x0119D0], [0x011A0B, 0x011A32], [0x011A5C, 0x011A89], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C2E], [0x011C72, 0x011C8F], @@ -559,10 +574,12 @@ const matchSymbols = buildString({ [0x011EE0, 0x011EF2], [0x012000, 0x012399], [0x012480, 0x012543], + [0x012F90, 0x012FF0], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], + [0x016A70, 0x016ABE], [0x016AD0, 0x016AED], [0x016B00, 0x016B2F], [0x016B40, 0x016B43], @@ -575,7 +592,10 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -610,9 +630,15 @@ const matchSymbols = buildString({ [0x01D78A, 0x01D7A8], [0x01D7AA, 0x01D7C2], [0x01D7C4, 0x01D7CB], + [0x01DF00, 0x01DF1E], [0x01E100, 0x01E12C], [0x01E137, 0x01E13D], + [0x01E290, 0x01E2AD], [0x01E2C0, 0x01E2EB], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E900, 0x01E943], [0x01EE00, 0x01EE03], @@ -632,8 +658,8 @@ const matchSymbols = buildString({ [0x01EEA1, 0x01EEA3], [0x01EEA5, 0x01EEA9], [0x01EEAB, 0x01EEBB], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -688,7 +714,7 @@ const nonMatchSymbols = buildString({ 0x000670, 0x0006D4, 0x000711, - 0x0008B5, + 0x000888, 0x0009A9, 0x0009B1, 0x0009DE, @@ -743,7 +769,6 @@ const nonMatchSymbols = buildString({ 0x0012D7, 0x001311, 0x001680, - 0x00170D, 0x00176D, 0x0018A9, 0x001CED, @@ -761,8 +786,6 @@ const nonMatchSymbols = buildString({ 0x002127, 0x002129, 0x00212E, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -774,6 +797,8 @@ const nonMatchSymbols = buildString({ 0x0030A0, 0x0030FB, 0x003130, + 0x00A7D2, + 0x00A7D4, 0x00A802, 0x00A806, 0x00A80B, @@ -799,6 +824,15 @@ const nonMatchSymbols = buildString({ 0x01003B, 0x01003E, 0x010341, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x0108F3, @@ -825,6 +859,9 @@ const nonMatchSymbols = buildString({ 0x011D66, 0x011D69, 0x016FE2, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -848,6 +885,10 @@ const nonMatchSymbols = buildString({ 0x01D789, 0x01D7A9, 0x01D7C3, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -912,8 +953,9 @@ const nonMatchSymbols = buildString({ [0x000825, 0x000827], [0x000829, 0x00083F], [0x000859, 0x00085F], - [0x00086B, 0x00089F], - [0x0008C8, 0x000903], + [0x00086B, 0x00086F], + [0x00088F, 0x00089F], + [0x0008CA, 0x000903], [0x00093A, 0x00093C], [0x00093E, 0x00094F], [0x000951, 0x000957], @@ -953,11 +995,12 @@ const nonMatchSymbols = buildString({ [0x000BD1, 0x000C04], [0x000C3A, 0x000C3C], [0x000C3E, 0x000C57], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C62, 0x000C7F], [0x000C81, 0x000C84], [0x000CBA, 0x000CBC], - [0x000CBE, 0x000CDD], + [0x000CBE, 0x000CDC], [0x000CE2, 0x000CF0], [0x000CF3, 0x000D03], [0x000D3B, 0x000D3C], @@ -1003,7 +1046,7 @@ const nonMatchSymbols = buildString({ [0x00169B, 0x00169F], [0x0016EB, 0x0016F0], [0x0016F9, 0x0016FF], - [0x001712, 0x00171F], + [0x001712, 0x00171E], [0x001732, 0x00173F], [0x001752, 0x00175F], [0x001771, 0x00177F], @@ -1023,7 +1066,7 @@ const nonMatchSymbols = buildString({ [0x001A55, 0x001AA6], [0x001AA8, 0x001B04], [0x001B34, 0x001B44], - [0x001B4C, 0x001B82], + [0x001B4D, 0x001B82], [0x001BA1, 0x001BAD], [0x001BB0, 0x001BB9], [0x001BE6, 0x001BFF], @@ -1078,7 +1121,6 @@ const nonMatchSymbols = buildString({ [0x0031C0, 0x0031EF], [0x003200, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A4CF], [0x00A4FE, 0x00A4FF], [0x00A60D, 0x00A60F], @@ -1089,8 +1131,8 @@ const nonMatchSymbols = buildString({ [0x00A6E6, 0x00A716], [0x00A720, 0x00A721], [0x00A789, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A823, 0x00A83F], [0x00A874, 0x00A881], [0x00A8B4, 0x00A8F1], @@ -1154,10 +1196,12 @@ const nonMatchSymbols = buildString({ [0x0104D4, 0x0104D7], [0x0104FC, 0x0104FF], [0x010528, 0x01052F], - [0x010564, 0x0105FF], + [0x010564, 0x01056F], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -1186,10 +1230,13 @@ const nonMatchSymbols = buildString({ [0x010EB2, 0x010EFF], [0x010F1D, 0x010F26], [0x010F28, 0x010F2F], - [0x010F46, 0x010FAF], + [0x010F46, 0x010F6F], + [0x010F82, 0x010FAF], [0x010FC5, 0x010FDF], [0x010FF7, 0x011002], - [0x011038, 0x011082], + [0x011038, 0x011070], + [0x011073, 0x011074], + [0x011076, 0x011082], [0x0110B0, 0x0110CF], [0x0110E9, 0x011102], [0x011127, 0x011143], @@ -1220,7 +1267,8 @@ const nonMatchSymbols = buildString({ [0x011645, 0x01167F], [0x0116AB, 0x0116B7], [0x0116B9, 0x0116FF], - [0x01171B, 0x0117FF], + [0x01171B, 0x01173F], + [0x011747, 0x0117FF], [0x01182C, 0x01189F], [0x0118E0, 0x0118FE], [0x011907, 0x011908], @@ -1235,7 +1283,7 @@ const nonMatchSymbols = buildString({ [0x011A3B, 0x011A4F], [0x011A51, 0x011A5B], [0x011A8A, 0x011A9C], - [0x011A9E, 0x011ABF], + [0x011A9E, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C2F, 0x011C3F], [0x011C41, 0x011C71], @@ -1247,11 +1295,13 @@ const nonMatchSymbols = buildString({ [0x011EF3, 0x011FAF], [0x011FB1, 0x011FFF], [0x01239A, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF1, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], - [0x016A5F, 0x016ACF], + [0x016A5F, 0x016A6F], + [0x016ABF, 0x016ACF], [0x016AEE, 0x016AFF], [0x016B30, 0x016B3F], [0x016B44, 0x016B62], @@ -1264,8 +1314,8 @@ const nonMatchSymbols = buildString({ [0x016FE4, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -1279,11 +1329,13 @@ const nonMatchSymbols = buildString({ [0x01D50B, 0x01D50C], [0x01D547, 0x01D549], [0x01D6A6, 0x01D6A7], - [0x01D7CC, 0x01E0FF], + [0x01D7CC, 0x01DEFF], + [0x01DF1F, 0x01E0FF], [0x01E12D, 0x01E136], [0x01E13E, 0x01E14D], - [0x01E14F, 0x01E2BF], - [0x01E2EC, 0x01E7FF], + [0x01E14F, 0x01E28F], + [0x01E2AE, 0x01E2BF], + [0x01E2EC, 0x01E7DF], [0x01E8C5, 0x01E8FF], [0x01E944, 0x01E94A], [0x01E94C, 0x01EDFF], @@ -1294,8 +1346,8 @@ const nonMatchSymbols = buildString({ [0x01EE65, 0x01EE66], [0x01EE9C, 0x01EEA0], [0x01EEBC, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter_Number.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter_Number.js index 4e6bd8a64e2b..bfc9c1ce172e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter_Number.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter_Number.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Letter_Number` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Line_Separator.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Line_Separator.js index 949bda0d32f1..2e2fc4e96623 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Line_Separator.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Line_Separator.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Line_Separator` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Lowercase_Letter.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Lowercase_Letter.js index ac581b90c73a..f93419c5d8dd 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Lowercase_Letter.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Lowercase_Letter.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Lowercase_Letter` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -549,9 +549,15 @@ const matchSymbols = buildString({ 0x00A7BB, 0x00A7BD, 0x00A7BF, + 0x00A7C1, 0x00A7C3, 0x00A7C8, 0x00A7CA, + 0x00A7D1, + 0x00A7D3, + 0x00A7D5, + 0x00A7D7, + 0x00A7D9, 0x00A7F6, 0x00A7FA, 0x01D4BB, @@ -615,7 +621,7 @@ const matchSymbols = buildString({ [0x00210E, 0x00210F], [0x00213C, 0x00213D], [0x002146, 0x002149], - [0x002C30, 0x002C5E], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002C73, 0x002C74], [0x002C76, 0x002C7B], @@ -632,6 +638,10 @@ const matchSymbols = buildString({ [0x00FF41, 0x00FF5A], [0x010428, 0x01044F], [0x0104D8, 0x0104FB], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010CC0, 0x010CF2], [0x0118C0, 0x0118DF], [0x016E60, 0x016E7F], @@ -661,6 +671,8 @@ const matchSymbols = buildString({ [0x01D78A, 0x01D78F], [0x01D7AA, 0x01D7C2], [0x01D7C4, 0x01D7C9], + [0x01DF00, 0x01DF09], + [0x01DF0B, 0x01DF1E], [0x01E922, 0x01E943] ] }); @@ -1057,6 +1069,7 @@ const nonMatchSymbols = buildString({ 0x001FB5, 0x001FC5, 0x001FF5, + 0x002C60, 0x002C67, 0x002C69, 0x002C6B, @@ -1209,7 +1222,16 @@ const nonMatchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, + 0x00A7C0, + 0x00A7C2, 0x00A7C9, + 0x00A7D2, + 0x00A7D4, + 0x00A7D6, + 0x00A7D8, + 0x0105A2, + 0x0105B2, + 0x0105BA, 0x01D455, 0x01D4BA, 0x01D4BC, @@ -1219,7 +1241,8 @@ const nonMatchSymbols = buildString({ 0x01D74F, 0x01D789, 0x01D7C3, - 0x01D7CA + 0x01D7CA, + 0x01DF0A ], ranges: [ [0x00DC00, 0x00DFFF], @@ -1295,7 +1318,6 @@ const nonMatchSymbols = buildString({ [0x00214A, 0x00214D], [0x00214F, 0x002183], [0x002185, 0x002C2F], - [0x002C5F, 0x002C60], [0x002C62, 0x002C64], [0x002C6D, 0x002C70], [0x002C7C, 0x002C80], @@ -1311,9 +1333,9 @@ const nonMatchSymbols = buildString({ [0x00A78F, 0x00A790], [0x00A7AA, 0x00A7AE], [0x00A7B0, 0x00A7B4], - [0x00A7C0, 0x00A7C2], [0x00A7C4, 0x00A7C7], - [0x00A7CB, 0x00A7F5], + [0x00A7CB, 0x00A7D0], + [0x00A7DA, 0x00A7F5], [0x00A7F7, 0x00A7F9], [0x00A7FB, 0x00AB2F], [0x00AB5B, 0x00AB5F], @@ -1324,7 +1346,8 @@ const nonMatchSymbols = buildString({ [0x00FB18, 0x00FF40], [0x00FF5B, 0x010427], [0x010450, 0x0104D7], - [0x0104FC, 0x010CBF], + [0x0104FC, 0x010596], + [0x0105BD, 0x010CBF], [0x010CF3, 0x0118BF], [0x0118E0, 0x016E5F], [0x016E80, 0x01D419], @@ -1345,7 +1368,8 @@ const nonMatchSymbols = buildString({ [0x01D71C, 0x01D735], [0x01D756, 0x01D76F], [0x01D790, 0x01D7A9], - [0x01D7CC, 0x01E921], + [0x01D7CC, 0x01DEFF], + [0x01DF1F, 0x01E921], [0x01E944, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Mark.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Mark.js index 3086dc263271..1a1d7e401a01 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Mark.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Mark.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Mark` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -30,6 +30,7 @@ const matchSymbols = buildString({ 0x000B3C, 0x000B82, 0x000BD7, + 0x000C3C, 0x000CBC, 0x000D57, 0x000DCA, @@ -42,6 +43,7 @@ const matchSymbols = buildString({ 0x000FC6, 0x00108F, 0x0017DD, + 0x00180F, 0x0018A9, 0x001A7F, 0x001CED, @@ -60,6 +62,8 @@ const matchSymbols = buildString({ 0x0101FD, 0x0102E0, 0x010A3F, + 0x011070, + 0x0110C2, 0x011173, 0x01123E, 0x011357, @@ -72,7 +76,8 @@ const matchSymbols = buildString({ 0x016F4F, 0x016FE4, 0x01DA75, - 0x01DA84 + 0x01DA84, + 0x01E2AE ], ranges: [ [0x000300, 0x00036F], @@ -94,7 +99,8 @@ const matchSymbols = buildString({ [0x000825, 0x000827], [0x000829, 0x00082D], [0x000859, 0x00085B], - [0x0008D3, 0x0008E1], + [0x000898, 0x00089F], + [0x0008CA, 0x0008E1], [0x0008E3, 0x000903], [0x00093A, 0x00093C], [0x00093E, 0x00094F], @@ -166,7 +172,7 @@ const matchSymbols = buildString({ [0x001082, 0x00108D], [0x00109A, 0x00109D], [0x00135D, 0x00135F], - [0x001712, 0x001714], + [0x001712, 0x001715], [0x001732, 0x001734], [0x001752, 0x001753], [0x001772, 0x001773], @@ -178,7 +184,7 @@ const matchSymbols = buildString({ [0x001A17, 0x001A1B], [0x001A55, 0x001A5E], [0x001A60, 0x001A7C], - [0x001AB0, 0x001AC0], + [0x001AB0, 0x001ACE], [0x001B00, 0x001B04], [0x001B34, 0x001B44], [0x001B6B, 0x001B73], @@ -189,8 +195,7 @@ const matchSymbols = buildString({ [0x001CD0, 0x001CD2], [0x001CD4, 0x001CE8], [0x001CF7, 0x001CF9], - [0x001DC0, 0x001DF9], - [0x001DFB, 0x001DFF], + [0x001DC0, 0x001DFF], [0x0020D0, 0x0020F0], [0x002CEF, 0x002CF1], [0x002DE0, 0x002DFF], @@ -229,8 +234,10 @@ const matchSymbols = buildString({ [0x010D24, 0x010D27], [0x010EAB, 0x010EAC], [0x010F46, 0x010F50], + [0x010F82, 0x010F85], [0x011000, 0x011002], [0x011038, 0x011046], + [0x011073, 0x011074], [0x01107F, 0x011082], [0x0110B0, 0x0110BA], [0x011100, 0x011102], @@ -287,6 +294,8 @@ const matchSymbols = buildString({ [0x016F8F, 0x016F92], [0x016FF0, 0x016FF1], [0x01BC9D, 0x01BC9E], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D165, 0x01D169], [0x01D16D, 0x01D172], [0x01D17B, 0x01D182], @@ -376,6 +385,7 @@ const nonMatchSymbols = buildString({ 0x000B00, 0x000B3D, 0x000BC9, + 0x000C3D, 0x000C45, 0x000C49, 0x000CBD, @@ -392,9 +402,9 @@ const nonMatchSymbols = buildString({ 0x000F98, 0x001061, 0x00108E, + 0x00180E, 0x001A5F, 0x001CD3, - 0x001DFA, 0x00A673, 0x00AAB1, 0x00AAC0, @@ -437,7 +447,8 @@ const nonMatchSymbols = buildString({ [0x0007F4, 0x0007FC], [0x0007FE, 0x000815], [0x00082E, 0x000858], - [0x00085C, 0x0008D2], + [0x00085C, 0x000897], + [0x0008A0, 0x0008C9], [0x000904, 0x000939], [0x000958, 0x000961], [0x000964, 0x000980], @@ -468,7 +479,7 @@ const nonMatchSymbols = buildString({ [0x000BC3, 0x000BC5], [0x000BCE, 0x000BD6], [0x000BD8, 0x000BFF], - [0x000C05, 0x000C3D], + [0x000C05, 0x000C3B], [0x000C4E, 0x000C54], [0x000C57, 0x000C61], [0x000C64, 0x000C80], @@ -504,13 +515,13 @@ const nonMatchSymbols = buildString({ [0x001090, 0x001099], [0x00109E, 0x00135C], [0x001360, 0x001711], - [0x001715, 0x001731], + [0x001716, 0x001731], [0x001735, 0x001751], [0x001754, 0x001771], [0x001774, 0x0017B3], [0x0017D4, 0x0017DC], [0x0017DE, 0x00180A], - [0x00180E, 0x001884], + [0x001810, 0x001884], [0x001887, 0x0018A8], [0x0018AA, 0x00191F], [0x00192C, 0x00192F], @@ -518,7 +529,7 @@ const nonMatchSymbols = buildString({ [0x001A1C, 0x001A54], [0x001A7D, 0x001A7E], [0x001A80, 0x001AAF], - [0x001AC1, 0x001AFF], + [0x001ACF, 0x001AFF], [0x001B05, 0x001B33], [0x001B45, 0x001B6A], [0x001B74, 0x001B7F], @@ -578,11 +589,15 @@ const nonMatchSymbols = buildString({ [0x010AE7, 0x010D23], [0x010D28, 0x010EAA], [0x010EAD, 0x010F45], - [0x010F51, 0x010FFF], + [0x010F51, 0x010F81], + [0x010F86, 0x010FFF], [0x011003, 0x011037], - [0x011047, 0x01107E], + [0x011047, 0x01106F], + [0x011071, 0x011072], + [0x011075, 0x01107E], [0x011083, 0x0110AF], - [0x0110BB, 0x0110FF], + [0x0110BB, 0x0110C1], + [0x0110C3, 0x0110FF], [0x011103, 0x011126], [0x011135, 0x011144], [0x011147, 0x011172], @@ -633,7 +648,9 @@ const nonMatchSymbols = buildString({ [0x016F93, 0x016FE3], [0x016FE5, 0x016FEF], [0x016FF2, 0x01BC9C], - [0x01BC9F, 0x01D164], + [0x01BC9F, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D164], [0x01D16A, 0x01D16C], [0x01D173, 0x01D17A], [0x01D183, 0x01D184], @@ -647,7 +664,8 @@ const nonMatchSymbols = buildString({ [0x01DAB0, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E12F], - [0x01E137, 0x01E2EB], + [0x01E137, 0x01E2AD], + [0x01E2AF, 0x01E2EB], [0x01E2F0, 0x01E8CF], [0x01E8D7, 0x01E943], [0x01E94B, 0x0E00FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Math_Symbol.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Math_Symbol.js index bb3623568c06..2d1c941fc203 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Math_Symbol.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Math_Symbol.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Math_Symbol` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Letter.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Letter.js index 923722068aa3..321d982de839 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Letter.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Letter.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Modifier_Letter` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -25,6 +25,7 @@ const matchSymbols = buildString({ 0x00081A, 0x000824, 0x000828, + 0x0008C9, 0x000971, 0x000E46, 0x000EC6, @@ -70,13 +71,20 @@ const matchSymbols = buildString({ [0x00A4F8, 0x00A4FD], [0x00A69C, 0x00A69D], [0x00A717, 0x00A71F], + [0x00A7F2, 0x00A7F4], [0x00A7F8, 0x00A7F9], [0x00AAF3, 0x00AAF4], [0x00AB5C, 0x00AB5F], [0x00FF9E, 0x00FF9F], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x016B40, 0x016B43], [0x016F93, 0x016F9F], [0x016FE0, 0x016FE1], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], [0x01E137, 0x01E13D] ] }); @@ -114,7 +122,11 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ 0x0002ED, - 0x016FE2 + 0x010786, + 0x0107B1, + 0x016FE2, + 0x01AFF4, + 0x01AFFC ], ranges: [ [0x00DC00, 0x00DFFF], @@ -132,7 +144,8 @@ const nonMatchSymbols = buildString({ [0x0007FB, 0x000819], [0x00081B, 0x000823], [0x000825, 0x000827], - [0x000829, 0x000970], + [0x000829, 0x0008C8], + [0x0008CA, 0x000970], [0x000972, 0x000E45], [0x000E47, 0x000EC5], [0x000EC7, 0x0010FB], @@ -162,7 +175,8 @@ const nonMatchSymbols = buildString({ [0x00A69E, 0x00A716], [0x00A720, 0x00A76F], [0x00A771, 0x00A787], - [0x00A789, 0x00A7F7], + [0x00A789, 0x00A7F1], + [0x00A7F5, 0x00A7F7], [0x00A7FA, 0x00A9CE], [0x00A9D0, 0x00A9E5], [0x00A9E7, 0x00AA6F], @@ -173,10 +187,12 @@ const nonMatchSymbols = buildString({ [0x00AB6A, 0x00DBFF], [0x00E000, 0x00FF6F], [0x00FF71, 0x00FF9D], - [0x00FFA0, 0x016B3F], + [0x00FFA0, 0x01077F], + [0x0107BB, 0x016B3F], [0x016B44, 0x016F92], [0x016FA0, 0x016FDF], - [0x016FE4, 0x01E136], + [0x016FE4, 0x01AFEF], + [0x01AFFF, 0x01E136], [0x01E13E, 0x01E94A], [0x01E94C, 0x10FFFF] ] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Symbol.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Symbol.js index 778096eebd1f..a7e668aace58 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Symbol.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Symbol.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Modifier_Symbol` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -23,6 +23,7 @@ const matchSymbols = buildString({ 0x0000B8, 0x0002ED, 0x000375, + 0x000888, 0x001FBD, 0x00AB5B, 0x00FF3E, @@ -45,7 +46,7 @@ const matchSymbols = buildString({ [0x00A720, 0x00A721], [0x00A789, 0x00A78A], [0x00AB6A, 0x00AB6B], - [0x00FBB2, 0x00FBC1], + [0x00FBB2, 0x00FBC2], [0x01F3FB, 0x01F3FF] ] }); @@ -100,7 +101,8 @@ const nonMatchSymbols = buildString({ [0x0002E0, 0x0002E4], [0x000300, 0x000374], [0x000376, 0x000383], - [0x000386, 0x001FBC], + [0x000386, 0x000887], + [0x000889, 0x001FBC], [0x001FC2, 0x001FCC], [0x001FD0, 0x001FDC], [0x001FE0, 0x001FEC], @@ -113,7 +115,7 @@ const nonMatchSymbols = buildString({ [0x00AB5C, 0x00AB69], [0x00AB6C, 0x00DBFF], [0x00E000, 0x00FBB1], - [0x00FBC2, 0x00FF3D], + [0x00FBC3, 0x00FF3D], [0x00FF41, 0x00FFE2], [0x00FFE4, 0x01F3FA], [0x01F400, 0x10FFFF] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Nonspacing_Mark.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Nonspacing_Mark.js index ef7458897e1f..1b19793cc083 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Nonspacing_Mark.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Nonspacing_Mark.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Nonspacing_Mark` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -41,6 +41,7 @@ const matchSymbols = buildString({ 0x000BCD, 0x000C00, 0x000C04, + 0x000C3C, 0x000C81, 0x000CBC, 0x000CBF, @@ -60,6 +61,7 @@ const matchSymbols = buildString({ 0x00109D, 0x0017C6, 0x0017DD, + 0x00180F, 0x0018A9, 0x001932, 0x001A1B, @@ -98,6 +100,8 @@ const matchSymbols = buildString({ 0x0102E0, 0x010A3F, 0x011001, + 0x011070, + 0x0110C2, 0x011173, 0x0111CF, 0x011234, @@ -123,7 +127,8 @@ const matchSymbols = buildString({ 0x016F4F, 0x016FE4, 0x01DA75, - 0x01DA84 + 0x01DA84, + 0x01E2AE ], ranges: [ [0x000300, 0x00036F], @@ -145,7 +150,8 @@ const matchSymbols = buildString({ [0x000825, 0x000827], [0x000829, 0x00082D], [0x000859, 0x00085B], - [0x0008D3, 0x0008E1], + [0x000898, 0x00089F], + [0x0008CA, 0x0008E1], [0x0008E3, 0x000902], [0x000941, 0x000948], [0x000951, 0x000957], @@ -197,7 +203,7 @@ const matchSymbols = buildString({ [0x001085, 0x001086], [0x00135D, 0x00135F], [0x001712, 0x001714], - [0x001732, 0x001734], + [0x001732, 0x001733], [0x001752, 0x001753], [0x001772, 0x001773], [0x0017B4, 0x0017B5], @@ -213,7 +219,7 @@ const matchSymbols = buildString({ [0x001A65, 0x001A6C], [0x001A73, 0x001A7C], [0x001AB0, 0x001ABD], - [0x001ABF, 0x001AC0], + [0x001ABF, 0x001ACE], [0x001B00, 0x001B03], [0x001B36, 0x001B3A], [0x001B6B, 0x001B73], @@ -229,8 +235,7 @@ const matchSymbols = buildString({ [0x001CD4, 0x001CE0], [0x001CE2, 0x001CE8], [0x001CF8, 0x001CF9], - [0x001DC0, 0x001DF9], - [0x001DFB, 0x001DFF], + [0x001DC0, 0x001DFF], [0x0020D0, 0x0020DC], [0x0020E5, 0x0020F0], [0x002CEF, 0x002CF1], @@ -266,7 +271,9 @@ const matchSymbols = buildString({ [0x010D24, 0x010D27], [0x010EAB, 0x010EAC], [0x010F46, 0x010F50], + [0x010F82, 0x010F85], [0x011038, 0x011046], + [0x011073, 0x011074], [0x01107F, 0x011081], [0x0110B3, 0x0110B6], [0x0110B9, 0x0110BA], @@ -325,6 +332,8 @@ const matchSymbols = buildString({ [0x016B30, 0x016B36], [0x016F8F, 0x016F92], [0x01BC9D, 0x01BC9E], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D167, 0x01D169], [0x01D17B, 0x01D182], [0x01D185, 0x01D18B], @@ -392,6 +401,7 @@ const nonMatchSymbols = buildString({ 0x000AC6, 0x000B00, 0x000B40, + 0x000C3D, 0x000C49, 0x000DD5, 0x000F36, @@ -402,6 +412,7 @@ const nonMatchSymbols = buildString({ 0x001031, 0x001038, 0x0017B6, + 0x00180E, 0x001A57, 0x001A5F, 0x001A61, @@ -413,7 +424,6 @@ const nonMatchSymbols = buildString({ 0x001BEE, 0x001CD3, 0x001CE1, - 0x001DFA, 0x00AAB1, 0x00AAC0, 0x010A04, @@ -461,7 +471,8 @@ const nonMatchSymbols = buildString({ [0x0007F4, 0x0007FC], [0x0007FE, 0x000815], [0x00082E, 0x000858], - [0x00085C, 0x0008D2], + [0x00085C, 0x000897], + [0x0008A0, 0x0008C9], [0x000903, 0x000939], [0x00093D, 0x000940], [0x000949, 0x00094C], @@ -497,7 +508,7 @@ const nonMatchSymbols = buildString({ [0x000BC1, 0x000BCC], [0x000BCE, 0x000BFF], [0x000C01, 0x000C03], - [0x000C05, 0x000C3D], + [0x000C05, 0x000C3B], [0x000C41, 0x000C45], [0x000C4E, 0x000C54], [0x000C57, 0x000C61], @@ -538,14 +549,14 @@ const nonMatchSymbols = buildString({ [0x00109E, 0x00135C], [0x001360, 0x001711], [0x001715, 0x001731], - [0x001735, 0x001751], + [0x001734, 0x001751], [0x001754, 0x001771], [0x001774, 0x0017B3], [0x0017BE, 0x0017C5], [0x0017C7, 0x0017C8], [0x0017D4, 0x0017DC], [0x0017DE, 0x00180A], - [0x00180E, 0x001884], + [0x001810, 0x001884], [0x001887, 0x0018A8], [0x0018AA, 0x00191F], [0x001923, 0x001926], @@ -558,7 +569,7 @@ const nonMatchSymbols = buildString({ [0x001A6D, 0x001A72], [0x001A7D, 0x001A7E], [0x001A80, 0x001AAF], - [0x001AC1, 0x001AFF], + [0x001ACF, 0x001AFF], [0x001B04, 0x001B33], [0x001B3D, 0x001B41], [0x001B43, 0x001B6A], @@ -630,12 +641,16 @@ const nonMatchSymbols = buildString({ [0x010AE7, 0x010D23], [0x010D28, 0x010EAA], [0x010EAD, 0x010F45], - [0x010F51, 0x011000], + [0x010F51, 0x010F81], + [0x010F86, 0x011000], [0x011002, 0x011037], - [0x011047, 0x01107E], + [0x011047, 0x01106F], + [0x011071, 0x011072], + [0x011075, 0x01107E], [0x011082, 0x0110B2], [0x0110B7, 0x0110B8], - [0x0110BB, 0x0110FF], + [0x0110BB, 0x0110C1], + [0x0110C3, 0x0110FF], [0x011103, 0x011126], [0x011135, 0x011172], [0x011174, 0x01117F], @@ -693,7 +708,9 @@ const nonMatchSymbols = buildString({ [0x016F50, 0x016F8E], [0x016F93, 0x016FE3], [0x016FE5, 0x01BC9C], - [0x01BC9F, 0x01D166], + [0x01BC9F, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D166], [0x01D16A, 0x01D17A], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], @@ -706,7 +723,8 @@ const nonMatchSymbols = buildString({ [0x01DAB0, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E12F], - [0x01E137, 0x01E2EB], + [0x01E137, 0x01E2AD], + [0x01E2AF, 0x01E2EB], [0x01E2F0, 0x01E8CF], [0x01E8D7, 0x01E943], [0x01E94B, 0x0E00FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Number.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Number.js index f2b84c41f288..217e8490e6b8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Number.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Number.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Number` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -133,6 +133,7 @@ const matchSymbols = buildString({ [0x011FC0, 0x011FD4], [0x012400, 0x01246E], [0x016A60, 0x016A69], + [0x016AC0, 0x016AC9], [0x016B50, 0x016B59], [0x016B5B, 0x016B61], [0x016E80, 0x016E96], @@ -309,7 +310,8 @@ const nonMatchSymbols = buildString({ [0x011DAA, 0x011FBF], [0x011FD5, 0x0123FF], [0x01246F, 0x016A5F], - [0x016A6A, 0x016B4F], + [0x016A6A, 0x016ABF], + [0x016ACA, 0x016B4F], [0x016B62, 0x016E7F], [0x016E97, 0x01D2DF], [0x01D2F4, 0x01D35F], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Open_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Open_Punctuation.js index 6e7a62494efc..f0b5c8c9a523 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Open_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Open_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Open_Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -61,6 +61,10 @@ const matchSymbols = buildString({ 0x002E26, 0x002E28, 0x002E42, + 0x002E55, + 0x002E57, + 0x002E59, + 0x002E5B, 0x003008, 0x00300A, 0x00300C, @@ -152,6 +156,9 @@ const nonMatchSymbols = buildString({ 0x002E23, 0x002E25, 0x002E27, + 0x002E56, + 0x002E58, + 0x002E5A, 0x003009, 0x00300B, 0x00300D, @@ -191,7 +198,8 @@ const nonMatchSymbols = buildString({ [0x0029DB, 0x0029FB], [0x0029FD, 0x002E21], [0x002E29, 0x002E41], - [0x002E43, 0x003007], + [0x002E43, 0x002E54], + [0x002E5C, 0x003007], [0x003011, 0x003013], [0x00301B, 0x00301C], [0x00301E, 0x00DBFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other.js index 3640e284dd6e..d454a74237a3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Other` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -21,10 +21,10 @@ const matchSymbols = buildString({ 0x0003A2, 0x000530, 0x000590, + 0x00061C, 0x0006DD, 0x00083F, 0x00085F, - 0x0008B5, 0x0008E2, 0x000984, 0x0009A9, @@ -101,12 +101,12 @@ const matchSymbols = buildString({ 0x0012C1, 0x0012D7, 0x001311, - 0x00170D, 0x00176D, 0x001771, + 0x00180E, 0x00191F, 0x001A5F, - 0x001DFA, + 0x001B7F, 0x001F58, 0x001F5A, 0x001F5C, @@ -118,8 +118,6 @@ const matchSymbols = buildString({ 0x001FFF, 0x00208F, 0x002B96, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -134,6 +132,8 @@ const matchSymbols = buildString({ 0x003130, 0x00318F, 0x00321F, + 0x00A7D2, + 0x00A7D4, 0x00A9CE, 0x00A9FF, 0x00AB27, @@ -153,6 +153,15 @@ const matchSymbols = buildString({ 0x01003E, 0x01018F, 0x01039E, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x010856, @@ -192,8 +201,12 @@ const matchSymbols = buildString({ 0x011D92, 0x01246F, 0x016A5F, + 0x016ABF, 0x016B5A, 0x016B62, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -211,6 +224,10 @@ const matchSymbols = buildString({ 0x01E007, 0x01E022, 0x01E025, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -239,8 +256,6 @@ const matchSymbols = buildString({ 0x01EEAA, 0x01F0C0, 0x01F0D0, - 0x01F979, - 0x01F9CC, 0x01FB93 ], ranges: [ @@ -254,15 +269,14 @@ const matchSymbols = buildString({ [0x0005C8, 0x0005CF], [0x0005EB, 0x0005EE], [0x0005F5, 0x000605], - [0x00061C, 0x00061D], [0x00070E, 0x00070F], [0x00074B, 0x00074C], [0x0007B2, 0x0007BF], [0x0007FB, 0x0007FC], [0x00082E, 0x00082F], [0x00085C, 0x00085D], - [0x00086B, 0x00089F], - [0x0008C8, 0x0008D2], + [0x00086B, 0x00086F], + [0x00088F, 0x000897], [0x00098D, 0x00098E], [0x000991, 0x000992], [0x0009B3, 0x0009B5], @@ -307,14 +321,15 @@ const matchSymbols = buildString({ [0x000BD1, 0x000BD6], [0x000BD8, 0x000BE5], [0x000BFB, 0x000BFF], - [0x000C3A, 0x000C3C], + [0x000C3A, 0x000C3B], [0x000C4E, 0x000C54], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C64, 0x000C65], [0x000C70, 0x000C76], [0x000CBA, 0x000CBB], [0x000CCE, 0x000CD4], - [0x000CD7, 0x000CDD], + [0x000CD7, 0x000CDC], [0x000CE4, 0x000CE5], [0x000CF3, 0x000CFF], [0x000D50, 0x000D53], @@ -349,14 +364,13 @@ const matchSymbols = buildString({ [0x0013FE, 0x0013FF], [0x00169D, 0x00169F], [0x0016F9, 0x0016FF], - [0x001715, 0x00171F], + [0x001716, 0x00171E], [0x001737, 0x00173F], [0x001754, 0x00175F], [0x001774, 0x00177F], [0x0017DE, 0x0017DF], [0x0017EA, 0x0017EF], [0x0017FA, 0x0017FF], - [0x00180E, 0x00180F], [0x00181A, 0x00181F], [0x001879, 0x00187F], [0x0018AB, 0x0018AF], @@ -374,9 +388,8 @@ const matchSymbols = buildString({ [0x001A8A, 0x001A8F], [0x001A9A, 0x001A9F], [0x001AAE, 0x001AAF], - [0x001AC1, 0x001AFF], - [0x001B4C, 0x001B4F], - [0x001B7D, 0x001B7F], + [0x001ACF, 0x001AFF], + [0x001B4D, 0x001B4F], [0x001BF4, 0x001BFB], [0x001C38, 0x001C3A], [0x001C4A, 0x001C4C], @@ -396,7 +409,7 @@ const matchSymbols = buildString({ [0x002060, 0x00206F], [0x002072, 0x002073], [0x00209D, 0x00209F], - [0x0020C0, 0x0020CF], + [0x0020C1, 0x0020CF], [0x0020F1, 0x0020FF], [0x00218C, 0x00218F], [0x002427, 0x00243F], @@ -408,20 +421,19 @@ const matchSymbols = buildString({ [0x002D68, 0x002D6E], [0x002D71, 0x002D7E], [0x002D97, 0x002D9F], - [0x002E53, 0x002E7F], + [0x002E5E, 0x002E7F], [0x002EF4, 0x002EFF], [0x002FD6, 0x002FEF], [0x002FFC, 0x002FFF], [0x003097, 0x003098], [0x003100, 0x003104], [0x0031E4, 0x0031EF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A48F], [0x00A4C7, 0x00A4CF], [0x00A62C, 0x00A63F], [0x00A6F8, 0x00A6FF], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A82D, 0x00A82F], [0x00A83A, 0x00A83F], [0x00A878, 0x00A87F], @@ -449,11 +461,10 @@ const matchSymbols = buildString({ [0x00FADA, 0x00FAFF], [0x00FB07, 0x00FB12], [0x00FB18, 0x00FB1C], - [0x00FBC2, 0x00FBD2], - [0x00FD40, 0x00FD4F], + [0x00FBC3, 0x00FBD2], [0x00FD90, 0x00FD91], - [0x00FDC8, 0x00FDEF], - [0x00FDFE, 0x00FDFF], + [0x00FDC8, 0x00FDCE], + [0x00FDD0, 0x00FDEF], [0x00FE1A, 0x00FE1F], [0x00FE6C, 0x00FE6F], [0x00FEFD, 0x00FF00], @@ -486,10 +497,11 @@ const matchSymbols = buildString({ [0x0104FC, 0x0104FF], [0x010528, 0x01052F], [0x010564, 0x01056E], - [0x010570, 0x0105FF], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -523,12 +535,13 @@ const matchSymbols = buildString({ [0x010EAE, 0x010EAF], [0x010EB2, 0x010EFF], [0x010F28, 0x010F2F], - [0x010F5A, 0x010FAF], + [0x010F5A, 0x010F6F], + [0x010F8A, 0x010FAF], [0x010FCC, 0x010FDF], [0x010FF7, 0x010FFF], [0x01104E, 0x011051], - [0x011070, 0x01107E], - [0x0110C2, 0x0110CF], + [0x011076, 0x01107E], + [0x0110C3, 0x0110CF], [0x0110E9, 0x0110EF], [0x0110FA, 0x0110FF], [0x011148, 0x01114F], @@ -556,11 +569,11 @@ const matchSymbols = buildString({ [0x011645, 0x01164F], [0x01165A, 0x01165F], [0x01166D, 0x01167F], - [0x0116B9, 0x0116BF], + [0x0116BA, 0x0116BF], [0x0116CA, 0x0116FF], [0x01171B, 0x01171C], [0x01172C, 0x01172F], - [0x011740, 0x0117FF], + [0x011747, 0x0117FF], [0x01183C, 0x01189F], [0x0118F3, 0x0118FE], [0x011907, 0x011908], @@ -572,7 +585,7 @@ const matchSymbols = buildString({ [0x0119D8, 0x0119D9], [0x0119E5, 0x0119FF], [0x011A48, 0x011A4F], - [0x011AA3, 0x011ABF], + [0x011AA3, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C46, 0x011C4F], [0x011C6D, 0x011C6F], @@ -588,12 +601,13 @@ const matchSymbols = buildString({ [0x011FF2, 0x011FFE], [0x01239A, 0x0123FF], [0x012475, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF3, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], [0x016A6A, 0x016A6D], - [0x016A70, 0x016ACF], + [0x016ACA, 0x016ACF], [0x016AEE, 0x016AEF], [0x016AF6, 0x016AFF], [0x016B46, 0x016B4F], @@ -607,8 +621,8 @@ const matchSymbols = buildString({ [0x016FF2, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -616,11 +630,14 @@ const matchSymbols = buildString({ [0x01BC7D, 0x01BC7F], [0x01BC89, 0x01BC8F], [0x01BC9A, 0x01BC9B], - [0x01BCA0, 0x01CFFF], + [0x01BCA0, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01CF4F], + [0x01CFC4, 0x01CFFF], [0x01D0F6, 0x01D0FF], [0x01D127, 0x01D128], [0x01D173, 0x01D17A], - [0x01D1E9, 0x01D1FF], + [0x01D1EB, 0x01D1FF], [0x01D246, 0x01D2DF], [0x01D2F4, 0x01D2FF], [0x01D357, 0x01D35F], @@ -633,15 +650,17 @@ const matchSymbols = buildString({ [0x01D6A6, 0x01D6A7], [0x01D7CC, 0x01D7CD], [0x01DA8C, 0x01DA9A], - [0x01DAB0, 0x01DFFF], + [0x01DAB0, 0x01DEFF], + [0x01DF1F, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E0FF], [0x01E12D, 0x01E12F], [0x01E13E, 0x01E13F], [0x01E14A, 0x01E14D], - [0x01E150, 0x01E2BF], + [0x01E150, 0x01E28F], + [0x01E2AF, 0x01E2BF], [0x01E2FA, 0x01E2FE], - [0x01E300, 0x01E7FF], + [0x01E300, 0x01E7DF], [0x01E8C5, 0x01E8C6], [0x01E8D7, 0x01E8FF], [0x01E94C, 0x01E94F], @@ -667,12 +686,13 @@ const matchSymbols = buildString({ [0x01F249, 0x01F24F], [0x01F252, 0x01F25F], [0x01F266, 0x01F2FF], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6ED, 0x01F6EF], [0x01F6FD, 0x01F6FF], [0x01F774, 0x01F77F], [0x01F7D9, 0x01F7DF], - [0x01F7EC, 0x01F7FF], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F7FF], [0x01F80C, 0x01F80F], [0x01F848, 0x01F84F], [0x01F85A, 0x01F85F], @@ -682,16 +702,18 @@ const matchSymbols = buildString({ [0x01FA54, 0x01FA5F], [0x01FA6E, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x01FAFF], + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x01FAFF], [0x01FBCB, 0x01FBEF], [0x01FBFA, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], @@ -744,7 +766,7 @@ const nonMatchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000BD7, - 0x000CDE, + 0x000C5D, 0x000DBD, 0x000DCA, 0x000DD6, @@ -761,9 +783,10 @@ const nonMatchSymbols = buildString({ 0x001F5D, 0x002D27, 0x002D2D, + 0x00A7D3, 0x00FB3E, + 0x00FDCF, 0x0101A0, - 0x01056F, 0x010808, 0x01083C, 0x01093F, @@ -792,7 +815,8 @@ const nonMatchSymbols = buildString({ 0x01EE5D, 0x01EE5F, 0x01EE64, - 0x01EE7E + 0x01EE7E, + 0x01F7F0 ], ranges: [ [0x000020, 0x00007E], @@ -809,7 +833,7 @@ const nonMatchSymbols = buildString({ [0x0005D0, 0x0005EA], [0x0005EF, 0x0005F4], [0x000606, 0x00061B], - [0x00061E, 0x0006DC], + [0x00061D, 0x0006DC], [0x0006DE, 0x00070D], [0x000710, 0x00074A], [0x00074D, 0x0007B1], @@ -818,9 +842,8 @@ const nonMatchSymbols = buildString({ [0x000830, 0x00083E], [0x000840, 0x00085B], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], - [0x0008D3, 0x0008E1], + [0x000870, 0x00088E], + [0x000898, 0x0008E1], [0x0008E3, 0x000983], [0x000985, 0x00098C], [0x00098F, 0x000990], @@ -890,7 +913,7 @@ const nonMatchSymbols = buildString({ [0x000C0E, 0x000C10], [0x000C12, 0x000C28], [0x000C2A, 0x000C39], - [0x000C3D, 0x000C44], + [0x000C3C, 0x000C44], [0x000C46, 0x000C48], [0x000C4A, 0x000C4D], [0x000C55, 0x000C56], @@ -906,6 +929,7 @@ const nonMatchSymbols = buildString({ [0x000CC6, 0x000CC8], [0x000CCA, 0x000CCD], [0x000CD5, 0x000CD6], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE3], [0x000CE6, 0x000CEF], [0x000CF1, 0x000CF2], @@ -962,9 +986,8 @@ const nonMatchSymbols = buildString({ [0x0013F8, 0x0013FD], [0x001400, 0x00169C], [0x0016A0, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001714], - [0x001720, 0x001736], + [0x001700, 0x001715], + [0x00171F, 0x001736], [0x001740, 0x001753], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -973,7 +996,7 @@ const nonMatchSymbols = buildString({ [0x0017E0, 0x0017E9], [0x0017F0, 0x0017F9], [0x001800, 0x00180D], - [0x001810, 0x001819], + [0x00180F, 0x001819], [0x001820, 0x001878], [0x001880, 0x0018AA], [0x0018B0, 0x0018F5], @@ -991,9 +1014,9 @@ const nonMatchSymbols = buildString({ [0x001A7F, 0x001A89], [0x001A90, 0x001A99], [0x001AA0, 0x001AAD], - [0x001AB0, 0x001AC0], - [0x001B00, 0x001B4B], - [0x001B50, 0x001B7C], + [0x001AB0, 0x001ACE], + [0x001B00, 0x001B4C], + [0x001B50, 0x001B7E], [0x001B80, 0x001BF3], [0x001BFC, 0x001C37], [0x001C3B, 0x001C49], @@ -1001,8 +1024,7 @@ const nonMatchSymbols = buildString({ [0x001C90, 0x001CBA], [0x001CBD, 0x001CC7], [0x001CD0, 0x001CFA], - [0x001D00, 0x001DF9], - [0x001DFB, 0x001F15], + [0x001D00, 0x001F15], [0x001F18, 0x001F1D], [0x001F20, 0x001F45], [0x001F48, 0x001F4D], @@ -1021,16 +1043,14 @@ const nonMatchSymbols = buildString({ [0x002070, 0x002071], [0x002074, 0x00208E], [0x002090, 0x00209C], - [0x0020A0, 0x0020BF], + [0x0020A0, 0x0020C0], [0x0020D0, 0x0020F0], [0x002100, 0x00218B], [0x002190, 0x002426], [0x002440, 0x00244A], [0x002460, 0x002B73], [0x002B76, 0x002B95], - [0x002B97, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CF3], + [0x002B97, 0x002CF3], [0x002CF9, 0x002D25], [0x002D30, 0x002D67], [0x002D6F, 0x002D70], @@ -1043,7 +1063,7 @@ const nonMatchSymbols = buildString({ [0x002DC8, 0x002DCE], [0x002DD0, 0x002DD6], [0x002DD8, 0x002DDE], - [0x002DE0, 0x002E52], + [0x002DE0, 0x002E5D], [0x002E80, 0x002E99], [0x002E9B, 0x002EF3], [0x002F00, 0x002FD5], @@ -1055,14 +1075,14 @@ const nonMatchSymbols = buildString({ [0x003131, 0x00318E], [0x003190, 0x0031E3], [0x0031F0, 0x00321E], - [0x003220, 0x009FFC], - [0x00A000, 0x00A48C], + [0x003220, 0x00A48C], [0x00A490, 0x00A4C6], [0x00A4D0, 0x00A62B], [0x00A640, 0x00A6F7], - [0x00A700, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A82C], + [0x00A700, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A82C], [0x00A830, 0x00A839], [0x00A840, 0x00A877], [0x00A880, 0x00A8C5], @@ -1096,12 +1116,10 @@ const nonMatchSymbols = buildString({ [0x00FB38, 0x00FB3C], [0x00FB40, 0x00FB41], [0x00FB43, 0x00FB44], - [0x00FB46, 0x00FBC1], - [0x00FBD3, 0x00FD3F], - [0x00FD50, 0x00FD8F], + [0x00FB46, 0x00FBC2], + [0x00FBD3, 0x00FD8F], [0x00FD92, 0x00FDC7], - [0x00FDF0, 0x00FDFD], - [0x00FE00, 0x00FE19], + [0x00FDF0, 0x00FE19], [0x00FE20, 0x00FE52], [0x00FE54, 0x00FE66], [0x00FE68, 0x00FE6B], @@ -1142,9 +1160,20 @@ const nonMatchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x01056F, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -1185,12 +1214,13 @@ const nonMatchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F27], [0x010F30, 0x010F59], + [0x010F70, 0x010F89], [0x010FB0, 0x010FCB], [0x010FE0, 0x010FF6], [0x011000, 0x01104D], - [0x011052, 0x01106F], + [0x011052, 0x011075], [0x01107F, 0x0110BC], - [0x0110BE, 0x0110C1], + [0x0110BE, 0x0110C2], [0x0110D0, 0x0110E8], [0x0110F0, 0x0110F9], [0x011100, 0x011134], @@ -1228,11 +1258,11 @@ const nonMatchSymbols = buildString({ [0x011600, 0x011644], [0x011650, 0x011659], [0x011660, 0x01166C], - [0x011680, 0x0116B8], + [0x011680, 0x0116B9], [0x0116C0, 0x0116C9], [0x011700, 0x01171A], [0x01171D, 0x01172B], - [0x011730, 0x01173F], + [0x011730, 0x011746], [0x011800, 0x01183B], [0x0118A0, 0x0118F2], [0x0118FF, 0x011906], @@ -1247,7 +1277,7 @@ const nonMatchSymbols = buildString({ [0x0119DA, 0x0119E4], [0x011A00, 0x011A47], [0x011A50, 0x011AA2], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C36], [0x011C38, 0x011C45], @@ -1273,12 +1303,14 @@ const nonMatchSymbols = buildString({ [0x012400, 0x01246E], [0x012470, 0x012474], [0x012480, 0x012543], + [0x012F90, 0x012FF2], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], [0x016A60, 0x016A69], - [0x016A6E, 0x016A6F], + [0x016A6E, 0x016ABE], + [0x016AC0, 0x016AC9], [0x016AD0, 0x016AED], [0x016AF0, 0x016AF5], [0x016B00, 0x016B45], @@ -1295,7 +1327,10 @@ const nonMatchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -1304,10 +1339,13 @@ const nonMatchSymbols = buildString({ [0x01BC80, 0x01BC88], [0x01BC90, 0x01BC99], [0x01BC9C, 0x01BC9F], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], + [0x01CF50, 0x01CFC3], [0x01D000, 0x01D0F5], [0x01D100, 0x01D126], [0x01D129, 0x01D172], - [0x01D17B, 0x01D1E8], + [0x01D17B, 0x01D1EA], [0x01D200, 0x01D245], [0x01D2E0, 0x01D2F3], [0x01D300, 0x01D356], @@ -1332,6 +1370,7 @@ const nonMatchSymbols = buildString({ [0x01D7CE, 0x01DA8B], [0x01DA9B, 0x01DA9F], [0x01DAA1, 0x01DAAF], + [0x01DF00, 0x01DF1E], [0x01E000, 0x01E006], [0x01E008, 0x01E018], [0x01E01B, 0x01E021], @@ -1341,7 +1380,12 @@ const nonMatchSymbols = buildString({ [0x01E130, 0x01E13D], [0x01E140, 0x01E149], [0x01E14E, 0x01E14F], + [0x01E290, 0x01E2AE], [0x01E2C0, 0x01E2F9], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E8C7, 0x01E8D6], [0x01E900, 0x01E94B], @@ -1380,7 +1424,7 @@ const nonMatchSymbols = buildString({ [0x01F250, 0x01F251], [0x01F260, 0x01F265], [0x01F300, 0x01F6D7], - [0x01F6E0, 0x01F6EC], + [0x01F6DD, 0x01F6EC], [0x01F6F0, 0x01F6FC], [0x01F700, 0x01F773], [0x01F780, 0x01F7D8], @@ -1391,22 +1435,22 @@ const nonMatchSymbols = buildString({ [0x01F860, 0x01F887], [0x01F890, 0x01F8AD], [0x01F8B0, 0x01F8B1], - [0x01F900, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01FA53], + [0x01F900, 0x01FA53], [0x01FA60, 0x01FA6D], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6], + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6], [0x01FB00, 0x01FB92], [0x01FB94, 0x01FBCA], [0x01FBF0, 0x01FBF9], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Letter.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Letter.js index e950fb7e76ff..5c1959b0539e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Letter.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Letter.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Other_Letter` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -39,9 +39,9 @@ const matchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000C3D, + 0x000C5D, 0x000C80, 0x000CBD, - 0x000CDE, 0x000D3D, 0x000D4E, 0x000DBD, @@ -76,6 +76,7 @@ const matchSymbols = buildString({ 0x01083C, 0x010A00, 0x010F27, + 0x011075, 0x011144, 0x011147, 0x011176, @@ -101,6 +102,7 @@ const matchSymbols = buildString({ 0x011D98, 0x011FB0, 0x016F50, + 0x01DF0A, 0x01E14E, 0x01EE24, 0x01EE27, @@ -135,8 +137,9 @@ const matchSymbols = buildString({ [0x000800, 0x000815], [0x000840, 0x000858], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], + [0x000870, 0x000887], + [0x000889, 0x00088E], + [0x0008A0, 0x0008C8], [0x000904, 0x000939], [0x000958, 0x000961], [0x000972, 0x000980], @@ -191,6 +194,7 @@ const matchSymbols = buildString({ [0x000C92, 0x000CA8], [0x000CAA, 0x000CB3], [0x000CB5, 0x000CB9], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE1], [0x000CF1, 0x000CF2], [0x000D04, 0x000D0C], @@ -242,9 +246,8 @@ const matchSymbols = buildString({ [0x001681, 0x00169A], [0x0016A0, 0x0016EA], [0x0016F1, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001711], - [0x001720, 0x001731], + [0x001700, 0x001711], + [0x00171F, 0x001731], [0x001740, 0x001751], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -262,7 +265,7 @@ const matchSymbols = buildString({ [0x001A00, 0x001A16], [0x001A20, 0x001A54], [0x001B05, 0x001B33], - [0x001B45, 0x001B4B], + [0x001B45, 0x001B4C], [0x001B83, 0x001BA0], [0x001BAE, 0x001BAF], [0x001BBA, 0x001BE5], @@ -290,8 +293,7 @@ const matchSymbols = buildString({ [0x0031A0, 0x0031BF], [0x0031F0, 0x0031FF], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], - [0x00A000, 0x00A014], + [0x004E00, 0x00A014], [0x00A016, 0x00A48C], [0x00A4D0, 0x00A4F7], [0x00A500, 0x00A60B], @@ -404,9 +406,11 @@ const matchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F1C], [0x010F30, 0x010F45], + [0x010F70, 0x010F81], [0x010FB0, 0x010FC4], [0x010FE0, 0x010FF6], [0x011003, 0x011037], + [0x011071, 0x011072], [0x011083, 0x0110AF], [0x0110D0, 0x0110E8], [0x011103, 0x011126], @@ -437,6 +441,7 @@ const matchSymbols = buildString({ [0x011600, 0x01162F], [0x011680, 0x0116AA], [0x011700, 0x01171A], + [0x011740, 0x011746], [0x011800, 0x01182B], [0x0118FF, 0x011906], [0x01190C, 0x011913], @@ -446,7 +451,7 @@ const matchSymbols = buildString({ [0x0119AA, 0x0119D0], [0x011A0B, 0x011A32], [0x011A5C, 0x011A89], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C2E], [0x011C72, 0x011C8F], @@ -459,10 +464,12 @@ const matchSymbols = buildString({ [0x011EE0, 0x011EF2], [0x012000, 0x012399], [0x012480, 0x012543], + [0x012F90, 0x012FF0], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], + [0x016A70, 0x016ABE], [0x016AD0, 0x016AED], [0x016B00, 0x016B2F], [0x016B63, 0x016B77], @@ -471,7 +478,7 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -480,7 +487,12 @@ const matchSymbols = buildString({ [0x01BC80, 0x01BC88], [0x01BC90, 0x01BC99], [0x01E100, 0x01E12C], + [0x01E290, 0x01E2AD], [0x01E2C0, 0x01E2EB], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01EE00, 0x01EE03], [0x01EE05, 0x01EE1F], @@ -499,8 +511,8 @@ const matchSymbols = buildString({ [0x01EEA1, 0x01EEA3], [0x01EEA5, 0x01EEA9], [0x01EEAB, 0x01EEBB], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -545,7 +557,7 @@ const nonMatchSymbols = buildString({ 0x000670, 0x0006D4, 0x000711, - 0x0008B5, + 0x000888, 0x0009A9, 0x0009B1, 0x0009DE, @@ -597,7 +609,6 @@ const nonMatchSymbols = buildString({ 0x0012D7, 0x001311, 0x001680, - 0x00170D, 0x00176D, 0x001843, 0x0018A9, @@ -662,6 +673,10 @@ const nonMatchSymbols = buildString({ 0x011D0A, 0x011D66, 0x011D69, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -710,8 +725,9 @@ const nonMatchSymbols = buildString({ [0x0007EB, 0x0007FF], [0x000816, 0x00083F], [0x000859, 0x00085F], - [0x00086B, 0x00089F], - [0x0008C8, 0x000903], + [0x00086B, 0x00086F], + [0x00088F, 0x00089F], + [0x0008C9, 0x000903], [0x00093A, 0x00093C], [0x00093E, 0x00094F], [0x000951, 0x000957], @@ -751,11 +767,12 @@ const nonMatchSymbols = buildString({ [0x000BD1, 0x000C04], [0x000C3A, 0x000C3C], [0x000C3E, 0x000C57], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C62, 0x000C7F], [0x000C81, 0x000C84], [0x000CBA, 0x000CBC], - [0x000CBE, 0x000CDD], + [0x000CBE, 0x000CDC], [0x000CE2, 0x000CF0], [0x000CF3, 0x000D03], [0x000D3B, 0x000D3C], @@ -797,7 +814,7 @@ const nonMatchSymbols = buildString({ [0x00169B, 0x00169F], [0x0016EB, 0x0016F0], [0x0016F9, 0x0016FF], - [0x001712, 0x00171F], + [0x001712, 0x00171E], [0x001732, 0x00173F], [0x001752, 0x00175F], [0x001771, 0x00177F], @@ -815,7 +832,7 @@ const nonMatchSymbols = buildString({ [0x001A17, 0x001A1F], [0x001A55, 0x001B04], [0x001B34, 0x001B44], - [0x001B4C, 0x001B82], + [0x001B4D, 0x001B82], [0x001BA1, 0x001BAD], [0x001BB0, 0x001BB9], [0x001BE6, 0x001BFF], @@ -837,7 +854,6 @@ const nonMatchSymbols = buildString({ [0x0031C0, 0x0031EF], [0x003200, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A4CF], [0x00A4F8, 0x00A4FF], [0x00A60C, 0x00A60F], @@ -935,10 +951,13 @@ const nonMatchSymbols = buildString({ [0x010EB2, 0x010EFF], [0x010F1D, 0x010F26], [0x010F28, 0x010F2F], - [0x010F46, 0x010FAF], + [0x010F46, 0x010F6F], + [0x010F82, 0x010FAF], [0x010FC5, 0x010FDF], [0x010FF7, 0x011002], - [0x011038, 0x011082], + [0x011038, 0x011070], + [0x011073, 0x011074], + [0x011076, 0x011082], [0x0110B0, 0x0110CF], [0x0110E9, 0x011102], [0x011127, 0x011143], @@ -969,7 +988,8 @@ const nonMatchSymbols = buildString({ [0x011645, 0x01167F], [0x0116AB, 0x0116B7], [0x0116B9, 0x0116FF], - [0x01171B, 0x0117FF], + [0x01171B, 0x01173F], + [0x011747, 0x0117FF], [0x01182C, 0x0118FE], [0x011907, 0x011908], [0x01190A, 0x01190B], @@ -983,7 +1003,7 @@ const nonMatchSymbols = buildString({ [0x011A3B, 0x011A4F], [0x011A51, 0x011A5B], [0x011A8A, 0x011A9C], - [0x011A9E, 0x011ABF], + [0x011A9E, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C2F, 0x011C3F], [0x011C41, 0x011C71], @@ -995,11 +1015,13 @@ const nonMatchSymbols = buildString({ [0x011EF3, 0x011FAF], [0x011FB1, 0x011FFF], [0x01239A, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF1, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], - [0x016A5F, 0x016ACF], + [0x016A5F, 0x016A6F], + [0x016ABF, 0x016ACF], [0x016AEE, 0x016AFF], [0x016B30, 0x016B62], [0x016B78, 0x016B7C], @@ -1009,17 +1031,19 @@ const nonMatchSymbols = buildString({ [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], [0x01BC6B, 0x01BC6F], [0x01BC7D, 0x01BC7F], [0x01BC89, 0x01BC8F], - [0x01BC9A, 0x01E0FF], + [0x01BC9A, 0x01DF09], + [0x01DF0B, 0x01E0FF], [0x01E12D, 0x01E14D], - [0x01E14F, 0x01E2BF], - [0x01E2EC, 0x01E7FF], + [0x01E14F, 0x01E28F], + [0x01E2AE, 0x01E2BF], + [0x01E2EC, 0x01E7DF], [0x01E8C5, 0x01EDFF], [0x01EE25, 0x01EE26], [0x01EE3C, 0x01EE41], @@ -1028,8 +1052,8 @@ const nonMatchSymbols = buildString({ [0x01EE65, 0x01EE66], [0x01EE9C, 0x01EEA0], [0x01EEBC, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Number.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Number.js index 28852351a988..825be586d329 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Number.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Number.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Other_Number` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Punctuation.js index 1d0510686a97..8f502f0184fa 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Other_Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -48,7 +48,6 @@ const matchSymbols = buildString({ 0x002E0B, 0x002E1B, 0x002E41, - 0x002E52, 0x00303D, 0x0030FB, 0x00A673, @@ -75,6 +74,7 @@ const matchSymbols = buildString({ 0x0112A9, 0x01145D, 0x0114C6, + 0x0116B9, 0x01183B, 0x0119E2, 0x011FFF, @@ -94,7 +94,7 @@ const matchSymbols = buildString({ [0x0005F3, 0x0005F4], [0x000609, 0x00060A], [0x00060C, 0x00060D], - [0x00061E, 0x00061F], + [0x00061D, 0x00061F], [0x00066A, 0x00066D], [0x000700, 0x00070D], [0x0007F7, 0x0007F9], @@ -117,6 +117,7 @@ const matchSymbols = buildString({ [0x001AA0, 0x001AA6], [0x001AA8, 0x001AAD], [0x001B5A, 0x001B60], + [0x001B7D, 0x001B7E], [0x001BFC, 0x001BFF], [0x001C3B, 0x001C3F], [0x001C7E, 0x001C7F], @@ -139,6 +140,7 @@ const matchSymbols = buildString({ [0x002E30, 0x002E39], [0x002E3C, 0x002E3F], [0x002E43, 0x002E4F], + [0x002E52, 0x002E54], [0x003001, 0x003003], [0x00A4FE, 0x00A4FF], [0x00A60D, 0x00A60F], @@ -171,6 +173,7 @@ const matchSymbols = buildString({ [0x010B39, 0x010B3F], [0x010B99, 0x010B9C], [0x010F55, 0x010F59], + [0x010F86, 0x010F89], [0x011047, 0x01104D], [0x0110BB, 0x0110BC], [0x0110BE, 0x0110C1], @@ -193,6 +196,7 @@ const matchSymbols = buildString({ [0x011C70, 0x011C71], [0x011EF7, 0x011EF8], [0x012470, 0x012474], + [0x012FF1, 0x012FF2], [0x016A6E, 0x016A6F], [0x016B37, 0x016B3B], [0x016E97, 0x016E9A], @@ -237,6 +241,7 @@ const nonMatchSymbols = buildString({ 0x00002B, 0x00002D, 0x00060B, + 0x00061C, 0x000F13, 0x0017D7, 0x001806, @@ -281,7 +286,6 @@ const nonMatchSymbols = buildString({ [0x0005C7, 0x0005F2], [0x0005F5, 0x000608], [0x00060E, 0x00061A], - [0x00061C, 0x00061D], [0x000620, 0x000669], [0x00066E, 0x0006D3], [0x0006D5, 0x0006FF], @@ -314,7 +318,8 @@ const nonMatchSymbols = buildString({ [0x001946, 0x001A1D], [0x001A20, 0x001A9F], [0x001AAE, 0x001B59], - [0x001B61, 0x001BFB], + [0x001B61, 0x001B7C], + [0x001B7F, 0x001BFB], [0x001C00, 0x001C3A], [0x001C40, 0x001C7D], [0x001C80, 0x001CBF], @@ -335,7 +340,7 @@ const nonMatchSymbols = buildString({ [0x002E20, 0x002E29], [0x002E3A, 0x002E3B], [0x002E50, 0x002E51], - [0x002E53, 0x003000], + [0x002E55, 0x003000], [0x003004, 0x00303C], [0x00303E, 0x0030FA], [0x0030FC, 0x00A4FD], @@ -383,7 +388,8 @@ const nonMatchSymbols = buildString({ [0x010AF7, 0x010B38], [0x010B40, 0x010B98], [0x010B9D, 0x010F54], - [0x010F5A, 0x011046], + [0x010F5A, 0x010F85], + [0x010F8A, 0x011046], [0x01104E, 0x0110BA], [0x0110C2, 0x01113F], [0x011144, 0x011173], @@ -398,7 +404,8 @@ const nonMatchSymbols = buildString({ [0x0114C7, 0x0115C0], [0x0115D8, 0x011640], [0x011644, 0x01165F], - [0x01166D, 0x01173B], + [0x01166D, 0x0116B8], + [0x0116BA, 0x01173B], [0x01173F, 0x01183A], [0x01183C, 0x011943], [0x011947, 0x0119E1], @@ -409,7 +416,8 @@ const nonMatchSymbols = buildString({ [0x011C72, 0x011EF6], [0x011EF9, 0x011FFE], [0x012000, 0x01246F], - [0x012475, 0x016A6D], + [0x012475, 0x012FF0], + [0x012FF3, 0x016A6D], [0x016A70, 0x016AF4], [0x016AF6, 0x016B36], [0x016B3C, 0x016B43], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Symbol.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Symbol.js index 7cb4418fec9d..c183e257a6da 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Symbol.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Symbol.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Other_Symbol` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -47,7 +47,7 @@ const matchSymbols = buildString({ 0x003020, 0x003250, 0x00A839, - 0x00FDFD, + 0x00FDCF, 0x00FFE4, 0x00FFE8, 0x0101A0, @@ -58,7 +58,8 @@ const matchSymbols = buildString({ 0x01D245, 0x01E14F, 0x01ECAC, - 0x01ED2E + 0x01ED2E, + 0x01F7F0 ], ranges: [ [0x00058D, 0x00058E], @@ -136,6 +137,8 @@ const matchSymbols = buildString({ [0x00A828, 0x00A82B], [0x00A836, 0x00A837], [0x00AA77, 0x00AA79], + [0x00FD40, 0x00FD4F], + [0x00FDFD, 0x00FDFF], [0x00FFED, 0x00FFEE], [0x00FFFC, 0x00FFFD], [0x010137, 0x01013F], @@ -147,13 +150,14 @@ const matchSymbols = buildString({ [0x011FD5, 0x011FDC], [0x011FE1, 0x011FF1], [0x016B3C, 0x016B3F], + [0x01CF50, 0x01CFC3], [0x01D000, 0x01D0F5], [0x01D100, 0x01D126], [0x01D129, 0x01D164], [0x01D16A, 0x01D16C], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], - [0x01D1AE, 0x01D1E8], + [0x01D1AE, 0x01D1EA], [0x01D200, 0x01D241], [0x01D300, 0x01D356], [0x01D800, 0x01D9FF], @@ -175,7 +179,7 @@ const matchSymbols = buildString({ [0x01F260, 0x01F265], [0x01F300, 0x01F3FA], [0x01F400, 0x01F6D7], - [0x01F6E0, 0x01F6EC], + [0x01F6DD, 0x01F6EC], [0x01F6F0, 0x01F6FC], [0x01F700, 0x01F773], [0x01F780, 0x01F7D8], @@ -186,17 +190,17 @@ const matchSymbols = buildString({ [0x01F860, 0x01F887], [0x01F890, 0x01F8AD], [0x01F8B0, 0x01F8B1], - [0x01F900, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01FA53], + [0x01F900, 0x01FA53], [0x01FA60, 0x01FA6D], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6], + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6], [0x01FB00, 0x01FB92], [0x01FB94, 0x01FBCA] ] @@ -267,8 +271,6 @@ const nonMatchSymbols = buildString({ 0x01DA84, 0x01F0C0, 0x01F0D0, - 0x01F979, - 0x01F9CC, 0x01FB93 ], ranges: [ @@ -353,8 +355,10 @@ const nonMatchSymbols = buildString({ [0x00A82C, 0x00A835], [0x00A83A, 0x00AA76], [0x00AA7A, 0x00DBFF], - [0x00E000, 0x00FDFC], - [0x00FDFE, 0x00FFE3], + [0x00E000, 0x00FD3F], + [0x00FD50, 0x00FDCE], + [0x00FDD0, 0x00FDFC], + [0x00FE00, 0x00FFE3], [0x00FFE5, 0x00FFE7], [0x00FFE9, 0x00FFEC], [0x00FFEF, 0x00FFFB], @@ -371,14 +375,15 @@ const nonMatchSymbols = buildString({ [0x011FF2, 0x016B3B], [0x016B40, 0x016B44], [0x016B46, 0x01BC9B], - [0x01BC9D, 0x01CFFF], + [0x01BC9D, 0x01CF4F], + [0x01CFC4, 0x01CFFF], [0x01D0F6, 0x01D0FF], [0x01D127, 0x01D128], [0x01D165, 0x01D169], [0x01D16D, 0x01D182], [0x01D185, 0x01D18B], [0x01D1AA, 0x01D1AD], - [0x01D1E9, 0x01D1FF], + [0x01D1EB, 0x01D1FF], [0x01D242, 0x01D244], [0x01D246, 0x01D2FF], [0x01D357, 0x01D7FF], @@ -399,12 +404,13 @@ const nonMatchSymbols = buildString({ [0x01F252, 0x01F25F], [0x01F266, 0x01F2FF], [0x01F3FB, 0x01F3FF], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6ED, 0x01F6EF], [0x01F6FD, 0x01F6FF], [0x01F774, 0x01F77F], [0x01F7D9, 0x01F7DF], - [0x01F7EC, 0x01F7FF], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F7FF], [0x01F80C, 0x01F80F], [0x01F848, 0x01F84F], [0x01F85A, 0x01F85F], @@ -414,12 +420,14 @@ const nonMatchSymbols = buildString({ [0x01FA54, 0x01FA5F], [0x01FA6E, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x01FAFF], + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x01FAFF], [0x01FBCB, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Paragraph_Separator.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Paragraph_Separator.js index 3fc3f4d78c36..56f0df6c6e08 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Paragraph_Separator.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Paragraph_Separator.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Paragraph_Separator` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Private_Use.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Private_Use.js index 19b8eb56290c..a52b4fe94f56 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Private_Use.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Private_Use.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Private_Use` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Punctuation.js index abc7c5baf894..36e65390bc37 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -47,7 +47,6 @@ const matchSymbols = buildString({ 0x00166E, 0x001CD3, 0x002D70, - 0x002E52, 0x003030, 0x00303D, 0x0030A0, @@ -75,6 +74,7 @@ const matchSymbols = buildString({ 0x0112A9, 0x01145D, 0x0114C6, + 0x0116B9, 0x01183B, 0x0119E2, 0x011FFF, @@ -96,7 +96,7 @@ const matchSymbols = buildString({ [0x0005F3, 0x0005F4], [0x000609, 0x00060A], [0x00060C, 0x00060D], - [0x00061E, 0x00061F], + [0x00061D, 0x00061F], [0x00066A, 0x00066D], [0x000700, 0x00070D], [0x0007F7, 0x0007F9], @@ -120,6 +120,7 @@ const matchSymbols = buildString({ [0x001AA0, 0x001AA6], [0x001AA8, 0x001AAD], [0x001B5A, 0x001B60], + [0x001B7D, 0x001B7E], [0x001BFC, 0x001BFF], [0x001C3B, 0x001C3F], [0x001C7E, 0x001C7F], @@ -142,6 +143,7 @@ const matchSymbols = buildString({ [0x002CFE, 0x002CFF], [0x002E00, 0x002E2E], [0x002E30, 0x002E4F], + [0x002E52, 0x002E5D], [0x003001, 0x003003], [0x003008, 0x003011], [0x003014, 0x00301F], @@ -175,6 +177,7 @@ const matchSymbols = buildString({ [0x010B39, 0x010B3F], [0x010B99, 0x010B9C], [0x010F55, 0x010F59], + [0x010F86, 0x010F89], [0x011047, 0x01104D], [0x0110BB, 0x0110BC], [0x0110BE, 0x0110C1], @@ -197,6 +200,7 @@ const matchSymbols = buildString({ [0x011C70, 0x011C71], [0x011EF7, 0x011EF8], [0x012470, 0x012474], + [0x012FF1, 0x012FF2], [0x016A6E, 0x016A6F], [0x016B37, 0x016B3B], [0x016E97, 0x016E9A], @@ -258,6 +262,7 @@ const nonMatchSymbols = buildString({ 0x00007C, 0x0005BF, 0x00060B, + 0x00061C, 0x000F13, 0x0017D7, 0x001AA7, @@ -302,7 +307,6 @@ const nonMatchSymbols = buildString({ [0x0005C7, 0x0005F2], [0x0005F5, 0x000608], [0x00060E, 0x00061A], - [0x00061C, 0x00061D], [0x000620, 0x000669], [0x00066E, 0x0006D3], [0x0006D5, 0x0006FF], @@ -338,7 +342,8 @@ const nonMatchSymbols = buildString({ [0x001946, 0x001A1D], [0x001A20, 0x001A9F], [0x001AAE, 0x001B59], - [0x001B61, 0x001BFB], + [0x001B61, 0x001B7C], + [0x001B7F, 0x001BFB], [0x001C00, 0x001C3A], [0x001C40, 0x001C7D], [0x001C80, 0x001CBF], @@ -359,7 +364,7 @@ const nonMatchSymbols = buildString({ [0x002D00, 0x002D6F], [0x002D71, 0x002DFF], [0x002E50, 0x002E51], - [0x002E53, 0x003000], + [0x002E5E, 0x003000], [0x003004, 0x003007], [0x003012, 0x003013], [0x003020, 0x00302F], @@ -406,7 +411,8 @@ const nonMatchSymbols = buildString({ [0x010B40, 0x010B98], [0x010B9D, 0x010EAC], [0x010EAE, 0x010F54], - [0x010F5A, 0x011046], + [0x010F5A, 0x010F85], + [0x010F8A, 0x011046], [0x01104E, 0x0110BA], [0x0110C2, 0x01113F], [0x011144, 0x011173], @@ -421,7 +427,8 @@ const nonMatchSymbols = buildString({ [0x0114C7, 0x0115C0], [0x0115D8, 0x011640], [0x011644, 0x01165F], - [0x01166D, 0x01173B], + [0x01166D, 0x0116B8], + [0x0116BA, 0x01173B], [0x01173F, 0x01183A], [0x01183C, 0x011943], [0x011947, 0x0119E1], @@ -432,7 +439,8 @@ const nonMatchSymbols = buildString({ [0x011C72, 0x011EF6], [0x011EF9, 0x011FFE], [0x012000, 0x01246F], - [0x012475, 0x016A6D], + [0x012475, 0x012FF0], + [0x012FF3, 0x016A6D], [0x016A70, 0x016AF4], [0x016AF6, 0x016B36], [0x016B3C, 0x016B43], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Separator.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Separator.js index d0c58e9cac38..562a21544b4f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Separator.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Separator.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Separator` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Space_Separator.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Space_Separator.js index 379b4f01ee6b..d83c2bf301e2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Space_Separator.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Space_Separator.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Space_Separator` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Spacing_Mark.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Spacing_Mark.js index 8a2149040b4e..7f59e9cda39a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Spacing_Mark.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Spacing_Mark.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Spacing_Mark` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -31,6 +31,8 @@ const matchSymbols = buildString({ 0x001031, 0x001038, 0x00108F, + 0x001715, + 0x001734, 0x0017B6, 0x001A55, 0x001A57, @@ -307,7 +309,9 @@ const nonMatchSymbols = buildString({ [0x001085, 0x001086], [0x00108D, 0x00108E], [0x001090, 0x001099], - [0x00109D, 0x0017B5], + [0x00109D, 0x001714], + [0x001716, 0x001733], + [0x001735, 0x0017B5], [0x0017B7, 0x0017BD], [0x0017C9, 0x001922], [0x001927, 0x001928], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Surrogate.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Surrogate.js index 06197c06f5ec..c63699b1459e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Surrogate.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Surrogate.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Surrogate` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Symbol.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Symbol.js index d50af24bffb3..bda9467f58ba 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Symbol.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Symbol.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Symbol` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -34,6 +34,7 @@ const matchSymbols = buildString({ 0x0006DE, 0x0006E9, 0x0007F6, + 0x000888, 0x000AF1, 0x000B70, 0x000C7F, @@ -61,6 +62,7 @@ const matchSymbols = buildString({ 0x003250, 0x00AB5B, 0x00FB29, + 0x00FDCF, 0x00FE62, 0x00FE69, 0x00FF04, @@ -89,7 +91,8 @@ const matchSymbols = buildString({ 0x01E2FF, 0x01ECAC, 0x01ECB0, - 0x01ED2E + 0x01ED2E, + 0x01F7F0 ], ranges: [ [0x00003C, 0x00003E], @@ -128,7 +131,7 @@ const matchSymbols = buildString({ [0x001FFD, 0x001FFE], [0x00207A, 0x00207C], [0x00208A, 0x00208C], - [0x0020A0, 0x0020BF], + [0x0020A0, 0x0020C0], [0x002100, 0x002101], [0x002103, 0x002106], [0x002108, 0x002109], @@ -179,8 +182,9 @@ const matchSymbols = buildString({ [0x00A836, 0x00A839], [0x00AA77, 0x00AA79], [0x00AB6A, 0x00AB6B], - [0x00FBB2, 0x00FBC1], - [0x00FDFC, 0x00FDFD], + [0x00FBB2, 0x00FBC2], + [0x00FD40, 0x00FD4F], + [0x00FDFC, 0x00FDFF], [0x00FE64, 0x00FE66], [0x00FF1C, 0x00FF1E], [0x00FFE0, 0x00FFE6], @@ -194,13 +198,14 @@ const matchSymbols = buildString({ [0x010877, 0x010878], [0x011FD5, 0x011FF1], [0x016B3C, 0x016B3F], + [0x01CF50, 0x01CFC3], [0x01D000, 0x01D0F5], [0x01D100, 0x01D126], [0x01D129, 0x01D164], [0x01D16A, 0x01D16C], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], - [0x01D1AE, 0x01D1E8], + [0x01D1AE, 0x01D1EA], [0x01D200, 0x01D241], [0x01D300, 0x01D356], [0x01D800, 0x01D9FF], @@ -222,7 +227,7 @@ const matchSymbols = buildString({ [0x01F250, 0x01F251], [0x01F260, 0x01F265], [0x01F300, 0x01F6D7], - [0x01F6E0, 0x01F6EC], + [0x01F6DD, 0x01F6EC], [0x01F6F0, 0x01F6FC], [0x01F700, 0x01F773], [0x01F780, 0x01F7D8], @@ -233,17 +238,17 @@ const matchSymbols = buildString({ [0x01F860, 0x01F887], [0x01F890, 0x01F8AD], [0x01F8B0, 0x01F8B1], - [0x01F900, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01FA53], + [0x01F900, 0x01FA53], [0x01FA60, 0x01FA6D], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6], + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6], [0x01FB00, 0x01FB92], [0x01FB94, 0x01FBCA] ] @@ -311,8 +316,6 @@ const nonMatchSymbols = buildString({ 0x01DA84, 0x01F0C0, 0x01F0D0, - 0x01F979, - 0x01F9CC, 0x01FB93 ], ranges: [ @@ -344,7 +347,8 @@ const nonMatchSymbols = buildString({ [0x0006EA, 0x0006FC], [0x0006FF, 0x0007F5], [0x0007F7, 0x0007FD], - [0x000800, 0x0009F1], + [0x000800, 0x000887], + [0x000889, 0x0009F1], [0x0009F4, 0x0009F9], [0x0009FC, 0x000AF0], [0x000AF2, 0x000B6F], @@ -377,7 +381,7 @@ const nonMatchSymbols = buildString({ [0x002053, 0x002079], [0x00207D, 0x002089], [0x00208D, 0x00209F], - [0x0020C0, 0x0020FF], + [0x0020C1, 0x0020FF], [0x00210A, 0x002113], [0x002119, 0x00211D], [0x00212A, 0x00212D], @@ -431,8 +435,10 @@ const nonMatchSymbols = buildString({ [0x00AB6C, 0x00DBFF], [0x00E000, 0x00FB28], [0x00FB2A, 0x00FBB1], - [0x00FBC2, 0x00FDFB], - [0x00FDFE, 0x00FE61], + [0x00FBC3, 0x00FD3F], + [0x00FD50, 0x00FDCE], + [0x00FDD0, 0x00FDFB], + [0x00FE00, 0x00FE61], [0x00FE67, 0x00FE68], [0x00FE6A, 0x00FF03], [0x00FF05, 0x00FF0A], @@ -453,14 +459,15 @@ const nonMatchSymbols = buildString({ [0x011FF2, 0x016B3B], [0x016B40, 0x016B44], [0x016B46, 0x01BC9B], - [0x01BC9D, 0x01CFFF], + [0x01BC9D, 0x01CF4F], + [0x01CFC4, 0x01CFFF], [0x01D0F6, 0x01D0FF], [0x01D127, 0x01D128], [0x01D165, 0x01D169], [0x01D16D, 0x01D182], [0x01D185, 0x01D18B], [0x01D1AA, 0x01D1AD], - [0x01D1E9, 0x01D1FF], + [0x01D1EB, 0x01D1FF], [0x01D242, 0x01D244], [0x01D246, 0x01D2FF], [0x01D357, 0x01D6C0], @@ -493,12 +500,13 @@ const nonMatchSymbols = buildString({ [0x01F249, 0x01F24F], [0x01F252, 0x01F25F], [0x01F266, 0x01F2FF], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6ED, 0x01F6EF], [0x01F6FD, 0x01F6FF], [0x01F774, 0x01F77F], [0x01F7D9, 0x01F7DF], - [0x01F7EC, 0x01F7FF], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F7FF], [0x01F80C, 0x01F80F], [0x01F848, 0x01F84F], [0x01F85A, 0x01F85F], @@ -508,12 +516,14 @@ const nonMatchSymbols = buildString({ [0x01FA54, 0x01FA5F], [0x01FA6E, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x01FAFF], + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x01FAFF], [0x01FBCB, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Titlecase_Letter.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Titlecase_Letter.js index 783fd85fe68e..bdcc37085bac 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Titlecase_Letter.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Titlecase_Letter.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Titlecase_Letter` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Unassigned.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Unassigned.js index e75a91f740ef..86793a889b31 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Unassigned.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Unassigned.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Unassigned` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -20,11 +20,10 @@ const matchSymbols = buildString({ 0x0003A2, 0x000530, 0x000590, - 0x00061D, 0x00070E, 0x00083F, 0x00085F, - 0x0008B5, + 0x00088F, 0x000984, 0x0009A9, 0x0009B1, @@ -100,13 +99,11 @@ const matchSymbols = buildString({ 0x0012C1, 0x0012D7, 0x001311, - 0x00170D, 0x00176D, 0x001771, - 0x00180F, 0x00191F, 0x001A5F, - 0x001DFA, + 0x001B7F, 0x001F58, 0x001F5A, 0x001F5C, @@ -119,8 +116,6 @@ const matchSymbols = buildString({ 0x002065, 0x00208F, 0x002B96, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -135,6 +130,8 @@ const matchSymbols = buildString({ 0x003130, 0x00318F, 0x00321F, + 0x00A7D2, + 0x00A7D4, 0x00A9CE, 0x00A9FF, 0x00AB27, @@ -155,6 +152,15 @@ const matchSymbols = buildString({ 0x01003E, 0x01018F, 0x01039E, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x010856, @@ -194,8 +200,12 @@ const matchSymbols = buildString({ 0x01246F, 0x01342F, 0x016A5F, + 0x016ABF, 0x016B5A, 0x016B62, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -213,6 +223,10 @@ const matchSymbols = buildString({ 0x01E007, 0x01E022, 0x01E025, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -241,8 +255,6 @@ const matchSymbols = buildString({ 0x01EEAA, 0x01F0C0, 0x01F0D0, - 0x01F979, - 0x01F9CC, 0x01FB93 ], ranges: [ @@ -258,8 +270,8 @@ const matchSymbols = buildString({ [0x0007FB, 0x0007FC], [0x00082E, 0x00082F], [0x00085C, 0x00085D], - [0x00086B, 0x00089F], - [0x0008C8, 0x0008D2], + [0x00086B, 0x00086F], + [0x000892, 0x000897], [0x00098D, 0x00098E], [0x000991, 0x000992], [0x0009B3, 0x0009B5], @@ -304,14 +316,15 @@ const matchSymbols = buildString({ [0x000BD1, 0x000BD6], [0x000BD8, 0x000BE5], [0x000BFB, 0x000BFF], - [0x000C3A, 0x000C3C], + [0x000C3A, 0x000C3B], [0x000C4E, 0x000C54], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C64, 0x000C65], [0x000C70, 0x000C76], [0x000CBA, 0x000CBB], [0x000CCE, 0x000CD4], - [0x000CD7, 0x000CDD], + [0x000CD7, 0x000CDC], [0x000CE4, 0x000CE5], [0x000CF3, 0x000CFF], [0x000D50, 0x000D53], @@ -346,7 +359,7 @@ const matchSymbols = buildString({ [0x0013FE, 0x0013FF], [0x00169D, 0x00169F], [0x0016F9, 0x0016FF], - [0x001715, 0x00171F], + [0x001716, 0x00171E], [0x001737, 0x00173F], [0x001754, 0x00175F], [0x001774, 0x00177F], @@ -370,9 +383,8 @@ const matchSymbols = buildString({ [0x001A8A, 0x001A8F], [0x001A9A, 0x001A9F], [0x001AAE, 0x001AAF], - [0x001AC1, 0x001AFF], - [0x001B4C, 0x001B4F], - [0x001B7D, 0x001B7F], + [0x001ACF, 0x001AFF], + [0x001B4D, 0x001B4F], [0x001BF4, 0x001BFB], [0x001C38, 0x001C3A], [0x001C4A, 0x001C4C], @@ -389,7 +401,7 @@ const matchSymbols = buildString({ [0x001FF0, 0x001FF1], [0x002072, 0x002073], [0x00209D, 0x00209F], - [0x0020C0, 0x0020CF], + [0x0020C1, 0x0020CF], [0x0020F1, 0x0020FF], [0x00218C, 0x00218F], [0x002427, 0x00243F], @@ -401,20 +413,19 @@ const matchSymbols = buildString({ [0x002D68, 0x002D6E], [0x002D71, 0x002D7E], [0x002D97, 0x002D9F], - [0x002E53, 0x002E7F], + [0x002E5E, 0x002E7F], [0x002EF4, 0x002EFF], [0x002FD6, 0x002FEF], [0x002FFC, 0x002FFF], [0x003097, 0x003098], [0x003100, 0x003104], [0x0031E4, 0x0031EF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A48F], [0x00A4C7, 0x00A4CF], [0x00A62C, 0x00A63F], [0x00A6F8, 0x00A6FF], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A82D, 0x00A82F], [0x00A83A, 0x00A83F], [0x00A878, 0x00A87F], @@ -441,11 +452,10 @@ const matchSymbols = buildString({ [0x00FADA, 0x00FAFF], [0x00FB07, 0x00FB12], [0x00FB18, 0x00FB1C], - [0x00FBC2, 0x00FBD2], - [0x00FD40, 0x00FD4F], + [0x00FBC3, 0x00FBD2], [0x00FD90, 0x00FD91], - [0x00FDC8, 0x00FDEF], - [0x00FDFE, 0x00FDFF], + [0x00FDC8, 0x00FDCE], + [0x00FDD0, 0x00FDEF], [0x00FE1A, 0x00FE1F], [0x00FE6C, 0x00FE6F], [0x00FEFD, 0x00FEFE], @@ -478,10 +488,11 @@ const matchSymbols = buildString({ [0x0104FC, 0x0104FF], [0x010528, 0x01052F], [0x010564, 0x01056E], - [0x010570, 0x0105FF], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -515,12 +526,13 @@ const matchSymbols = buildString({ [0x010EAE, 0x010EAF], [0x010EB2, 0x010EFF], [0x010F28, 0x010F2F], - [0x010F5A, 0x010FAF], + [0x010F5A, 0x010F6F], + [0x010F8A, 0x010FAF], [0x010FCC, 0x010FDF], [0x010FF7, 0x010FFF], [0x01104E, 0x011051], - [0x011070, 0x01107E], - [0x0110C2, 0x0110CC], + [0x011076, 0x01107E], + [0x0110C3, 0x0110CC], [0x0110CE, 0x0110CF], [0x0110E9, 0x0110EF], [0x0110FA, 0x0110FF], @@ -549,11 +561,11 @@ const matchSymbols = buildString({ [0x011645, 0x01164F], [0x01165A, 0x01165F], [0x01166D, 0x01167F], - [0x0116B9, 0x0116BF], + [0x0116BA, 0x0116BF], [0x0116CA, 0x0116FF], [0x01171B, 0x01171C], [0x01172C, 0x01172F], - [0x011740, 0x0117FF], + [0x011747, 0x0117FF], [0x01183C, 0x01189F], [0x0118F3, 0x0118FE], [0x011907, 0x011908], @@ -565,7 +577,7 @@ const matchSymbols = buildString({ [0x0119D8, 0x0119D9], [0x0119E5, 0x0119FF], [0x011A48, 0x011A4F], - [0x011AA3, 0x011ABF], + [0x011AA3, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C46, 0x011C4F], [0x011C6D, 0x011C6F], @@ -581,12 +593,13 @@ const matchSymbols = buildString({ [0x011FF2, 0x011FFE], [0x01239A, 0x0123FF], [0x012475, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF3, 0x012FFF], [0x013439, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], [0x016A6A, 0x016A6D], - [0x016A70, 0x016ACF], + [0x016ACA, 0x016ACF], [0x016AEE, 0x016AEF], [0x016AF6, 0x016AFF], [0x016B46, 0x016B4F], @@ -600,8 +613,8 @@ const matchSymbols = buildString({ [0x016FF2, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -609,10 +622,13 @@ const matchSymbols = buildString({ [0x01BC7D, 0x01BC7F], [0x01BC89, 0x01BC8F], [0x01BC9A, 0x01BC9B], - [0x01BCA4, 0x01CFFF], + [0x01BCA4, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01CF4F], + [0x01CFC4, 0x01CFFF], [0x01D0F6, 0x01D0FF], [0x01D127, 0x01D128], - [0x01D1E9, 0x01D1FF], + [0x01D1EB, 0x01D1FF], [0x01D246, 0x01D2DF], [0x01D2F4, 0x01D2FF], [0x01D357, 0x01D35F], @@ -625,15 +641,17 @@ const matchSymbols = buildString({ [0x01D6A6, 0x01D6A7], [0x01D7CC, 0x01D7CD], [0x01DA8C, 0x01DA9A], - [0x01DAB0, 0x01DFFF], + [0x01DAB0, 0x01DEFF], + [0x01DF1F, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E0FF], [0x01E12D, 0x01E12F], [0x01E13E, 0x01E13F], [0x01E14A, 0x01E14D], - [0x01E150, 0x01E2BF], + [0x01E150, 0x01E28F], + [0x01E2AF, 0x01E2BF], [0x01E2FA, 0x01E2FE], - [0x01E300, 0x01E7FF], + [0x01E300, 0x01E7DF], [0x01E8C5, 0x01E8C6], [0x01E8D7, 0x01E8FF], [0x01E94C, 0x01E94F], @@ -659,12 +677,13 @@ const matchSymbols = buildString({ [0x01F249, 0x01F24F], [0x01F252, 0x01F25F], [0x01F266, 0x01F2FF], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6ED, 0x01F6EF], [0x01F6FD, 0x01F6FF], [0x01F774, 0x01F77F], [0x01F7D9, 0x01F7DF], - [0x01F7EC, 0x01F7FF], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F7FF], [0x01F80C, 0x01F80F], [0x01F848, 0x01F84F], [0x01F85A, 0x01F85F], @@ -674,16 +693,18 @@ const matchSymbols = buildString({ [0x01FA54, 0x01FA5F], [0x01FA6E, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x01FAFF], + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x01FAFF], [0x01FBCB, 0x01FBEF], [0x01FBFA, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], @@ -740,7 +761,7 @@ const nonMatchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000BD7, - 0x000CDE, + 0x000C5D, 0x000DBD, 0x000DCA, 0x000DD6, @@ -757,10 +778,11 @@ const nonMatchSymbols = buildString({ 0x001F5D, 0x002D27, 0x002D2D, + 0x00A7D3, 0x00FB3E, + 0x00FDCF, 0x00FEFF, 0x0101A0, - 0x01056F, 0x010808, 0x01083C, 0x01093F, @@ -791,6 +813,7 @@ const nonMatchSymbols = buildString({ 0x01EE5F, 0x01EE64, 0x01EE7E, + 0x01F7F0, 0x0E0001 ], ranges: [ @@ -806,8 +829,7 @@ const nonMatchSymbols = buildString({ [0x000591, 0x0005C7], [0x0005D0, 0x0005EA], [0x0005EF, 0x0005F4], - [0x000600, 0x00061C], - [0x00061E, 0x00070D], + [0x000600, 0x00070D], [0x00070F, 0x00074A], [0x00074D, 0x0007B1], [0x0007C0, 0x0007FA], @@ -815,9 +837,9 @@ const nonMatchSymbols = buildString({ [0x000830, 0x00083E], [0x000840, 0x00085B], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], - [0x0008D3, 0x000983], + [0x000870, 0x00088E], + [0x000890, 0x000891], + [0x000898, 0x000983], [0x000985, 0x00098C], [0x00098F, 0x000990], [0x000993, 0x0009A8], @@ -886,7 +908,7 @@ const nonMatchSymbols = buildString({ [0x000C0E, 0x000C10], [0x000C12, 0x000C28], [0x000C2A, 0x000C39], - [0x000C3D, 0x000C44], + [0x000C3C, 0x000C44], [0x000C46, 0x000C48], [0x000C4A, 0x000C4D], [0x000C55, 0x000C56], @@ -902,6 +924,7 @@ const nonMatchSymbols = buildString({ [0x000CC6, 0x000CC8], [0x000CCA, 0x000CCD], [0x000CD5, 0x000CD6], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE3], [0x000CE6, 0x000CEF], [0x000CF1, 0x000CF2], @@ -958,9 +981,8 @@ const nonMatchSymbols = buildString({ [0x0013F8, 0x0013FD], [0x001400, 0x00169C], [0x0016A0, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001714], - [0x001720, 0x001736], + [0x001700, 0x001715], + [0x00171F, 0x001736], [0x001740, 0x001753], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -968,8 +990,7 @@ const nonMatchSymbols = buildString({ [0x001780, 0x0017DD], [0x0017E0, 0x0017E9], [0x0017F0, 0x0017F9], - [0x001800, 0x00180E], - [0x001810, 0x001819], + [0x001800, 0x001819], [0x001820, 0x001878], [0x001880, 0x0018AA], [0x0018B0, 0x0018F5], @@ -987,9 +1008,9 @@ const nonMatchSymbols = buildString({ [0x001A7F, 0x001A89], [0x001A90, 0x001A99], [0x001AA0, 0x001AAD], - [0x001AB0, 0x001AC0], - [0x001B00, 0x001B4B], - [0x001B50, 0x001B7C], + [0x001AB0, 0x001ACE], + [0x001B00, 0x001B4C], + [0x001B50, 0x001B7E], [0x001B80, 0x001BF3], [0x001BFC, 0x001C37], [0x001C3B, 0x001C49], @@ -997,8 +1018,7 @@ const nonMatchSymbols = buildString({ [0x001C90, 0x001CBA], [0x001CBD, 0x001CC7], [0x001CD0, 0x001CFA], - [0x001D00, 0x001DF9], - [0x001DFB, 0x001F15], + [0x001D00, 0x001F15], [0x001F18, 0x001F1D], [0x001F20, 0x001F45], [0x001F48, 0x001F4D], @@ -1015,16 +1035,14 @@ const nonMatchSymbols = buildString({ [0x002066, 0x002071], [0x002074, 0x00208E], [0x002090, 0x00209C], - [0x0020A0, 0x0020BF], + [0x0020A0, 0x0020C0], [0x0020D0, 0x0020F0], [0x002100, 0x00218B], [0x002190, 0x002426], [0x002440, 0x00244A], [0x002460, 0x002B73], [0x002B76, 0x002B95], - [0x002B97, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CF3], + [0x002B97, 0x002CF3], [0x002CF9, 0x002D25], [0x002D30, 0x002D67], [0x002D6F, 0x002D70], @@ -1037,7 +1055,7 @@ const nonMatchSymbols = buildString({ [0x002DC8, 0x002DCE], [0x002DD0, 0x002DD6], [0x002DD8, 0x002DDE], - [0x002DE0, 0x002E52], + [0x002DE0, 0x002E5D], [0x002E80, 0x002E99], [0x002E9B, 0x002EF3], [0x002F00, 0x002FD5], @@ -1049,14 +1067,14 @@ const nonMatchSymbols = buildString({ [0x003131, 0x00318E], [0x003190, 0x0031E3], [0x0031F0, 0x00321E], - [0x003220, 0x009FFC], - [0x00A000, 0x00A48C], + [0x003220, 0x00A48C], [0x00A490, 0x00A4C6], [0x00A4D0, 0x00A62B], [0x00A640, 0x00A6F7], - [0x00A700, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A82C], + [0x00A700, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A82C], [0x00A830, 0x00A839], [0x00A840, 0x00A877], [0x00A880, 0x00A8C5], @@ -1091,12 +1109,10 @@ const nonMatchSymbols = buildString({ [0x00FB38, 0x00FB3C], [0x00FB40, 0x00FB41], [0x00FB43, 0x00FB44], - [0x00FB46, 0x00FBC1], - [0x00FBD3, 0x00FD3F], - [0x00FD50, 0x00FD8F], + [0x00FB46, 0x00FBC2], + [0x00FBD3, 0x00FD8F], [0x00FD92, 0x00FDC7], - [0x00FDF0, 0x00FDFD], - [0x00FE00, 0x00FE19], + [0x00FDF0, 0x00FE19], [0x00FE20, 0x00FE52], [0x00FE54, 0x00FE66], [0x00FE68, 0x00FE6B], @@ -1137,9 +1153,20 @@ const nonMatchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x01056F, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -1180,11 +1207,12 @@ const nonMatchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F27], [0x010F30, 0x010F59], + [0x010F70, 0x010F89], [0x010FB0, 0x010FCB], [0x010FE0, 0x010FF6], [0x011000, 0x01104D], - [0x011052, 0x01106F], - [0x01107F, 0x0110C1], + [0x011052, 0x011075], + [0x01107F, 0x0110C2], [0x0110D0, 0x0110E8], [0x0110F0, 0x0110F9], [0x011100, 0x011134], @@ -1222,11 +1250,11 @@ const nonMatchSymbols = buildString({ [0x011600, 0x011644], [0x011650, 0x011659], [0x011660, 0x01166C], - [0x011680, 0x0116B8], + [0x011680, 0x0116B9], [0x0116C0, 0x0116C9], [0x011700, 0x01171A], [0x01171D, 0x01172B], - [0x011730, 0x01173F], + [0x011730, 0x011746], [0x011800, 0x01183B], [0x0118A0, 0x0118F2], [0x0118FF, 0x011906], @@ -1241,7 +1269,7 @@ const nonMatchSymbols = buildString({ [0x0119DA, 0x0119E4], [0x011A00, 0x011A47], [0x011A50, 0x011AA2], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C36], [0x011C38, 0x011C45], @@ -1267,13 +1295,15 @@ const nonMatchSymbols = buildString({ [0x012400, 0x01246E], [0x012470, 0x012474], [0x012480, 0x012543], + [0x012F90, 0x012FF2], [0x013000, 0x01342E], [0x013430, 0x013438], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], [0x016A60, 0x016A69], - [0x016A6E, 0x016A6F], + [0x016A6E, 0x016ABE], + [0x016AC0, 0x016AC9], [0x016AD0, 0x016AED], [0x016AF0, 0x016AF5], [0x016B00, 0x016B45], @@ -1290,7 +1320,10 @@ const nonMatchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -1299,9 +1332,12 @@ const nonMatchSymbols = buildString({ [0x01BC80, 0x01BC88], [0x01BC90, 0x01BC99], [0x01BC9C, 0x01BCA3], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], + [0x01CF50, 0x01CFC3], [0x01D000, 0x01D0F5], [0x01D100, 0x01D126], - [0x01D129, 0x01D1E8], + [0x01D129, 0x01D1EA], [0x01D200, 0x01D245], [0x01D2E0, 0x01D2F3], [0x01D300, 0x01D356], @@ -1326,6 +1362,7 @@ const nonMatchSymbols = buildString({ [0x01D7CE, 0x01DA8B], [0x01DA9B, 0x01DA9F], [0x01DAA1, 0x01DAAF], + [0x01DF00, 0x01DF1E], [0x01E000, 0x01E006], [0x01E008, 0x01E018], [0x01E01B, 0x01E021], @@ -1335,7 +1372,12 @@ const nonMatchSymbols = buildString({ [0x01E130, 0x01E13D], [0x01E140, 0x01E149], [0x01E14E, 0x01E14F], + [0x01E290, 0x01E2AE], [0x01E2C0, 0x01E2F9], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E8C7, 0x01E8D6], [0x01E900, 0x01E94B], @@ -1374,7 +1416,7 @@ const nonMatchSymbols = buildString({ [0x01F250, 0x01F251], [0x01F260, 0x01F265], [0x01F300, 0x01F6D7], - [0x01F6E0, 0x01F6EC], + [0x01F6DD, 0x01F6EC], [0x01F6F0, 0x01F6FC], [0x01F700, 0x01F773], [0x01F780, 0x01F7D8], @@ -1385,22 +1427,22 @@ const nonMatchSymbols = buildString({ [0x01F860, 0x01F887], [0x01F890, 0x01F8AD], [0x01F8B0, 0x01F8B1], - [0x01F900, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01FA53], + [0x01F900, 0x01FA53], [0x01FA60, 0x01FA6D], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6], + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6], [0x01FB00, 0x01FB92], [0x01FB94, 0x01FBCA], [0x01FBF0, 0x01FBF9], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Uppercase_Letter.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Uppercase_Letter.js index 85d4825b11a1..685abf00208f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Uppercase_Letter.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Uppercase_Letter.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `General_Category=Uppercase_Letter` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -554,8 +554,12 @@ const matchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, + 0x00A7C0, 0x00A7C2, 0x00A7C9, + 0x00A7D0, + 0x00A7D6, + 0x00A7D8, 0x00A7F5, 0x01D49C, 0x01D4A2, @@ -613,7 +617,7 @@ const matchSymbols = buildString({ [0x00212A, 0x00212D], [0x002130, 0x002133], [0x00213E, 0x00213F], - [0x002C00, 0x002C2E], + [0x002C00, 0x002C2F], [0x002C62, 0x002C64], [0x002C6D, 0x002C70], [0x002C7E, 0x002C80], @@ -624,6 +628,10 @@ const matchSymbols = buildString({ [0x00FF21, 0x00FF3A], [0x010400, 0x010427], [0x0104B0, 0x0104D3], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], [0x010C80, 0x010CB2], [0x0118A0, 0x0118BF], [0x016E40, 0x016E5F], @@ -1208,8 +1216,14 @@ const nonMatchSymbols = buildString({ 0x00A7B9, 0x00A7BB, 0x00A7BD, + 0x00A7BF, + 0x00A7C1, 0x00A7C3, 0x00A7C8, + 0x00A7D7, + 0x01057B, + 0x01058B, + 0x010593, 0x01D49D, 0x01D4AD, 0x01D506, @@ -1284,7 +1298,7 @@ const nonMatchSymbols = buildString({ [0x002140, 0x002144], [0x002146, 0x002182], [0x002184, 0x002BFF], - [0x002C2F, 0x002C5F], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002C73, 0x002C74], [0x002C76, 0x002C7D], @@ -1298,13 +1312,15 @@ const nonMatchSymbols = buildString({ [0x00A787, 0x00A78A], [0x00A78E, 0x00A78F], [0x00A793, 0x00A795], - [0x00A7BF, 0x00A7C1], - [0x00A7CA, 0x00A7F4], + [0x00A7CA, 0x00A7CF], + [0x00A7D1, 0x00A7D5], + [0x00A7D9, 0x00A7F4], [0x00A7F6, 0x00DBFF], [0x00E000, 0x00FF20], [0x00FF3B, 0x0103FF], [0x010428, 0x0104AF], - [0x0104D4, 0x010C7F], + [0x0104D4, 0x01056F], + [0x010596, 0x010C7F], [0x010CB3, 0x01189F], [0x0118C0, 0x016E3F], [0x016E60, 0x01D3FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Base.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Base.js index babadafff013..558bff875e3c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Base.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Base.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Grapheme_Base` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -47,7 +47,7 @@ const matchSymbols = buildString({ 0x000BBF, 0x000BD0, 0x000C3D, - 0x000CDE, + 0x000C5D, 0x000D3D, 0x000DBD, 0x000E84, @@ -64,6 +64,7 @@ const matchSymbols = buildString({ 0x0010CD, 0x001258, 0x0012C0, + 0x001715, 0x0017B6, 0x0018AA, 0x001940, @@ -82,19 +83,21 @@ const matchSymbols = buildString({ 0x002D27, 0x002D2D, 0x00A673, + 0x00A7D3, 0x00AA4D, 0x00AAB1, 0x00AAC0, 0x00AAC2, 0x00FB1D, 0x00FB3E, + 0x00FDCF, 0x0101A0, - 0x01056F, 0x010808, 0x01083C, 0x01093F, 0x010EAD, 0x011000, + 0x011075, 0x01112C, 0x011235, 0x011288, @@ -110,7 +113,6 @@ const matchSymbols = buildString({ 0x01163E, 0x0116AC, 0x0116B6, - 0x0116B8, 0x011726, 0x011838, 0x01183B, @@ -152,7 +154,8 @@ const matchSymbols = buildString({ 0x01EE5D, 0x01EE5F, 0x01EE64, - 0x01EE7E + 0x01EE7E, + 0x01F7F0 ], ranges: [ [0x000020, 0x00007E], @@ -170,7 +173,7 @@ const matchSymbols = buildString({ [0x0005D0, 0x0005EA], [0x0005EF, 0x0005F4], [0x000606, 0x00060F], - [0x00061E, 0x00064A], + [0x00061D, 0x00064A], [0x000660, 0x00066F], [0x000671, 0x0006D5], [0x0006E5, 0x0006E6], @@ -183,8 +186,8 @@ const matchSymbols = buildString({ [0x000830, 0x00083E], [0x000840, 0x000858], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], + [0x000870, 0x00088E], + [0x0008A0, 0x0008C9], [0x000903, 0x000939], [0x00093D, 0x000940], [0x000949, 0x00094C], @@ -268,6 +271,7 @@ const matchSymbols = buildString({ [0x000CC3, 0x000CC4], [0x000CC7, 0x000CC8], [0x000CCA, 0x000CCB], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE1], [0x000CE6, 0x000CEF], [0x000CF1, 0x000CF2], @@ -340,10 +344,9 @@ const matchSymbols = buildString({ [0x0013F8, 0x0013FD], [0x001400, 0x00169C], [0x0016A0, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001711], - [0x001720, 0x001731], - [0x001735, 0x001736], + [0x001700, 0x001711], + [0x00171F, 0x001731], + [0x001734, 0x001736], [0x001740, 0x001751], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -379,9 +382,9 @@ const matchSymbols = buildString({ [0x001AA0, 0x001AAD], [0x001B04, 0x001B33], [0x001B3D, 0x001B41], - [0x001B43, 0x001B4B], + [0x001B43, 0x001B4C], [0x001B50, 0x001B6A], - [0x001B74, 0x001B7C], + [0x001B74, 0x001B7E], [0x001B82, 0x001BA1], [0x001BA6, 0x001BA7], [0x001BAE, 0x001BE5], @@ -416,15 +419,13 @@ const matchSymbols = buildString({ [0x002070, 0x002071], [0x002074, 0x00208E], [0x002090, 0x00209C], - [0x0020A0, 0x0020BF], + [0x0020A0, 0x0020C0], [0x002100, 0x00218B], [0x002190, 0x002426], [0x002440, 0x00244A], [0x002460, 0x002B73], [0x002B76, 0x002B95], - [0x002B97, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CEE], + [0x002B97, 0x002CEE], [0x002CF2, 0x002CF3], [0x002CF9, 0x002D25], [0x002D30, 0x002D67], @@ -438,7 +439,7 @@ const matchSymbols = buildString({ [0x002DC8, 0x002DCE], [0x002DD0, 0x002DD6], [0x002DD8, 0x002DDE], - [0x002E00, 0x002E52], + [0x002E00, 0x002E5D], [0x002E80, 0x002E99], [0x002E9B, 0x002EF3], [0x002F00, 0x002FD5], @@ -451,17 +452,17 @@ const matchSymbols = buildString({ [0x003131, 0x00318E], [0x003190, 0x0031E3], [0x0031F0, 0x00321E], - [0x003220, 0x009FFC], - [0x00A000, 0x00A48C], + [0x003220, 0x00A48C], [0x00A490, 0x00A4C6], [0x00A4D0, 0x00A62B], [0x00A640, 0x00A66E], [0x00A67E, 0x00A69D], [0x00A6A0, 0x00A6EF], [0x00A6F2, 0x00A6F7], - [0x00A700, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A801], + [0x00A700, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A801], [0x00A803, 0x00A805], [0x00A807, 0x00A80A], [0x00A80C, 0x00A824], @@ -515,11 +516,10 @@ const matchSymbols = buildString({ [0x00FB38, 0x00FB3C], [0x00FB40, 0x00FB41], [0x00FB43, 0x00FB44], - [0x00FB46, 0x00FBC1], - [0x00FBD3, 0x00FD3F], - [0x00FD50, 0x00FD8F], + [0x00FB46, 0x00FBC2], + [0x00FBD3, 0x00FD8F], [0x00FD92, 0x00FDC7], - [0x00FDF0, 0x00FDFD], + [0x00FDF0, 0x00FDFF], [0x00FE10, 0x00FE19], [0x00FE30, 0x00FE52], [0x00FE54, 0x00FE66], @@ -562,9 +562,20 @@ const matchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x01056F, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -603,11 +614,14 @@ const matchSymbols = buildString({ [0x010F00, 0x010F27], [0x010F30, 0x010F45], [0x010F51, 0x010F59], + [0x010F70, 0x010F81], + [0x010F86, 0x010F89], [0x010FB0, 0x010FCB], [0x010FE0, 0x010FF6], [0x011002, 0x011037], [0x011047, 0x01104D], [0x011052, 0x01106F], + [0x011071, 0x011072], [0x011082, 0x0110B2], [0x0110B7, 0x0110B8], [0x0110BB, 0x0110BC], @@ -665,10 +679,11 @@ const matchSymbols = buildString({ [0x011660, 0x01166C], [0x011680, 0x0116AA], [0x0116AE, 0x0116AF], + [0x0116B8, 0x0116B9], [0x0116C0, 0x0116C9], [0x011700, 0x01171A], [0x011720, 0x011721], - [0x011730, 0x01173F], + [0x011730, 0x011746], [0x011800, 0x01182E], [0x0118A0, 0x0118F2], [0x0118FF, 0x011906], @@ -690,7 +705,7 @@ const matchSymbols = buildString({ [0x011A57, 0x011A58], [0x011A5C, 0x011A89], [0x011A9A, 0x011AA2], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C2F], [0x011C40, 0x011C45], @@ -712,12 +727,14 @@ const matchSymbols = buildString({ [0x012400, 0x01246E], [0x012470, 0x012474], [0x012480, 0x012543], + [0x012F90, 0x012FF2], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], [0x016A60, 0x016A69], - [0x016A6E, 0x016A6F], + [0x016A6E, 0x016ABE], + [0x016AC0, 0x016AC9], [0x016AD0, 0x016AED], [0x016B00, 0x016B2F], [0x016B37, 0x016B45], @@ -734,7 +751,10 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -742,13 +762,14 @@ const matchSymbols = buildString({ [0x01BC70, 0x01BC7C], [0x01BC80, 0x01BC88], [0x01BC90, 0x01BC99], + [0x01CF50, 0x01CFC3], [0x01D000, 0x01D0F5], [0x01D100, 0x01D126], [0x01D129, 0x01D164], [0x01D16A, 0x01D16D], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], - [0x01D1AE, 0x01D1E8], + [0x01D1AE, 0x01D1EA], [0x01D200, 0x01D241], [0x01D2E0, 0x01D2F3], [0x01D300, 0x01D356], @@ -775,12 +796,18 @@ const matchSymbols = buildString({ [0x01DA6D, 0x01DA74], [0x01DA76, 0x01DA83], [0x01DA85, 0x01DA8B], + [0x01DF00, 0x01DF1E], [0x01E100, 0x01E12C], [0x01E137, 0x01E13D], [0x01E140, 0x01E149], [0x01E14E, 0x01E14F], + [0x01E290, 0x01E2AD], [0x01E2C0, 0x01E2EB], [0x01E2F0, 0x01E2F9], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E8C7, 0x01E8CF], [0x01E900, 0x01E943], @@ -819,7 +846,7 @@ const matchSymbols = buildString({ [0x01F250, 0x01F251], [0x01F260, 0x01F265], [0x01F300, 0x01F6D7], - [0x01F6E0, 0x01F6EC], + [0x01F6DD, 0x01F6EC], [0x01F6F0, 0x01F6FC], [0x01F700, 0x01F773], [0x01F780, 0x01F7D8], @@ -830,22 +857,22 @@ const matchSymbols = buildString({ [0x01F860, 0x01F887], [0x01F890, 0x01F8AD], [0x01F8B0, 0x01F8B1], - [0x01F900, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01FA53], + [0x01F900, 0x01FA53], [0x01FA60, 0x01FA6D], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6], + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6], [0x01FB00, 0x01FB92], [0x01FB94, 0x01FBCA], [0x01FBF0, 0x01FBF9], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -872,11 +899,11 @@ const nonMatchSymbols = buildString({ 0x0003A2, 0x000530, 0x0005BF, + 0x00061C, 0x000670, 0x000711, 0x00083F, 0x00085F, - 0x0008B5, 0x00093A, 0x00093C, 0x00094D, @@ -962,7 +989,6 @@ const nonMatchSymbols = buildString({ 0x0012C1, 0x0012D7, 0x001311, - 0x00170D, 0x00176D, 0x0017C6, 0x0018A9, @@ -986,8 +1012,6 @@ const nonMatchSymbols = buildString({ 0x001FFF, 0x00208F, 0x002B96, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -1001,6 +1025,8 @@ const nonMatchSymbols = buildString({ 0x003130, 0x00318F, 0x00321F, + 0x00A7D2, + 0x00A7D4, 0x00A802, 0x00A806, 0x00A80B, @@ -1034,6 +1060,15 @@ const nonMatchSymbols = buildString({ 0x01003E, 0x01018F, 0x01039E, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x010856, @@ -1042,6 +1077,7 @@ const nonMatchSymbols = buildString({ 0x010A18, 0x010E7F, 0x011001, + 0x011070, 0x0110BD, 0x011173, 0x0111CF, @@ -1087,8 +1123,12 @@ const nonMatchSymbols = buildString({ 0x011D97, 0x01246F, 0x016A5F, + 0x016ABF, 0x016B5A, 0x016B62, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D165, 0x01D455, 0x01D49D, @@ -1105,6 +1145,10 @@ const nonMatchSymbols = buildString({ 0x01D551, 0x01DA75, 0x01DA84, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -1133,8 +1177,6 @@ const nonMatchSymbols = buildString({ 0x01EEAA, 0x01F0C0, 0x01F0D0, - 0x01F979, - 0x01F9CC, 0x01FB93 ], ranges: [ @@ -1154,7 +1196,6 @@ const nonMatchSymbols = buildString({ [0x0005EB, 0x0005EE], [0x0005F5, 0x000605], [0x000610, 0x00061A], - [0x00061C, 0x00061D], [0x00064B, 0x00065F], [0x0006D6, 0x0006DD], [0x0006DF, 0x0006E4], @@ -1171,8 +1212,9 @@ const nonMatchSymbols = buildString({ [0x000825, 0x000827], [0x000829, 0x00082F], [0x000859, 0x00085D], - [0x00086B, 0x00089F], - [0x0008C8, 0x000902], + [0x00086B, 0x00086F], + [0x00088F, 0x00089F], + [0x0008CA, 0x000902], [0x000941, 0x000948], [0x000951, 0x000957], [0x000962, 0x000963], @@ -1221,12 +1263,13 @@ const nonMatchSymbols = buildString({ [0x000C3A, 0x000C3C], [0x000C3E, 0x000C40], [0x000C45, 0x000C57], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C62, 0x000C65], [0x000C70, 0x000C76], [0x000CBA, 0x000CBC], [0x000CC5, 0x000CC6], - [0x000CCC, 0x000CDD], + [0x000CCC, 0x000CDC], [0x000CE2, 0x000CE5], [0x000CF3, 0x000D01], [0x000D3B, 0x000D3C], @@ -1278,8 +1321,9 @@ const nonMatchSymbols = buildString({ [0x0013FE, 0x0013FF], [0x00169D, 0x00169F], [0x0016F9, 0x0016FF], - [0x001712, 0x00171F], - [0x001732, 0x001734], + [0x001712, 0x001714], + [0x001716, 0x00171E], + [0x001732, 0x001733], [0x001737, 0x00173F], [0x001752, 0x00175F], [0x001771, 0x00177F], @@ -1314,9 +1358,9 @@ const nonMatchSymbols = buildString({ [0x001A9A, 0x001A9F], [0x001AAE, 0x001B03], [0x001B34, 0x001B3A], - [0x001B4C, 0x001B4F], + [0x001B4D, 0x001B4F], [0x001B6B, 0x001B73], - [0x001B7D, 0x001B81], + [0x001B7F, 0x001B81], [0x001BA2, 0x001BA5], [0x001BA8, 0x001BA9], [0x001BAB, 0x001BAD], @@ -1346,7 +1390,7 @@ const nonMatchSymbols = buildString({ [0x002060, 0x00206F], [0x002072, 0x002073], [0x00209D, 0x00209F], - [0x0020C0, 0x0020FF], + [0x0020C1, 0x0020FF], [0x00218C, 0x00218F], [0x002427, 0x00243F], [0x00244B, 0x00245F], @@ -1359,7 +1403,7 @@ const nonMatchSymbols = buildString({ [0x002D71, 0x002D7F], [0x002D97, 0x002D9F], [0x002DDF, 0x002DFF], - [0x002E53, 0x002E7F], + [0x002E5E, 0x002E7F], [0x002EF4, 0x002EFF], [0x002FD6, 0x002FEF], [0x002FFC, 0x002FFF], @@ -1367,7 +1411,6 @@ const nonMatchSymbols = buildString({ [0x003097, 0x00309A], [0x003100, 0x003104], [0x0031E4, 0x0031EF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A48F], [0x00A4C7, 0x00A4CF], [0x00A62C, 0x00A63F], @@ -1376,8 +1419,8 @@ const nonMatchSymbols = buildString({ [0x00A69E, 0x00A69F], [0x00A6F0, 0x00A6F1], [0x00A6F8, 0x00A6FF], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A825, 0x00A826], [0x00A82C, 0x00A82F], [0x00A83A, 0x00A83F], @@ -1416,11 +1459,11 @@ const nonMatchSymbols = buildString({ [0x00FADA, 0x00FAFF], [0x00FB07, 0x00FB12], [0x00FB18, 0x00FB1C], - [0x00FBC2, 0x00FBD2], - [0x00FD40, 0x00FD4F], + [0x00FBC3, 0x00FBD2], [0x00FD90, 0x00FD91], - [0x00FDC8, 0x00FDEF], - [0x00FDFE, 0x00FE0F], + [0x00FDC8, 0x00FDCE], + [0x00FDD0, 0x00FDEF], + [0x00FE00, 0x00FE0F], [0x00FE1A, 0x00FE2F], [0x00FE6C, 0x00FE6F], [0x00FEFD, 0x00FF00], @@ -1454,10 +1497,11 @@ const nonMatchSymbols = buildString({ [0x0104FC, 0x0104FF], [0x010528, 0x01052F], [0x010564, 0x01056E], - [0x010570, 0x0105FF], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -1492,12 +1536,15 @@ const nonMatchSymbols = buildString({ [0x010EB2, 0x010EFF], [0x010F28, 0x010F2F], [0x010F46, 0x010F50], - [0x010F5A, 0x010FAF], + [0x010F5A, 0x010F6F], + [0x010F82, 0x010F85], + [0x010F8A, 0x010FAF], [0x010FCC, 0x010FDF], [0x010FF7, 0x010FFF], [0x011038, 0x011046], [0x01104E, 0x011051], - [0x011070, 0x011081], + [0x011073, 0x011074], + [0x011076, 0x011081], [0x0110B3, 0x0110B6], [0x0110B9, 0x0110BA], [0x0110C2, 0x0110CF], @@ -1542,12 +1589,12 @@ const nonMatchSymbols = buildString({ [0x01165A, 0x01165F], [0x01166D, 0x01167F], [0x0116B0, 0x0116B5], - [0x0116B9, 0x0116BF], + [0x0116BA, 0x0116BF], [0x0116CA, 0x0116FF], [0x01171B, 0x01171F], [0x011722, 0x011725], [0x011727, 0x01172F], - [0x011740, 0x0117FF], + [0x011747, 0x0117FF], [0x01182F, 0x011837], [0x011839, 0x01183A], [0x01183C, 0x01189F], @@ -1568,7 +1615,7 @@ const nonMatchSymbols = buildString({ [0x011A59, 0x011A5B], [0x011A8A, 0x011A96], [0x011A98, 0x011A99], - [0x011AA3, 0x011ABF], + [0x011AA3, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C30, 0x011C3D], [0x011C46, 0x011C4F], @@ -1589,12 +1636,13 @@ const nonMatchSymbols = buildString({ [0x011FF2, 0x011FFE], [0x01239A, 0x0123FF], [0x012475, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF3, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], [0x016A6A, 0x016A6D], - [0x016A70, 0x016ACF], + [0x016ACA, 0x016ACF], [0x016AEE, 0x016AF4], [0x016AF6, 0x016AFF], [0x016B30, 0x016B36], @@ -1609,8 +1657,8 @@ const nonMatchSymbols = buildString({ [0x016FF2, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -1619,14 +1667,15 @@ const nonMatchSymbols = buildString({ [0x01BC89, 0x01BC8F], [0x01BC9A, 0x01BC9B], [0x01BC9D, 0x01BC9E], - [0x01BCA0, 0x01CFFF], + [0x01BCA0, 0x01CF4F], + [0x01CFC4, 0x01CFFF], [0x01D0F6, 0x01D0FF], [0x01D127, 0x01D128], [0x01D167, 0x01D169], [0x01D16E, 0x01D182], [0x01D185, 0x01D18B], [0x01D1AA, 0x01D1AD], - [0x01D1E9, 0x01D1FF], + [0x01D1EB, 0x01D1FF], [0x01D242, 0x01D244], [0x01D246, 0x01D2DF], [0x01D2F4, 0x01D2FF], @@ -1641,14 +1690,16 @@ const nonMatchSymbols = buildString({ [0x01D7CC, 0x01D7CD], [0x01DA00, 0x01DA36], [0x01DA3B, 0x01DA6C], - [0x01DA8C, 0x01E0FF], + [0x01DA8C, 0x01DEFF], + [0x01DF1F, 0x01E0FF], [0x01E12D, 0x01E136], [0x01E13E, 0x01E13F], [0x01E14A, 0x01E14D], - [0x01E150, 0x01E2BF], + [0x01E150, 0x01E28F], + [0x01E2AE, 0x01E2BF], [0x01E2EC, 0x01E2EF], [0x01E2FA, 0x01E2FE], - [0x01E300, 0x01E7FF], + [0x01E300, 0x01E7DF], [0x01E8C5, 0x01E8C6], [0x01E8D0, 0x01E8FF], [0x01E944, 0x01E94A], @@ -1675,12 +1726,13 @@ const nonMatchSymbols = buildString({ [0x01F249, 0x01F24F], [0x01F252, 0x01F25F], [0x01F266, 0x01F2FF], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6ED, 0x01F6EF], [0x01F6FD, 0x01F6FF], [0x01F774, 0x01F77F], [0x01F7D9, 0x01F7DF], - [0x01F7EC, 0x01F7FF], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F7FF], [0x01F80C, 0x01F80F], [0x01F848, 0x01F84F], [0x01F85A, 0x01F85F], @@ -1690,16 +1742,18 @@ const nonMatchSymbols = buildString({ [0x01FA54, 0x01FA5F], [0x01FA6E, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x01FAFF], + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x01FAFF], [0x01FBCB, 0x01FBEF], [0x01FBFA, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Extend.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Extend.js index a767c366a7e2..8456dd32f9b8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Extend.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Extend.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Grapheme_Extend` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -44,6 +44,7 @@ const matchSymbols = buildString({ 0x000BD7, 0x000C00, 0x000C04, + 0x000C3C, 0x000C81, 0x000CBC, 0x000CBF, @@ -68,6 +69,7 @@ const matchSymbols = buildString({ 0x00109D, 0x0017C6, 0x0017DD, + 0x00180F, 0x0018A9, 0x001932, 0x001A1B, @@ -104,6 +106,8 @@ const matchSymbols = buildString({ 0x0102E0, 0x010A3F, 0x011001, + 0x011070, + 0x0110C2, 0x011173, 0x0111CF, 0x011234, @@ -136,7 +140,8 @@ const matchSymbols = buildString({ 0x016FE4, 0x01D165, 0x01DA75, - 0x01DA84 + 0x01DA84, + 0x01E2AE ], ranges: [ [0x000300, 0x00036F], @@ -158,7 +163,8 @@ const matchSymbols = buildString({ [0x000825, 0x000827], [0x000829, 0x00082D], [0x000859, 0x00085B], - [0x0008D3, 0x0008E1], + [0x000898, 0x00089F], + [0x0008CA, 0x0008E1], [0x0008E3, 0x000902], [0x000941, 0x000948], [0x000951, 0x000957], @@ -212,7 +218,7 @@ const matchSymbols = buildString({ [0x001085, 0x001086], [0x00135D, 0x00135F], [0x001712, 0x001714], - [0x001732, 0x001734], + [0x001732, 0x001733], [0x001752, 0x001753], [0x001772, 0x001773], [0x0017B4, 0x0017B5], @@ -227,7 +233,7 @@ const matchSymbols = buildString({ [0x001A58, 0x001A5E], [0x001A65, 0x001A6C], [0x001A73, 0x001A7C], - [0x001AB0, 0x001AC0], + [0x001AB0, 0x001ACE], [0x001B00, 0x001B03], [0x001B34, 0x001B3A], [0x001B6B, 0x001B73], @@ -243,8 +249,7 @@ const matchSymbols = buildString({ [0x001CD4, 0x001CE0], [0x001CE2, 0x001CE8], [0x001CF8, 0x001CF9], - [0x001DC0, 0x001DF9], - [0x001DFB, 0x001DFF], + [0x001DC0, 0x001DFF], [0x0020D0, 0x0020F0], [0x002CEF, 0x002CF1], [0x002DE0, 0x002DFF], @@ -281,7 +286,9 @@ const matchSymbols = buildString({ [0x010D24, 0x010D27], [0x010EAB, 0x010EAC], [0x010F46, 0x010F50], + [0x010F82, 0x010F85], [0x011038, 0x011046], + [0x011073, 0x011074], [0x01107F, 0x011081], [0x0110B3, 0x0110B6], [0x0110B9, 0x0110BA], @@ -340,6 +347,8 @@ const matchSymbols = buildString({ [0x016B30, 0x016B36], [0x016F8F, 0x016F92], [0x01BC9D, 0x01BC9E], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D167, 0x01D169], [0x01D16E, 0x01D172], [0x01D17B, 0x01D182], @@ -392,6 +401,7 @@ const nonMatchSymbols = buildString({ 0x000B3D, 0x000B40, 0x000BBF, + 0x000C3D, 0x000C49, 0x000D3D, 0x000DD5, @@ -403,6 +413,7 @@ const nonMatchSymbols = buildString({ 0x001031, 0x001038, 0x0017B6, + 0x00180E, 0x001A57, 0x001A5F, 0x001A61, @@ -412,7 +423,6 @@ const nonMatchSymbols = buildString({ 0x001BEE, 0x001CD3, 0x001CE1, - 0x001DFA, 0x00A673, 0x00AAB1, 0x00AAC0, @@ -465,7 +475,8 @@ const nonMatchSymbols = buildString({ [0x0007F4, 0x0007FC], [0x0007FE, 0x000815], [0x00082E, 0x000858], - [0x00085C, 0x0008D2], + [0x00085C, 0x000897], + [0x0008A0, 0x0008C9], [0x000903, 0x000939], [0x00093D, 0x000940], [0x000949, 0x00094C], @@ -502,7 +513,7 @@ const nonMatchSymbols = buildString({ [0x000BCE, 0x000BD6], [0x000BD8, 0x000BFF], [0x000C01, 0x000C03], - [0x000C05, 0x000C3D], + [0x000C05, 0x000C3B], [0x000C41, 0x000C45], [0x000C4E, 0x000C54], [0x000C57, 0x000C61], @@ -548,14 +559,14 @@ const nonMatchSymbols = buildString({ [0x00109E, 0x00135C], [0x001360, 0x001711], [0x001715, 0x001731], - [0x001735, 0x001751], + [0x001734, 0x001751], [0x001754, 0x001771], [0x001774, 0x0017B3], [0x0017BE, 0x0017C5], [0x0017C7, 0x0017C8], [0x0017D4, 0x0017DC], [0x0017DE, 0x00180A], - [0x00180E, 0x001884], + [0x001810, 0x001884], [0x001887, 0x0018A8], [0x0018AA, 0x00191F], [0x001923, 0x001926], @@ -568,7 +579,7 @@ const nonMatchSymbols = buildString({ [0x001A6D, 0x001A72], [0x001A7D, 0x001A7E], [0x001A80, 0x001AAF], - [0x001AC1, 0x001AFF], + [0x001ACF, 0x001AFF], [0x001B04, 0x001B33], [0x001B3D, 0x001B41], [0x001B43, 0x001B6A], @@ -639,12 +650,16 @@ const nonMatchSymbols = buildString({ [0x010AE7, 0x010D23], [0x010D28, 0x010EAA], [0x010EAD, 0x010F45], - [0x010F51, 0x011000], + [0x010F51, 0x010F81], + [0x010F86, 0x011000], [0x011002, 0x011037], - [0x011047, 0x01107E], + [0x011047, 0x01106F], + [0x011071, 0x011072], + [0x011075, 0x01107E], [0x011082, 0x0110B2], [0x0110B7, 0x0110B8], - [0x0110BB, 0x0110FF], + [0x0110BB, 0x0110C1], + [0x0110C3, 0x0110FF], [0x011103, 0x011126], [0x011135, 0x011172], [0x011174, 0x01117F], @@ -705,7 +720,9 @@ const nonMatchSymbols = buildString({ [0x016F50, 0x016F8E], [0x016F93, 0x016FE3], [0x016FE5, 0x01BC9C], - [0x01BC9F, 0x01D164], + [0x01BC9F, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D164], [0x01D16A, 0x01D16D], [0x01D173, 0x01D17A], [0x01D183, 0x01D184], @@ -719,7 +736,8 @@ const nonMatchSymbols = buildString({ [0x01DAB0, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E12F], - [0x01E137, 0x01E2EB], + [0x01E137, 0x01E2AD], + [0x01E2AF, 0x01E2EB], [0x01E2F0, 0x01E8CF], [0x01E8D7, 0x01E943], [0x01E94B, 0x0E001F], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Hex_Digit.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Hex_Digit.js index 81b5ddb7572a..cb8bf115cf6d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Hex_Digit.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Hex_Digit.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Hex_Digit` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Binary_Operator.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Binary_Operator.js index f14ebc4a2ac4..8bf2e9cebf2c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Binary_Operator.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Binary_Operator.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `IDS_Binary_Operator` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Trinary_Operator.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Trinary_Operator.js index a8c33b0925e6..12f0a862acc9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Trinary_Operator.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Trinary_Operator.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `IDS_Trinary_Operator` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Continue.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Continue.js index fe1576508455..d0b0f21797d9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Continue.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Continue.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `ID_Continue` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -42,7 +42,7 @@ const matchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000BD7, - 0x000CDE, + 0x000C5D, 0x000DBD, 0x000DCA, 0x000DD6, @@ -78,6 +78,7 @@ const matchSymbols = buildString({ 0x002D27, 0x002D2D, 0x002D6F, + 0x00A7D3, 0x00A82C, 0x00A8FB, 0x00FB3E, @@ -88,6 +89,7 @@ const matchSymbols = buildString({ 0x01083C, 0x010A3F, 0x010F27, + 0x0110C2, 0x011176, 0x0111DC, 0x01123E, @@ -161,9 +163,9 @@ const matchSymbols = buildString({ [0x000800, 0x00082D], [0x000840, 0x00085B], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], - [0x0008D3, 0x0008E1], + [0x000870, 0x000887], + [0x000889, 0x00088E], + [0x000898, 0x0008E1], [0x0008E3, 0x000963], [0x000966, 0x00096F], [0x000971, 0x000983], @@ -235,7 +237,7 @@ const matchSymbols = buildString({ [0x000C0E, 0x000C10], [0x000C12, 0x000C28], [0x000C2A, 0x000C39], - [0x000C3D, 0x000C44], + [0x000C3C, 0x000C44], [0x000C46, 0x000C48], [0x000C4A, 0x000C4D], [0x000C55, 0x000C56], @@ -252,6 +254,7 @@ const matchSymbols = buildString({ [0x000CC6, 0x000CC8], [0x000CCA, 0x000CCD], [0x000CD5, 0x000CD6], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE3], [0x000CE6, 0x000CEF], [0x000CF1, 0x000CF2], @@ -319,9 +322,8 @@ const matchSymbols = buildString({ [0x001681, 0x00169A], [0x0016A0, 0x0016EA], [0x0016EE, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001714], - [0x001720, 0x001734], + [0x001700, 0x001715], + [0x00171F, 0x001734], [0x001740, 0x001753], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -330,7 +332,7 @@ const matchSymbols = buildString({ [0x0017DC, 0x0017DD], [0x0017E0, 0x0017E9], [0x00180B, 0x00180D], - [0x001810, 0x001819], + [0x00180F, 0x001819], [0x001820, 0x001878], [0x001880, 0x0018AA], [0x0018B0, 0x0018F5], @@ -348,8 +350,8 @@ const matchSymbols = buildString({ [0x001A7F, 0x001A89], [0x001A90, 0x001A99], [0x001AB0, 0x001ABD], - [0x001ABF, 0x001AC0], - [0x001B00, 0x001B4B], + [0x001ABF, 0x001ACE], + [0x001B00, 0x001B4C], [0x001B50, 0x001B59], [0x001B6B, 0x001B73], [0x001B80, 0x001BF3], @@ -361,8 +363,7 @@ const matchSymbols = buildString({ [0x001CBD, 0x001CBF], [0x001CD0, 0x001CD2], [0x001CD4, 0x001CFA], - [0x001D00, 0x001DF9], - [0x001DFB, 0x001F15], + [0x001D00, 0x001F15], [0x001F18, 0x001F1D], [0x001F20, 0x001F45], [0x001F48, 0x001F4D], @@ -387,9 +388,7 @@ const matchSymbols = buildString({ [0x00213C, 0x00213F], [0x002145, 0x002149], [0x002160, 0x002188], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CE4], + [0x002C00, 0x002CE4], [0x002CEB, 0x002CF3], [0x002D00, 0x002D25], [0x002D30, 0x002D67], @@ -416,8 +415,7 @@ const matchSymbols = buildString({ [0x0031A0, 0x0031BF], [0x0031F0, 0x0031FF], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], - [0x00A000, 0x00A48C], + [0x004E00, 0x00A48C], [0x00A4D0, 0x00A4FD], [0x00A500, 0x00A60C], [0x00A610, 0x00A62B], @@ -426,9 +424,10 @@ const matchSymbols = buildString({ [0x00A67F, 0x00A6F1], [0x00A717, 0x00A71F], [0x00A722, 0x00A788], - [0x00A78B, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A827], + [0x00A78B, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A827], [0x00A840, 0x00A873], [0x00A880, 0x00A8C5], [0x00A8D0, 0x00A8D9], @@ -511,9 +510,20 @@ const matchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -550,10 +560,11 @@ const matchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F1C], [0x010F30, 0x010F50], + [0x010F70, 0x010F85], [0x010FB0, 0x010FC4], [0x010FE0, 0x010FF6], [0x011000, 0x011046], - [0x011066, 0x01106F], + [0x011066, 0x011075], [0x01107F, 0x0110BA], [0x0110D0, 0x0110E8], [0x0110F0, 0x0110F9], @@ -600,6 +611,7 @@ const matchSymbols = buildString({ [0x011700, 0x01171A], [0x01171D, 0x01172B], [0x011730, 0x011739], + [0x011740, 0x011746], [0x011800, 0x01183A], [0x0118A0, 0x0118E9], [0x0118FF, 0x011906], @@ -615,7 +627,7 @@ const matchSymbols = buildString({ [0x0119E3, 0x0119E4], [0x011A00, 0x011A3E], [0x011A50, 0x011A99], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C36], [0x011C38, 0x011C40], @@ -639,11 +651,14 @@ const matchSymbols = buildString({ [0x012000, 0x012399], [0x012400, 0x01246E], [0x012480, 0x012543], + [0x012F90, 0x012FF0], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], [0x016A60, 0x016A69], + [0x016A70, 0x016ABE], + [0x016AC0, 0x016AC9], [0x016AD0, 0x016AED], [0x016AF0, 0x016AF4], [0x016B00, 0x016B36], @@ -661,7 +676,10 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -670,6 +688,8 @@ const matchSymbols = buildString({ [0x01BC80, 0x01BC88], [0x01BC90, 0x01BC99], [0x01BC9D, 0x01BC9E], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D165, 0x01D169], [0x01D16D, 0x01D172], [0x01D17B, 0x01D182], @@ -708,6 +728,7 @@ const matchSymbols = buildString({ [0x01DA3B, 0x01DA6C], [0x01DA9B, 0x01DA9F], [0x01DAA1, 0x01DAAF], + [0x01DF00, 0x01DF1E], [0x01E000, 0x01E006], [0x01E008, 0x01E018], [0x01E01B, 0x01E021], @@ -716,7 +737,12 @@ const matchSymbols = buildString({ [0x01E100, 0x01E12C], [0x01E130, 0x01E13D], [0x01E140, 0x01E149], + [0x01E290, 0x01E2AE], [0x01E2C0, 0x01E2F9], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E8D0, 0x01E8D6], [0x01E900, 0x01E94B], @@ -739,8 +765,8 @@ const matchSymbols = buildString({ [0x01EEA5, 0x01EEA9], [0x01EEAB, 0x01EEBB], [0x01FBF0, 0x01FBF9], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -781,7 +807,7 @@ const nonMatchSymbols = buildString({ 0x0005C6, 0x0006D4, 0x0006E9, - 0x0008B5, + 0x000888, 0x0008E2, 0x000970, 0x000984, @@ -866,14 +892,13 @@ const nonMatchSymbols = buildString({ 0x0012D7, 0x001311, 0x001680, - 0x00170D, 0x00176D, 0x001771, + 0x00180E, 0x00191F, 0x001A5F, 0x001ABE, 0x001CD3, - 0x001DFA, 0x001F58, 0x001F5A, 0x001F5C, @@ -886,8 +911,6 @@ const nonMatchSymbols = buildString({ 0x002125, 0x002127, 0x002129, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -902,6 +925,8 @@ const nonMatchSymbols = buildString({ 0x0030FB, 0x003130, 0x00A67E, + 0x00A7D2, + 0x00A7D4, 0x00A8FC, 0x00A9FF, 0x00AB27, @@ -921,6 +946,15 @@ const nonMatchSymbols = buildString({ 0x01003B, 0x01003E, 0x0103D0, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x0108F3, @@ -959,7 +993,11 @@ const nonMatchSymbols = buildString({ 0x011D8F, 0x011D92, 0x016A5F, + 0x016ABF, 0x016FE2, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -987,6 +1025,10 @@ const nonMatchSymbols = buildString({ 0x01E007, 0x01E022, 0x01E025, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -1048,8 +1090,8 @@ const nonMatchSymbols = buildString({ [0x0007FE, 0x0007FF], [0x00082E, 0x00083F], [0x00085C, 0x00085F], - [0x00086B, 0x00089F], - [0x0008C8, 0x0008D2], + [0x00086B, 0x00086F], + [0x00088F, 0x000897], [0x000964, 0x000965], [0x00098D, 0x00098E], [0x000991, 0x000992], @@ -1096,14 +1138,15 @@ const nonMatchSymbols = buildString({ [0x000BD1, 0x000BD6], [0x000BD8, 0x000BE5], [0x000BF0, 0x000BFF], - [0x000C3A, 0x000C3C], + [0x000C3A, 0x000C3B], [0x000C4E, 0x000C54], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C64, 0x000C65], [0x000C70, 0x000C7F], [0x000CBA, 0x000CBB], [0x000CCE, 0x000CD4], - [0x000CD7, 0x000CDD], + [0x000CD7, 0x000CDC], [0x000CE4, 0x000CE5], [0x000CF3, 0x000CFF], [0x000D4F, 0x000D53], @@ -1150,7 +1193,7 @@ const nonMatchSymbols = buildString({ [0x00169B, 0x00169F], [0x0016EB, 0x0016ED], [0x0016F9, 0x0016FF], - [0x001715, 0x00171F], + [0x001716, 0x00171E], [0x001735, 0x00173F], [0x001754, 0x00175F], [0x001774, 0x00177F], @@ -1158,7 +1201,6 @@ const nonMatchSymbols = buildString({ [0x0017D8, 0x0017DB], [0x0017DE, 0x0017DF], [0x0017EA, 0x00180A], - [0x00180E, 0x00180F], [0x00181A, 0x00181F], [0x001879, 0x00187F], [0x0018AB, 0x0018AF], @@ -1175,8 +1217,8 @@ const nonMatchSymbols = buildString({ [0x001A8A, 0x001A8F], [0x001A9A, 0x001AA6], [0x001AA8, 0x001AAF], - [0x001AC1, 0x001AFF], - [0x001B4C, 0x001B4F], + [0x001ACF, 0x001AFF], + [0x001B4D, 0x001B4F], [0x001B5A, 0x001B6A], [0x001B74, 0x001B7F], [0x001BF4, 0x001BFF], @@ -1232,7 +1274,6 @@ const nonMatchSymbols = buildString({ [0x0031C0, 0x0031EF], [0x003200, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A4CF], [0x00A4FE, 0x00A4FF], [0x00A60D, 0x00A60F], @@ -1241,8 +1282,8 @@ const nonMatchSymbols = buildString({ [0x00A6F2, 0x00A716], [0x00A720, 0x00A721], [0x00A789, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A828, 0x00A82B], [0x00A82D, 0x00A83F], [0x00A874, 0x00A87F], @@ -1313,10 +1354,12 @@ const nonMatchSymbols = buildString({ [0x0104D4, 0x0104D7], [0x0104FC, 0x0104FF], [0x010528, 0x01052F], - [0x010564, 0x0105FF], + [0x010564, 0x01056F], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -1348,12 +1391,14 @@ const nonMatchSymbols = buildString({ [0x010EB2, 0x010EFF], [0x010F1D, 0x010F26], [0x010F28, 0x010F2F], - [0x010F51, 0x010FAF], + [0x010F51, 0x010F6F], + [0x010F86, 0x010FAF], [0x010FC5, 0x010FDF], [0x010FF7, 0x010FFF], [0x011047, 0x011065], - [0x011070, 0x01107E], - [0x0110BB, 0x0110CF], + [0x011076, 0x01107E], + [0x0110BB, 0x0110C1], + [0x0110C3, 0x0110CF], [0x0110E9, 0x0110EF], [0x0110FA, 0x0110FF], [0x011140, 0x011143], @@ -1392,7 +1437,8 @@ const nonMatchSymbols = buildString({ [0x0116CA, 0x0116FF], [0x01171B, 0x01171C], [0x01172C, 0x01172F], - [0x01173A, 0x0117FF], + [0x01173A, 0x01173F], + [0x011747, 0x0117FF], [0x01183B, 0x01189F], [0x0118EA, 0x0118FE], [0x011907, 0x011908], @@ -1406,7 +1452,7 @@ const nonMatchSymbols = buildString({ [0x011A3F, 0x011A46], [0x011A48, 0x011A4F], [0x011A9A, 0x011A9C], - [0x011A9E, 0x011ABF], + [0x011A9E, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C41, 0x011C4F], [0x011C5A, 0x011C71], @@ -1421,11 +1467,13 @@ const nonMatchSymbols = buildString({ [0x011FB1, 0x011FFF], [0x01239A, 0x0123FF], [0x01246F, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF1, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], - [0x016A6A, 0x016ACF], + [0x016A6A, 0x016A6F], + [0x016ACA, 0x016ACF], [0x016AEE, 0x016AEF], [0x016AF5, 0x016AFF], [0x016B37, 0x016B3F], @@ -1441,8 +1489,8 @@ const nonMatchSymbols = buildString({ [0x016FF2, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -1450,7 +1498,9 @@ const nonMatchSymbols = buildString({ [0x01BC7D, 0x01BC7F], [0x01BC89, 0x01BC8F], [0x01BC9A, 0x01BC9C], - [0x01BC9F, 0x01D164], + [0x01BC9F, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D164], [0x01D16A, 0x01D16C], [0x01D173, 0x01D17A], [0x01D183, 0x01D184], @@ -1469,14 +1519,16 @@ const nonMatchSymbols = buildString({ [0x01DA6D, 0x01DA74], [0x01DA76, 0x01DA83], [0x01DA85, 0x01DA9A], - [0x01DAB0, 0x01DFFF], + [0x01DAB0, 0x01DEFF], + [0x01DF1F, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E0FF], [0x01E12D, 0x01E12F], [0x01E13E, 0x01E13F], [0x01E14A, 0x01E14D], - [0x01E14F, 0x01E2BF], - [0x01E2FA, 0x01E7FF], + [0x01E14F, 0x01E28F], + [0x01E2AF, 0x01E2BF], + [0x01E2FA, 0x01E7DF], [0x01E8C5, 0x01E8CF], [0x01E8D7, 0x01E8FF], [0x01E94C, 0x01E94F], @@ -1489,8 +1541,8 @@ const nonMatchSymbols = buildString({ [0x01EE9C, 0x01EEA0], [0x01EEBC, 0x01FBEF], [0x01FBFA, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Start.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Start.js index 1971844ac73c..42008237982b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Start.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Start.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `ID_Start` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -48,9 +48,9 @@ const matchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000C3D, + 0x000C5D, 0x000C80, 0x000CBD, - 0x000CDE, 0x000D3D, 0x000D4E, 0x000DBD, @@ -87,6 +87,7 @@ const matchSymbols = buildString({ 0x002D27, 0x002D2D, 0x002D6F, + 0x00A7D3, 0x00A8FB, 0x00A9CF, 0x00AA7A, @@ -99,6 +100,7 @@ const matchSymbols = buildString({ 0x01083C, 0x010A00, 0x010F27, + 0x011075, 0x011144, 0x011147, 0x011176, @@ -180,8 +182,9 @@ const matchSymbols = buildString({ [0x000800, 0x000815], [0x000840, 0x000858], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], + [0x000870, 0x000887], + [0x000889, 0x00088E], + [0x0008A0, 0x0008C9], [0x000904, 0x000939], [0x000958, 0x000961], [0x000971, 0x000980], @@ -236,6 +239,7 @@ const matchSymbols = buildString({ [0x000C92, 0x000CA8], [0x000CAA, 0x000CB3], [0x000CB5, 0x000CB9], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE1], [0x000CF1, 0x000CF2], [0x000D04, 0x000D0C], @@ -291,9 +295,8 @@ const matchSymbols = buildString({ [0x001681, 0x00169A], [0x0016A0, 0x0016EA], [0x0016EE, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001711], - [0x001720, 0x001731], + [0x001700, 0x001711], + [0x00171F, 0x001731], [0x001740, 0x001751], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -309,7 +312,7 @@ const matchSymbols = buildString({ [0x001A00, 0x001A16], [0x001A20, 0x001A54], [0x001B05, 0x001B33], - [0x001B45, 0x001B4B], + [0x001B45, 0x001B4C], [0x001B83, 0x001BA0], [0x001BAE, 0x001BAF], [0x001BBA, 0x001BE5], @@ -345,9 +348,7 @@ const matchSymbols = buildString({ [0x00213C, 0x00213F], [0x002145, 0x002149], [0x002160, 0x002188], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CE4], + [0x002C00, 0x002CE4], [0x002CEB, 0x002CEE], [0x002CF2, 0x002CF3], [0x002D00, 0x002D25], @@ -374,8 +375,7 @@ const matchSymbols = buildString({ [0x0031A0, 0x0031BF], [0x0031F0, 0x0031FF], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], - [0x00A000, 0x00A48C], + [0x004E00, 0x00A48C], [0x00A4D0, 0x00A4FD], [0x00A500, 0x00A60C], [0x00A610, 0x00A61F], @@ -385,9 +385,10 @@ const matchSymbols = buildString({ [0x00A6A0, 0x00A6EF], [0x00A717, 0x00A71F], [0x00A722, 0x00A788], - [0x00A78B, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A801], + [0x00A78B, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A801], [0x00A803, 0x00A805], [0x00A807, 0x00A80A], [0x00A80C, 0x00A822], @@ -468,9 +469,20 @@ const matchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -502,9 +514,11 @@ const matchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F1C], [0x010F30, 0x010F45], + [0x010F70, 0x010F81], [0x010FB0, 0x010FC4], [0x010FE0, 0x010FF6], [0x011003, 0x011037], + [0x011071, 0x011072], [0x011083, 0x0110AF], [0x0110D0, 0x0110E8], [0x011103, 0x011126], @@ -535,6 +549,7 @@ const matchSymbols = buildString({ [0x011600, 0x01162F], [0x011680, 0x0116AA], [0x011700, 0x01171A], + [0x011740, 0x011746], [0x011800, 0x01182B], [0x0118A0, 0x0118DF], [0x0118FF, 0x011906], @@ -545,7 +560,7 @@ const matchSymbols = buildString({ [0x0119AA, 0x0119D0], [0x011A0B, 0x011A32], [0x011A5C, 0x011A89], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C2E], [0x011C72, 0x011C8F], @@ -559,10 +574,12 @@ const matchSymbols = buildString({ [0x012000, 0x012399], [0x012400, 0x01246E], [0x012480, 0x012543], + [0x012F90, 0x012FF0], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], + [0x016A70, 0x016ABE], [0x016AD0, 0x016AED], [0x016B00, 0x016B2F], [0x016B40, 0x016B43], @@ -575,7 +592,10 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -610,9 +630,15 @@ const matchSymbols = buildString({ [0x01D78A, 0x01D7A8], [0x01D7AA, 0x01D7C2], [0x01D7C4, 0x01D7CB], + [0x01DF00, 0x01DF1E], [0x01E100, 0x01E12C], [0x01E137, 0x01E13D], + [0x01E290, 0x01E2AD], [0x01E2C0, 0x01E2EB], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E900, 0x01E943], [0x01EE00, 0x01EE03], @@ -632,8 +658,8 @@ const matchSymbols = buildString({ [0x01EEA1, 0x01EEA3], [0x01EEA5, 0x01EEA9], [0x01EEAB, 0x01EEBB], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -668,7 +694,7 @@ const nonMatchSymbols = buildString({ 0x000670, 0x0006D4, 0x000711, - 0x0008B5, + 0x000888, 0x0009A9, 0x0009B1, 0x0009DE, @@ -723,7 +749,6 @@ const nonMatchSymbols = buildString({ 0x0012D7, 0x001311, 0x001680, - 0x00170D, 0x00176D, 0x0018A9, 0x001CED, @@ -740,8 +765,6 @@ const nonMatchSymbols = buildString({ 0x002125, 0x002127, 0x002129, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -753,6 +776,8 @@ const nonMatchSymbols = buildString({ 0x0030A0, 0x0030FB, 0x003130, + 0x00A7D2, + 0x00A7D4, 0x00A802, 0x00A806, 0x00A80B, @@ -778,6 +803,15 @@ const nonMatchSymbols = buildString({ 0x01003B, 0x01003E, 0x0103D0, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x0108F3, @@ -804,6 +838,9 @@ const nonMatchSymbols = buildString({ 0x011D66, 0x011D69, 0x016FE2, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -827,6 +864,10 @@ const nonMatchSymbols = buildString({ 0x01D789, 0x01D7A9, 0x01D7C3, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -891,8 +932,9 @@ const nonMatchSymbols = buildString({ [0x000825, 0x000827], [0x000829, 0x00083F], [0x000859, 0x00085F], - [0x00086B, 0x00089F], - [0x0008C8, 0x000903], + [0x00086B, 0x00086F], + [0x00088F, 0x00089F], + [0x0008CA, 0x000903], [0x00093A, 0x00093C], [0x00093E, 0x00094F], [0x000951, 0x000957], @@ -932,11 +974,12 @@ const nonMatchSymbols = buildString({ [0x000BD1, 0x000C04], [0x000C3A, 0x000C3C], [0x000C3E, 0x000C57], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C62, 0x000C7F], [0x000C81, 0x000C84], [0x000CBA, 0x000CBC], - [0x000CBE, 0x000CDD], + [0x000CBE, 0x000CDC], [0x000CE2, 0x000CF0], [0x000CF3, 0x000D03], [0x000D3B, 0x000D3C], @@ -982,7 +1025,7 @@ const nonMatchSymbols = buildString({ [0x00169B, 0x00169F], [0x0016EB, 0x0016ED], [0x0016F9, 0x0016FF], - [0x001712, 0x00171F], + [0x001712, 0x00171E], [0x001732, 0x00173F], [0x001752, 0x00175F], [0x001771, 0x00177F], @@ -1001,7 +1044,7 @@ const nonMatchSymbols = buildString({ [0x001A55, 0x001AA6], [0x001AA8, 0x001B04], [0x001B34, 0x001B44], - [0x001B4C, 0x001B82], + [0x001B4D, 0x001B82], [0x001BA1, 0x001BAD], [0x001BB0, 0x001BB9], [0x001BE6, 0x001BFF], @@ -1056,7 +1099,6 @@ const nonMatchSymbols = buildString({ [0x0031C0, 0x0031EF], [0x003200, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A4CF], [0x00A4FE, 0x00A4FF], [0x00A60D, 0x00A60F], @@ -1067,8 +1109,8 @@ const nonMatchSymbols = buildString({ [0x00A6F0, 0x00A716], [0x00A720, 0x00A721], [0x00A789, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A823, 0x00A83F], [0x00A874, 0x00A881], [0x00A8B4, 0x00A8F1], @@ -1133,10 +1175,12 @@ const nonMatchSymbols = buildString({ [0x0104D4, 0x0104D7], [0x0104FC, 0x0104FF], [0x010528, 0x01052F], - [0x010564, 0x0105FF], + [0x010564, 0x01056F], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -1165,10 +1209,13 @@ const nonMatchSymbols = buildString({ [0x010EB2, 0x010EFF], [0x010F1D, 0x010F26], [0x010F28, 0x010F2F], - [0x010F46, 0x010FAF], + [0x010F46, 0x010F6F], + [0x010F82, 0x010FAF], [0x010FC5, 0x010FDF], [0x010FF7, 0x011002], - [0x011038, 0x011082], + [0x011038, 0x011070], + [0x011073, 0x011074], + [0x011076, 0x011082], [0x0110B0, 0x0110CF], [0x0110E9, 0x011102], [0x011127, 0x011143], @@ -1199,7 +1246,8 @@ const nonMatchSymbols = buildString({ [0x011645, 0x01167F], [0x0116AB, 0x0116B7], [0x0116B9, 0x0116FF], - [0x01171B, 0x0117FF], + [0x01171B, 0x01173F], + [0x011747, 0x0117FF], [0x01182C, 0x01189F], [0x0118E0, 0x0118FE], [0x011907, 0x011908], @@ -1214,7 +1262,7 @@ const nonMatchSymbols = buildString({ [0x011A3B, 0x011A4F], [0x011A51, 0x011A5B], [0x011A8A, 0x011A9C], - [0x011A9E, 0x011ABF], + [0x011A9E, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C2F, 0x011C3F], [0x011C41, 0x011C71], @@ -1227,11 +1275,13 @@ const nonMatchSymbols = buildString({ [0x011FB1, 0x011FFF], [0x01239A, 0x0123FF], [0x01246F, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF1, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], - [0x016A5F, 0x016ACF], + [0x016A5F, 0x016A6F], + [0x016ABF, 0x016ACF], [0x016AEE, 0x016AFF], [0x016B30, 0x016B3F], [0x016B44, 0x016B62], @@ -1244,8 +1294,8 @@ const nonMatchSymbols = buildString({ [0x016FE4, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -1259,11 +1309,13 @@ const nonMatchSymbols = buildString({ [0x01D50B, 0x01D50C], [0x01D547, 0x01D549], [0x01D6A6, 0x01D6A7], - [0x01D7CC, 0x01E0FF], + [0x01D7CC, 0x01DEFF], + [0x01DF1F, 0x01E0FF], [0x01E12D, 0x01E136], [0x01E13E, 0x01E14D], - [0x01E14F, 0x01E2BF], - [0x01E2EC, 0x01E7FF], + [0x01E14F, 0x01E28F], + [0x01E2AE, 0x01E2BF], + [0x01E2EC, 0x01E7DF], [0x01E8C5, 0x01E8FF], [0x01E944, 0x01E94A], [0x01E94C, 0x01EDFF], @@ -1274,8 +1326,8 @@ const nonMatchSymbols = buildString({ [0x01EE65, 0x01EE66], [0x01EE9C, 0x01EEA0], [0x01EEBC, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Ideographic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Ideographic.js index b89c80362831..ed4615cf2d62 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Ideographic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Ideographic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Ideographic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -22,15 +22,15 @@ const matchSymbols = buildString({ [0x003021, 0x003029], [0x003038, 0x00303A], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], + [0x004E00, 0x009FFF], [0x00F900, 0x00FA6D], [0x00FA70, 0x00FAD9], [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], [0x01B170, 0x01B2FB], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -58,7 +58,7 @@ const nonMatchSymbols = buildString({ [0x00302A, 0x003037], [0x00303B, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x00DBFF], + [0x00A000, 0x00DBFF], [0x00E000, 0x00F8FF], [0x00FA6E, 0x00FA6F], [0x00FADA, 0x016FE3], @@ -67,8 +67,8 @@ const nonMatchSymbols = buildString({ [0x018CD6, 0x018CFF], [0x018D09, 0x01B16F], [0x01B2FC, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Join_Control.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Join_Control.js index 890e5e234c9e..0eefc876ae8c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Join_Control.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Join_Control.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Join_Control` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Logical_Order_Exception.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Logical_Order_Exception.js index 870f91b08c63..75e359dc3fbd 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Logical_Order_Exception.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Logical_Order_Exception.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Logical_Order_Exception` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Lowercase.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Lowercase.js index 1c0448ed945c..94b8ee28f92b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Lowercase.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Lowercase.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Lowercase` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -552,10 +552,17 @@ const matchSymbols = buildString({ 0x00A7BB, 0x00A7BD, 0x00A7BF, + 0x00A7C1, 0x00A7C3, 0x00A7C8, 0x00A7CA, + 0x00A7D1, + 0x00A7D3, + 0x00A7D5, + 0x00A7D7, + 0x00A7D9, 0x00A7F6, + 0x010780, 0x01D4BB, 0x01D7CB ], @@ -620,7 +627,7 @@ const matchSymbols = buildString({ [0x002146, 0x002149], [0x002170, 0x00217F], [0x0024D0, 0x0024E9], - [0x002C30, 0x002C5E], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002C73, 0x002C74], [0x002C76, 0x002C7D], @@ -639,6 +646,13 @@ const matchSymbols = buildString({ [0x00FF41, 0x00FF5A], [0x010428, 0x01044F], [0x0104D8, 0x0104FB], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], + [0x010783, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010CC0, 0x010CF2], [0x0118C0, 0x0118DF], [0x016E60, 0x016E7F], @@ -668,6 +682,8 @@ const matchSymbols = buildString({ [0x01D78A, 0x01D78F], [0x01D7AA, 0x01D7C2], [0x01D7C4, 0x01D7C9], + [0x01DF00, 0x01DF09], + [0x01DF0B, 0x01DF1E], [0x01E922, 0x01E943] ] }); @@ -1043,6 +1059,7 @@ const nonMatchSymbols = buildString({ 0x001FB5, 0x001FC5, 0x001FF5, + 0x002C60, 0x002C67, 0x002C69, 0x002C6B, @@ -1194,9 +1211,20 @@ const nonMatchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, + 0x00A7C0, + 0x00A7C2, 0x00A7C9, + 0x00A7D2, + 0x00A7D4, + 0x00A7D6, + 0x00A7D8, 0x00A7F7, 0x00AB5B, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x01D455, 0x01D4BA, 0x01D4BC, @@ -1206,7 +1234,8 @@ const nonMatchSymbols = buildString({ 0x01D74F, 0x01D789, 0x01D7C3, - 0x01D7CA + 0x01D7CA, + 0x01DF0A ], ranges: [ [0x00DC00, 0x00DFFF], @@ -1291,7 +1320,6 @@ const nonMatchSymbols = buildString({ [0x002180, 0x002183], [0x002185, 0x0024CF], [0x0024EA, 0x002C2F], - [0x002C5F, 0x002C60], [0x002C62, 0x002C64], [0x002C6D, 0x002C70], [0x002C7E, 0x002C80], @@ -1307,9 +1335,9 @@ const nonMatchSymbols = buildString({ [0x00A78F, 0x00A790], [0x00A7AA, 0x00A7AE], [0x00A7B0, 0x00A7B4], - [0x00A7C0, 0x00A7C2], [0x00A7C4, 0x00A7C7], - [0x00A7CB, 0x00A7F5], + [0x00A7CB, 0x00A7D0], + [0x00A7DA, 0x00A7F5], [0x00A7FB, 0x00AB2F], [0x00AB69, 0x00AB6F], [0x00ABC0, 0x00DBFF], @@ -1318,7 +1346,10 @@ const nonMatchSymbols = buildString({ [0x00FB18, 0x00FF40], [0x00FF5B, 0x010427], [0x010450, 0x0104D7], - [0x0104FC, 0x010CBF], + [0x0104FC, 0x010596], + [0x0105BD, 0x01077F], + [0x010781, 0x010782], + [0x0107BB, 0x010CBF], [0x010CF3, 0x0118BF], [0x0118E0, 0x016E5F], [0x016E80, 0x01D419], @@ -1339,7 +1370,8 @@ const nonMatchSymbols = buildString({ [0x01D71C, 0x01D735], [0x01D756, 0x01D76F], [0x01D790, 0x01D7A9], - [0x01D7CC, 0x01E921], + [0x01D7CC, 0x01DEFF], + [0x01DF1F, 0x01E921], [0x01E944, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Math.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Math.js index 69b5884ca3fe..3d1c6e177266 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Math.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Math.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Math` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Noncharacter_Code_Point.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Noncharacter_Code_Point.js index 70b2ab3fbfad..74c8155b24d6 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Noncharacter_Code_Point.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Noncharacter_Code_Point.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Noncharacter_Code_Point` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_Syntax.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_Syntax.js index be6c32c9d7b0..6b638c7f5e32 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_Syntax.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_Syntax.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Pattern_Syntax` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_White_Space.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_White_Space.js index 0a113f11c574..693cab84383c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_White_Space.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_White_Space.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Pattern_White_Space` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Quotation_Mark.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Quotation_Mark.js index 3d5192ee02ad..ebe3d755a2b5 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Quotation_Mark.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Quotation_Mark.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Quotation_Mark` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Radical.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Radical.js index 227d330d2fb9..59195388139b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Radical.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Radical.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Radical` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Regional_Indicator.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Regional_Indicator.js index 1c55097c1582..e8029a50fbe9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Regional_Indicator.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Regional_Indicator.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Regional_Indicator` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Adlam.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Adlam.js index ac912ce4514e..5a9e78e3e802 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Adlam.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Adlam.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Adlam` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ahom.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ahom.js index 266f7620f265..7f5584b615f9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ahom.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ahom.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Ahom` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -18,7 +18,7 @@ const matchSymbols = buildString({ ranges: [ [0x011700, 0x01171A], [0x01171D, 0x01172B], - [0x011730, 0x01173F] + [0x011730, 0x011746] ] }); testPropertyEscapes( @@ -50,7 +50,7 @@ const nonMatchSymbols = buildString({ [0x00E000, 0x0116FF], [0x01171B, 0x01171C], [0x01172C, 0x01172F], - [0x011740, 0x10FFFF] + [0x011747, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Anatolian_Hieroglyphs.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Anatolian_Hieroglyphs.js index 6dc0df82d187..5f503c99b7c2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Anatolian_Hieroglyphs.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Anatolian_Hieroglyphs.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Anatolian_Hieroglyphs` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Arabic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Arabic.js index b4ce1321b849..453030445e2a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Arabic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Arabic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Arabic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -15,8 +15,7 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [ - 0x00061C, - 0x00061E, + 0x00FDCF, 0x01EE24, 0x01EE27, 0x01EE39, @@ -38,21 +37,22 @@ const matchSymbols = buildString({ [0x000600, 0x000604], [0x000606, 0x00060B], [0x00060D, 0x00061A], + [0x00061C, 0x00061E], [0x000620, 0x00063F], [0x000641, 0x00064A], [0x000656, 0x00066F], [0x000671, 0x0006DC], [0x0006DE, 0x0006FF], [0x000750, 0x00077F], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], - [0x0008D3, 0x0008E1], + [0x000870, 0x00088E], + [0x000890, 0x000891], + [0x000898, 0x0008E1], [0x0008E3, 0x0008FF], - [0x00FB50, 0x00FBC1], + [0x00FB50, 0x00FBC2], [0x00FBD3, 0x00FD3D], - [0x00FD50, 0x00FD8F], + [0x00FD40, 0x00FD8F], [0x00FD92, 0x00FDC7], - [0x00FDF0, 0x00FDFD], + [0x00FDF0, 0x00FDFF], [0x00FE70, 0x00FE74], [0x00FE76, 0x00FEFC], [0x010E60, 0x010E7E], @@ -102,12 +102,11 @@ const nonMatchSymbols = buildString({ 0x000605, 0x00060C, 0x00061B, - 0x00061D, 0x00061F, 0x000640, 0x000670, 0x0006DD, - 0x0008B5, + 0x00088F, 0x0008E2, 0x00FE75, 0x01EE04, @@ -142,15 +141,16 @@ const nonMatchSymbols = buildString({ [0x000000, 0x0005FF], [0x00064B, 0x000655], [0x000700, 0x00074F], - [0x000780, 0x00089F], - [0x0008C8, 0x0008D2], + [0x000780, 0x00086F], + [0x000892, 0x000897], [0x000900, 0x00DBFF], [0x00E000, 0x00FB4F], - [0x00FBC2, 0x00FBD2], - [0x00FD3E, 0x00FD4F], + [0x00FBC3, 0x00FBD2], + [0x00FD3E, 0x00FD3F], [0x00FD90, 0x00FD91], - [0x00FDC8, 0x00FDEF], - [0x00FDFE, 0x00FE6F], + [0x00FDC8, 0x00FDCE], + [0x00FDD0, 0x00FDEF], + [0x00FE00, 0x00FE6F], [0x00FEFD, 0x010E5F], [0x010E7F, 0x01EDFF], [0x01EE25, 0x01EE26], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Armenian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Armenian.js index e13bc7af087b..42a85cfd9a44 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Armenian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Armenian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Armenian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Avestan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Avestan.js index 79376709be74..48c678900e36 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Avestan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Avestan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Avestan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Balinese.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Balinese.js index 1378de59058c..99486d6ae1eb 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Balinese.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Balinese.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Balinese` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -16,8 +16,8 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [], ranges: [ - [0x001B00, 0x001B4B], - [0x001B50, 0x001B7C] + [0x001B00, 0x001B4C], + [0x001B50, 0x001B7E] ] }); testPropertyEscapes( @@ -46,8 +46,8 @@ const nonMatchSymbols = buildString({ ranges: [ [0x00DC00, 0x00DFFF], [0x000000, 0x001AFF], - [0x001B4C, 0x001B4F], - [0x001B7D, 0x00DBFF], + [0x001B4D, 0x001B4F], + [0x001B7F, 0x00DBFF], [0x00E000, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bamum.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bamum.js index d20bc6d44c33..c71d7321a8ce 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bamum.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bamum.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Bamum` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bassa_Vah.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bassa_Vah.js index 3a75fccf83ea..4a00e9cc7578 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bassa_Vah.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bassa_Vah.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Bassa_Vah` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Batak.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Batak.js index a84faab42dbf..9d28c697af80 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Batak.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Batak.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Batak` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bengali.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bengali.js index 352604946327..e6d500469817 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bengali.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bengali.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Bengali` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bhaiksuki.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bhaiksuki.js index 88e56c5ad230..cae0f2fb430c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bhaiksuki.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bhaiksuki.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Bhaiksuki` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bopomofo.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bopomofo.js index b8cf8e4b49dc..df33e49641ec 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bopomofo.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bopomofo.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Bopomofo` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Brahmi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Brahmi.js index a89251fea77e..4abca964e36f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Brahmi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Brahmi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Brahmi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -19,7 +19,7 @@ const matchSymbols = buildString({ ], ranges: [ [0x011000, 0x01104D], - [0x011052, 0x01106F] + [0x011052, 0x011075] ] }); testPropertyEscapes( @@ -50,7 +50,7 @@ const nonMatchSymbols = buildString({ [0x000000, 0x00DBFF], [0x00E000, 0x010FFF], [0x01104E, 0x011051], - [0x011070, 0x01107E], + [0x011076, 0x01107E], [0x011080, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Braille.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Braille.js index bbc7beeb08f1..08975a596076 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Braille.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Braille.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Braille` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Buginese.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Buginese.js index 9730010119f9..7b26f79810d4 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Buginese.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Buginese.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Buginese` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Buhid.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Buhid.js index 251c761e11f4..24052196fcf3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Buhid.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Buhid.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Buhid` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Canadian_Aboriginal.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Canadian_Aboriginal.js index 5ff88d456679..b88524731488 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Canadian_Aboriginal.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Canadian_Aboriginal.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Canadian_Aboriginal` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -17,7 +17,8 @@ const matchSymbols = buildString({ loneCodePoints: [], ranges: [ [0x001400, 0x00167F], - [0x0018B0, 0x0018F5] + [0x0018B0, 0x0018F5], + [0x011AB0, 0x011ABF] ] }); testPropertyEscapes( @@ -48,7 +49,8 @@ const nonMatchSymbols = buildString({ [0x000000, 0x0013FF], [0x001680, 0x0018AF], [0x0018F6, 0x00DBFF], - [0x00E000, 0x10FFFF] + [0x00E000, 0x011AAF], + [0x011AC0, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Carian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Carian.js index 8029f0f93e58..179720afd9b5 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Carian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Carian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Carian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Caucasian_Albanian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Caucasian_Albanian.js index a9c516664ded..234a49758f62 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Caucasian_Albanian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Caucasian_Albanian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Caucasian_Albanian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Chakma.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Chakma.js index f83aa1b39707..0ea6a82c9fba 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Chakma.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Chakma.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Chakma` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cham.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cham.js index ec6877aa3252..a9c6fbdaca7e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cham.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cham.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Cham` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cherokee.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cherokee.js index d3844953cc3e..7f80e5adcbda 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cherokee.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cherokee.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Cherokee` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Chorasmian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Chorasmian.js index a8693a5f9510..8ea0573439f0 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Chorasmian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Chorasmian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Chorasmian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Common.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Common.js index 1a1c8c68ae20..bd0ee291f7f9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Common.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Common.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Common` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -45,6 +45,7 @@ const matchSymbols = buildString({ 0x01D4A2, 0x01D4BB, 0x01D546, + 0x01F7F0, 0x0E0001 ], ranges: [ @@ -69,7 +70,7 @@ const matchSymbols = buildString({ [0x002066, 0x002070], [0x002074, 0x00207E], [0x002080, 0x00208E], - [0x0020A0, 0x0020BF], + [0x0020A0, 0x0020C0], [0x002100, 0x002125], [0x002127, 0x002129], [0x00212C, 0x002131], @@ -82,7 +83,7 @@ const matchSymbols = buildString({ [0x002900, 0x002B73], [0x002B76, 0x002B95], [0x002B97, 0x002BFF], - [0x002E00, 0x002E52], + [0x002E00, 0x002E5D], [0x002FF0, 0x002FFB], [0x003000, 0x003004], [0x003008, 0x003020], @@ -118,15 +119,15 @@ const matchSymbols = buildString({ [0x010190, 0x01019C], [0x0101D0, 0x0101FC], [0x0102E1, 0x0102FB], - [0x016FE2, 0x016FE3], [0x01BCA0, 0x01BCA3], + [0x01CF50, 0x01CFC3], [0x01D000, 0x01D0F5], [0x01D100, 0x01D126], [0x01D129, 0x01D166], [0x01D16A, 0x01D17A], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], - [0x01D1AE, 0x01D1E8], + [0x01D1AE, 0x01D1EA], [0x01D2E0, 0x01D2F3], [0x01D300, 0x01D356], [0x01D360, 0x01D378], @@ -164,7 +165,7 @@ const matchSymbols = buildString({ [0x01F250, 0x01F251], [0x01F260, 0x01F265], [0x01F300, 0x01F6D7], - [0x01F6E0, 0x01F6EC], + [0x01F6DD, 0x01F6EC], [0x01F6F0, 0x01F6FC], [0x01F700, 0x01F773], [0x01F780, 0x01F7D8], @@ -175,17 +176,17 @@ const matchSymbols = buildString({ [0x01F860, 0x01F887], [0x01F890, 0x01F8AD], [0x01F8B0, 0x01F8B1], - [0x01F900, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01FA53], + [0x01F900, 0x01FA53], [0x01FA60, 0x01FA6D], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6], + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6], [0x01FB00, 0x01FB92], [0x01FB94, 0x01FBCA], [0x01FBF0, 0x01FBF9], @@ -249,8 +250,6 @@ const nonMatchSymbols = buildString({ 0x01F0C0, 0x01F0D0, 0x01F200, - 0x01F979, - 0x01F9CC, 0x01FB93 ], ranges: [ @@ -287,7 +286,7 @@ const nonMatchSymbols = buildString({ [0x00200C, 0x00200D], [0x002071, 0x002073], [0x00208F, 0x00209F], - [0x0020C0, 0x0020FF], + [0x0020C1, 0x0020FF], [0x00212A, 0x00212B], [0x002160, 0x002188], [0x00218C, 0x00218F], @@ -296,7 +295,7 @@ const nonMatchSymbols = buildString({ [0x002800, 0x0028FF], [0x002B74, 0x002B75], [0x002C00, 0x002DFF], - [0x002E53, 0x002FEF], + [0x002E5E, 0x002FEF], [0x002FFC, 0x002FFF], [0x003021, 0x00302F], [0x003038, 0x00303B], @@ -334,16 +333,16 @@ const nonMatchSymbols = buildString({ [0x010140, 0x01018F], [0x01019D, 0x0101CF], [0x0101FD, 0x0102E0], - [0x0102FC, 0x016FE1], - [0x016FE4, 0x01BC9F], - [0x01BCA4, 0x01CFFF], + [0x0102FC, 0x01BC9F], + [0x01BCA4, 0x01CF4F], + [0x01CFC4, 0x01CFFF], [0x01D0F6, 0x01D0FF], [0x01D127, 0x01D128], [0x01D167, 0x01D169], [0x01D17B, 0x01D182], [0x01D185, 0x01D18B], [0x01D1AA, 0x01D1AD], - [0x01D1E9, 0x01D2DF], + [0x01D1EB, 0x01D2DF], [0x01D2F4, 0x01D2FF], [0x01D357, 0x01D35F], [0x01D379, 0x01D3FF], @@ -367,12 +366,13 @@ const nonMatchSymbols = buildString({ [0x01F249, 0x01F24F], [0x01F252, 0x01F25F], [0x01F266, 0x01F2FF], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6ED, 0x01F6EF], [0x01F6FD, 0x01F6FF], [0x01F774, 0x01F77F], [0x01F7D9, 0x01F7DF], - [0x01F7EC, 0x01F7FF], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F7FF], [0x01F80C, 0x01F80F], [0x01F848, 0x01F84F], [0x01F85A, 0x01F85F], @@ -382,12 +382,14 @@ const nonMatchSymbols = buildString({ [0x01FA54, 0x01FA5F], [0x01FA6E, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x01FAFF], + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x01FAFF], [0x01FBCB, 0x01FBEF], [0x01FBFA, 0x0E0000], [0x0E0002, 0x0E001F], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Coptic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Coptic.js index 2b0c9abd5569..4495e7fa8ce9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Coptic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Coptic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Coptic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cuneiform.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cuneiform.js index 62ecf004d852..6a3c051c1544 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cuneiform.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cuneiform.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Cuneiform` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cypriot.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cypriot.js index 1f55541ec026..e707a80d1adb 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cypriot.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cypriot.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Cypriot` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cypro_Minoan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cypro_Minoan.js new file mode 100644 index 000000000000..88425b03b1a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cypro_Minoan.js @@ -0,0 +1,73 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script=Cypro_Minoan` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x012F90, 0x012FF2] + ] +}); +testPropertyEscapes( + /^\p{Script=Cypro_Minoan}+$/u, + matchSymbols, + "\\p{Script=Cypro_Minoan}" +); +testPropertyEscapes( + /^\p{Script=Cpmn}+$/u, + matchSymbols, + "\\p{Script=Cpmn}" +); +testPropertyEscapes( + /^\p{sc=Cypro_Minoan}+$/u, + matchSymbols, + "\\p{sc=Cypro_Minoan}" +); +testPropertyEscapes( + /^\p{sc=Cpmn}+$/u, + matchSymbols, + "\\p{sc=Cpmn}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x012F8F], + [0x012FF3, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script=Cypro_Minoan}+$/u, + nonMatchSymbols, + "\\P{Script=Cypro_Minoan}" +); +testPropertyEscapes( + /^\P{Script=Cpmn}+$/u, + nonMatchSymbols, + "\\P{Script=Cpmn}" +); +testPropertyEscapes( + /^\P{sc=Cypro_Minoan}+$/u, + nonMatchSymbols, + "\\P{sc=Cypro_Minoan}" +); +testPropertyEscapes( + /^\P{sc=Cpmn}+$/u, + nonMatchSymbols, + "\\P{sc=Cpmn}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cyrillic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cyrillic.js index adc35adb2263..a9c1f88f0f4a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cyrillic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Cyrillic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Cyrillic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Deseret.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Deseret.js index e020b73913c8..1d490a159676 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Deseret.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Deseret.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Deseret` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Devanagari.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Devanagari.js index 3bcd19c414bb..7726e34ee00b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Devanagari.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Devanagari.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Devanagari` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Dives_Akuru.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Dives_Akuru.js index ffe4e1242b3e..9cfb7dfd6642 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Dives_Akuru.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Dives_Akuru.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Dives_Akuru` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Dogra.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Dogra.js index 154eaee27e47..a6bb96b0d128 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Dogra.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Dogra.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Dogra` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Duployan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Duployan.js index 0b79bf458c7c..39a8a969d9e7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Duployan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Duployan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Duployan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Egyptian_Hieroglyphs.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Egyptian_Hieroglyphs.js index 3e7f279ebfc9..4b89e897db6f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Egyptian_Hieroglyphs.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Egyptian_Hieroglyphs.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Egyptian_Hieroglyphs` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Elbasan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Elbasan.js index bc03063e28d6..58d99ad5d04f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Elbasan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Elbasan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Elbasan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Elymaic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Elymaic.js index c9114f58e527..977bc27ef643 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Elymaic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Elymaic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Elymaic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ethiopic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ethiopic.js index ea782d127e13..e29dacb7f5b8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ethiopic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ethiopic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Ethiopic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -48,7 +48,11 @@ const matchSymbols = buildString({ [0x00AB09, 0x00AB0E], [0x00AB11, 0x00AB16], [0x00AB20, 0x00AB26], - [0x00AB28, 0x00AB2E] + [0x00AB28, 0x00AB2E], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE] ] }); testPropertyEscapes( @@ -90,7 +94,10 @@ const nonMatchSymbols = buildString({ 0x002DC7, 0x002DCF, 0x002DD7, - 0x00AB27 + 0x00AB27, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF ], ranges: [ [0x00DC00, 0x00DFFF], @@ -110,7 +117,8 @@ const nonMatchSymbols = buildString({ [0x00AB0F, 0x00AB10], [0x00AB17, 0x00AB1F], [0x00AB2F, 0x00DBFF], - [0x00E000, 0x10FFFF] + [0x00E000, 0x01E7DF], + [0x01E7FF, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Georgian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Georgian.js index d6143a1a4cf8..89b2ea42c6ac 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Georgian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Georgian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Georgian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Glagolitic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Glagolitic.js index d44549928150..d2604f9c72cf 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Glagolitic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Glagolitic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Glagolitic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -16,8 +16,7 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [], ranges: [ - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], + [0x002C00, 0x002C5F], [0x01E000, 0x01E006], [0x01E008, 0x01E018], [0x01E01B, 0x01E021], @@ -48,7 +47,6 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ - 0x002C2F, 0x01E007, 0x01E022, 0x01E025 @@ -56,7 +54,7 @@ const nonMatchSymbols = buildString({ ranges: [ [0x00DC00, 0x00DFFF], [0x000000, 0x002BFF], - [0x002C5F, 0x00DBFF], + [0x002C60, 0x00DBFF], [0x00E000, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x10FFFF] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gothic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gothic.js index a1883fbf16ae..95d6defb476d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gothic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gothic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Gothic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Grantha.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Grantha.js index ff5b71729c60..d275c541021c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Grantha.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Grantha.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Grantha` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Greek.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Greek.js index 39d7e2a568ae..c3cc40d3da48 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Greek.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Greek.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Greek` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gujarati.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gujarati.js index 7d4968cf4390..b03ffb517f2f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gujarati.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gujarati.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Gujarati` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gunjala_Gondi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gunjala_Gondi.js index 259f632b3be9..5358a172041b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gunjala_Gondi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gunjala_Gondi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Gunjala_Gondi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gurmukhi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gurmukhi.js index c934be74ba62..590c87fd31c4 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gurmukhi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Gurmukhi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Gurmukhi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Han.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Han.js index 300908a6d5c7..9e751e31d254 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Han.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Han.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Han` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -25,12 +25,13 @@ const matchSymbols = buildString({ [0x003021, 0x003029], [0x003038, 0x00303B], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], + [0x004E00, 0x009FFF], [0x00F900, 0x00FA6D], [0x00FA70, 0x00FAD9], + [0x016FE2, 0x016FE3], [0x016FF0, 0x016FF1], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -73,13 +74,14 @@ const nonMatchSymbols = buildString({ [0x00302A, 0x003037], [0x00303C, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x00DBFF], + [0x00A000, 0x00DBFF], [0x00E000, 0x00F8FF], [0x00FA6E, 0x00FA6F], - [0x00FADA, 0x016FEF], + [0x00FADA, 0x016FE1], + [0x016FE4, 0x016FEF], [0x016FF2, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hangul.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hangul.js index afb0db5c96fd..ba0889e44eae 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hangul.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hangul.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Hangul` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hanifi_Rohingya.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hanifi_Rohingya.js index 3afb012d9d7c..8c0bbbeb7bc4 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hanifi_Rohingya.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hanifi_Rohingya.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Hanifi_Rohingya` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hanunoo.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hanunoo.js index 6415198a4a02..9b42f7ed6086 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hanunoo.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hanunoo.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Hanunoo` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hatran.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hatran.js index daaae9b5c36c..fe5fc5a0b8bb 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hatran.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hatran.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Hatran` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hebrew.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hebrew.js index ebec15769b5d..6ed52516008a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hebrew.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hebrew.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Hebrew` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hiragana.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hiragana.js index 337f131995f6..fc648a659fc6 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hiragana.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Hiragana.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Hiragana` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -20,7 +20,7 @@ const matchSymbols = buildString({ ranges: [ [0x003041, 0x003096], [0x00309D, 0x00309F], - [0x01B001, 0x01B11E], + [0x01B001, 0x01B11F], [0x01B150, 0x01B152] ] }); @@ -53,7 +53,7 @@ const nonMatchSymbols = buildString({ [0x003097, 0x00309C], [0x0030A0, 0x00DBFF], [0x00E000, 0x01B000], - [0x01B11F, 0x01B14F], + [0x01B120, 0x01B14F], [0x01B153, 0x01F1FF], [0x01F201, 0x10FFFF] ] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Imperial_Aramaic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Imperial_Aramaic.js index fc75d2a7b5dd..19f15faa33bc 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Imperial_Aramaic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Imperial_Aramaic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Imperial_Aramaic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inherited.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inherited.js index 53356727d126..e13eb8fce06d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inherited.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inherited.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Inherited` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -27,19 +27,20 @@ const matchSymbols = buildString({ [0x000485, 0x000486], [0x00064B, 0x000655], [0x000951, 0x000954], - [0x001AB0, 0x001AC0], + [0x001AB0, 0x001ACE], [0x001CD0, 0x001CD2], [0x001CD4, 0x001CE0], [0x001CE2, 0x001CE8], [0x001CF8, 0x001CF9], - [0x001DC0, 0x001DF9], - [0x001DFB, 0x001DFF], + [0x001DC0, 0x001DFF], [0x00200C, 0x00200D], [0x0020D0, 0x0020F0], [0x00302A, 0x00302D], [0x003099, 0x00309A], [0x00FE00, 0x00FE0F], [0x00FE20, 0x00FE2D], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D167, 0x01D169], [0x01D17B, 0x01D182], [0x01D185, 0x01D18B], @@ -81,8 +82,7 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ 0x001CD3, - 0x001CE1, - 0x001DFA + 0x001CE1 ], ranges: [ [0x00DC00, 0x00DFFF], @@ -92,7 +92,7 @@ const nonMatchSymbols = buildString({ [0x000656, 0x00066F], [0x000671, 0x000950], [0x000955, 0x001AAF], - [0x001AC1, 0x001CCF], + [0x001ACF, 0x001CCF], [0x001CE9, 0x001CEC], [0x001CEE, 0x001CF3], [0x001CF5, 0x001CF7], @@ -107,7 +107,9 @@ const nonMatchSymbols = buildString({ [0x00FE2E, 0x0101FC], [0x0101FE, 0x0102DF], [0x0102E1, 0x01133A], - [0x01133C, 0x01D166], + [0x01133C, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D166], [0x01D16A, 0x01D17A], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Pahlavi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Pahlavi.js index bba16b3a37cd..36eda8a3d024 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Pahlavi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Pahlavi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Inscriptional_Pahlavi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Parthian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Parthian.js index c7404175ce8a..db50b4d4e082 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Parthian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Parthian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Inscriptional_Parthian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Javanese.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Javanese.js index 4bd2dcdb5d42..6caa51e545a7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Javanese.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Javanese.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Javanese` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kaithi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kaithi.js index 5c8050afc5c6..7301b53141b8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kaithi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kaithi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Kaithi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -18,7 +18,7 @@ const matchSymbols = buildString({ 0x0110CD ], ranges: [ - [0x011080, 0x0110C1] + [0x011080, 0x0110C2] ] }); testPropertyEscapes( @@ -48,7 +48,7 @@ const nonMatchSymbols = buildString({ [0x00DC00, 0x00DFFF], [0x000000, 0x00DBFF], [0x00E000, 0x01107F], - [0x0110C2, 0x0110CC], + [0x0110C3, 0x0110CC], [0x0110CE, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kannada.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kannada.js index bd43544b6379..38b5652d809c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kannada.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kannada.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,16 +7,14 @@ description: > Unicode property escapes for `Script=Kannada` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] ---*/ const matchSymbols = buildString({ - loneCodePoints: [ - 0x000CDE - ], + loneCodePoints: [], ranges: [ [0x000C80, 0x000C8C], [0x000C8E, 0x000C90], @@ -27,6 +25,7 @@ const matchSymbols = buildString({ [0x000CC6, 0x000CC8], [0x000CCA, 0x000CCD], [0x000CD5, 0x000CD6], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE3], [0x000CE6, 0x000CEF], [0x000CF1, 0x000CF2] @@ -69,7 +68,7 @@ const nonMatchSymbols = buildString({ [0x000000, 0x000C7F], [0x000CBA, 0x000CBB], [0x000CCE, 0x000CD4], - [0x000CD7, 0x000CDD], + [0x000CD7, 0x000CDC], [0x000CE4, 0x000CE5], [0x000CF3, 0x00DBFF], [0x00E000, 0x10FFFF] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Katakana.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Katakana.js index 0f6629923faa..df2ed8494a8b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Katakana.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Katakana.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Katakana` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -25,6 +25,10 @@ const matchSymbols = buildString({ [0x003300, 0x003357], [0x00FF66, 0x00FF6F], [0x00FF71, 0x00FF9D], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B120, 0x01B122], [0x01B164, 0x01B167] ] }); @@ -52,7 +56,10 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ 0x0032FF, - 0x00FF70 + 0x00FF70, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF ], ranges: [ [0x00DC00, 0x00DFFF], @@ -62,8 +69,9 @@ const nonMatchSymbols = buildString({ [0x003200, 0x0032CF], [0x003358, 0x00DBFF], [0x00E000, 0x00FF65], - [0x00FF9E, 0x01AFFF], - [0x01B001, 0x01B163], + [0x00FF9E, 0x01AFEF], + [0x01B001, 0x01B11F], + [0x01B123, 0x01B163], [0x01B168, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kayah_Li.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kayah_Li.js index 5fc78c5bf635..693372e20466 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kayah_Li.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kayah_Li.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Kayah_Li` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kharoshthi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kharoshthi.js index 217c21ac4665..7efbbb2511fd 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kharoshthi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Kharoshthi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Kharoshthi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khitan_Small_Script.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khitan_Small_Script.js index 43a77c6d18fc..eaa144221821 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khitan_Small_Script.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khitan_Small_Script.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Khitan_Small_Script` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khmer.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khmer.js index f85401bbb307..45f3cee80228 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khmer.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khmer.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Khmer` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khojki.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khojki.js index 2f91910845a5..2ad8b56094ec 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khojki.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khojki.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Khojki` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khudawadi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khudawadi.js index 31e6cc89e851..dc2c0791489e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khudawadi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Khudawadi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Khudawadi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lao.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lao.js index 7cf24eec5849..873c490af686 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lao.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lao.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Lao` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Latin.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Latin.js index 6a6d62387509..c917f602249d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Latin.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Latin.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Latin` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -20,7 +20,8 @@ const matchSymbols = buildString({ 0x002071, 0x00207F, 0x002132, - 0x00214E + 0x00214E, + 0x00A7D3 ], ranges: [ [0x000041, 0x00005A], @@ -40,15 +41,20 @@ const matchSymbols = buildString({ [0x002160, 0x002188], [0x002C60, 0x002C7F], [0x00A722, 0x00A787], - [0x00A78B, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A7FF], + [0x00A78B, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A7FF], [0x00AB30, 0x00AB5A], [0x00AB5C, 0x00AB64], [0x00AB66, 0x00AB69], [0x00FB00, 0x00FB06], [0x00FF21, 0x00FF3A], - [0x00FF41, 0x00FF5A] + [0x00FF41, 0x00FF5A], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], + [0x01DF00, 0x01DF1E] ] }); testPropertyEscapes( @@ -77,8 +83,12 @@ const nonMatchSymbols = buildString({ 0x0000D7, 0x0000F7, 0x001D78, + 0x00A7D2, + 0x00A7D4, 0x00AB5B, - 0x00AB65 + 0x00AB65, + 0x010786, + 0x0107B1 ], ranges: [ [0x00DC00, 0x00DFFF], @@ -103,14 +113,16 @@ const nonMatchSymbols = buildString({ [0x002189, 0x002C5F], [0x002C80, 0x00A721], [0x00A788, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A800, 0x00AB2F], [0x00AB6A, 0x00DBFF], [0x00E000, 0x00FAFF], [0x00FB07, 0x00FF20], [0x00FF3B, 0x00FF40], - [0x00FF5B, 0x10FFFF] + [0x00FF5B, 0x01077F], + [0x0107BB, 0x01DEFF], + [0x01DF1F, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lepcha.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lepcha.js index cc6469149b9a..97a1948aa0b7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lepcha.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lepcha.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Lepcha` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Limbu.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Limbu.js index 549faf01d73e..df5ee0cf0880 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Limbu.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Limbu.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Limbu` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Linear_A.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Linear_A.js index 5b94c0337d6a..f0f0903e5adf 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Linear_A.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Linear_A.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Linear_A` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Linear_B.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Linear_B.js index 05735653550f..09500068da1a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Linear_B.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Linear_B.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Linear_B` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lisu.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lisu.js index 9a7f83bcd036..6b2e2691a69e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lisu.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lisu.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Lisu` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lycian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lycian.js index bc29fe64cda4..b335c9488926 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lycian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lycian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Lycian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lydian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lydian.js index 14eee88ba285..60ea513d09e4 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lydian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Lydian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Lydian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mahajani.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mahajani.js index 4769a5a0d6f8..00ea9ede2268 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mahajani.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mahajani.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Mahajani` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Makasar.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Makasar.js index cf815b4fc069..132293bd4730 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Makasar.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Makasar.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Makasar` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Malayalam.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Malayalam.js index 4ca958c7eeda..be85d6059c15 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Malayalam.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Malayalam.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Malayalam` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mandaic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mandaic.js index fdaf88743d07..e80c007bb8fa 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mandaic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mandaic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Mandaic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Manichaean.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Manichaean.js index bfb96280661d..705d73b35553 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Manichaean.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Manichaean.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Manichaean` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Marchen.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Marchen.js index 3a29691dd235..6c2d98d32603 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Marchen.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Marchen.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Marchen` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Masaram_Gondi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Masaram_Gondi.js index efec1bb869f7..e71703475cab 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Masaram_Gondi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Masaram_Gondi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Masaram_Gondi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Medefaidrin.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Medefaidrin.js index 90913c0c4f84..0f54f52534ba 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Medefaidrin.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Medefaidrin.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Medefaidrin` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meetei_Mayek.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meetei_Mayek.js index 3995f989ec02..c13c1950b4d7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meetei_Mayek.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meetei_Mayek.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Meetei_Mayek` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mende_Kikakui.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mende_Kikakui.js index bcf6ce89f856..dc11abe4c084 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mende_Kikakui.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mende_Kikakui.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Mende_Kikakui` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meroitic_Cursive.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meroitic_Cursive.js index 356c68fcaaca..a12285201a90 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meroitic_Cursive.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meroitic_Cursive.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Meroitic_Cursive` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meroitic_Hieroglyphs.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meroitic_Hieroglyphs.js index 3457b5f777af..0fad1b29b1e9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meroitic_Hieroglyphs.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Meroitic_Hieroglyphs.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Meroitic_Hieroglyphs` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Miao.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Miao.js index b40cd9bfeebb..eb6a3e19b06f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Miao.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Miao.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Miao` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Modi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Modi.js index 7fec34b3355b..b61f29f5a674 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Modi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Modi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Modi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mongolian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mongolian.js index 8b1c64673a19..a27d5d69ca0d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mongolian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mongolian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Mongolian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -19,8 +19,7 @@ const matchSymbols = buildString({ ], ranges: [ [0x001800, 0x001801], - [0x001806, 0x00180E], - [0x001810, 0x001819], + [0x001806, 0x001819], [0x001820, 0x001878], [0x001880, 0x0018AA], [0x011660, 0x01166C] @@ -49,8 +48,7 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ - 0x001805, - 0x00180F + 0x001805 ], ranges: [ [0x00DC00, 0x00DFFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mro.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mro.js index 53d1858deb91..cac3983c1bb0 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mro.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Mro.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Mro` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Multani.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Multani.js index 8e1ff89ca16d..03d9e547a11c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Multani.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Multani.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Multani` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Myanmar.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Myanmar.js index d830acfe1152..e24e90a1e037 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Myanmar.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Myanmar.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Myanmar` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nabataean.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nabataean.js index 306d98dd21e0..931eee6fa29d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nabataean.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nabataean.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Nabataean` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nandinagari.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nandinagari.js index b79486b9af17..69a7a8e1525f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nandinagari.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nandinagari.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Nandinagari` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_New_Tai_Lue.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_New_Tai_Lue.js index 3d4c8caaa8e2..d41a37987823 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_New_Tai_Lue.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_New_Tai_Lue.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=New_Tai_Lue` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Newa.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Newa.js index 2e1cd46fab62..f4e3407ead05 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Newa.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Newa.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Newa` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nko.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nko.js index d6a3868790d3..77efa2c2d5b2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nko.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nko.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Nko` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nushu.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nushu.js index 201ec12ad339..e1d706ba7e93 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nushu.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nushu.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Nushu` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nyiakeng_Puachue_Hmong.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nyiakeng_Puachue_Hmong.js index 9ad6e576f1ca..87d28d185e95 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nyiakeng_Puachue_Hmong.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Nyiakeng_Puachue_Hmong.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Nyiakeng_Puachue_Hmong` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ogham.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ogham.js index 934e64e044c4..94ff4ac5b064 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ogham.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ogham.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Ogham` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ol_Chiki.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ol_Chiki.js index c44554ef0878..7ebd96a3761f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ol_Chiki.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ol_Chiki.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Ol_Chiki` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Hungarian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Hungarian.js index 390d731adbd8..aa225f8a48e5 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Hungarian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Hungarian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Old_Hungarian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Italic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Italic.js index fd6eeef62e8a..9951abd26460 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Italic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Italic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Old_Italic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_North_Arabian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_North_Arabian.js index b4240ba076a3..63e3c96861b8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_North_Arabian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_North_Arabian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Old_North_Arabian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Permic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Permic.js index b88cd8c2a80c..72d8f1dd1aab 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Permic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Permic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Old_Permic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Persian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Persian.js index 1aa6072a0931..aa8f0b4d3104 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Persian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Persian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Old_Persian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Sogdian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Sogdian.js index c3057832a64b..68089331b4bd 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Sogdian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Sogdian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Old_Sogdian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_South_Arabian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_South_Arabian.js index 9ac434bb377c..3a7e49f97cdb 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_South_Arabian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_South_Arabian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Old_South_Arabian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Turkic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Turkic.js index 7457713e6e3f..fb9aa1e38d13 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Turkic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Turkic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Old_Turkic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Uyghur.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Uyghur.js new file mode 100644 index 000000000000..63f16b590086 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Old_Uyghur.js @@ -0,0 +1,73 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script=Old_Uyghur` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x010F70, 0x010F89] + ] +}); +testPropertyEscapes( + /^\p{Script=Old_Uyghur}+$/u, + matchSymbols, + "\\p{Script=Old_Uyghur}" +); +testPropertyEscapes( + /^\p{Script=Ougr}+$/u, + matchSymbols, + "\\p{Script=Ougr}" +); +testPropertyEscapes( + /^\p{sc=Old_Uyghur}+$/u, + matchSymbols, + "\\p{sc=Old_Uyghur}" +); +testPropertyEscapes( + /^\p{sc=Ougr}+$/u, + matchSymbols, + "\\p{sc=Ougr}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x010F6F], + [0x010F8A, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script=Old_Uyghur}+$/u, + nonMatchSymbols, + "\\P{Script=Old_Uyghur}" +); +testPropertyEscapes( + /^\P{Script=Ougr}+$/u, + nonMatchSymbols, + "\\P{Script=Ougr}" +); +testPropertyEscapes( + /^\P{sc=Old_Uyghur}+$/u, + nonMatchSymbols, + "\\P{sc=Old_Uyghur}" +); +testPropertyEscapes( + /^\P{sc=Ougr}+$/u, + nonMatchSymbols, + "\\P{sc=Ougr}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Oriya.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Oriya.js index a97eddcce32a..d740d5dd7a7e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Oriya.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Oriya.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Oriya` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Osage.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Osage.js index 2ab2a3c714ba..5b175c873e35 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Osage.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Osage.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Osage` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Osmanya.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Osmanya.js index a5c18bb21dc4..ae4b7a8d9496 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Osmanya.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Osmanya.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Osmanya` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Pahawh_Hmong.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Pahawh_Hmong.js index af27d858c925..9c6bce338505 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Pahawh_Hmong.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Pahawh_Hmong.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Pahawh_Hmong` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Palmyrene.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Palmyrene.js index f4bbb85c0006..827a02bf3947 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Palmyrene.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Palmyrene.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Palmyrene` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Pau_Cin_Hau.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Pau_Cin_Hau.js index 4d401cb11bf7..0b82fa51a9df 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Pau_Cin_Hau.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Pau_Cin_Hau.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Pau_Cin_Hau` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Phags_Pa.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Phags_Pa.js index 16b3f6e1edd4..4c210db918c1 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Phags_Pa.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Phags_Pa.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Phags_Pa` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Phoenician.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Phoenician.js index 1bc0aa043496..7315bd32e959 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Phoenician.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Phoenician.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Phoenician` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Psalter_Pahlavi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Psalter_Pahlavi.js index 3008af9a0ab5..ea0e49d0f4f8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Psalter_Pahlavi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Psalter_Pahlavi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Psalter_Pahlavi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Rejang.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Rejang.js index 4d2a66d7eaee..b0722f964a14 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Rejang.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Rejang.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Rejang` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Runic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Runic.js index d223712c8bb5..55fd60ec82da 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Runic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Runic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Runic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Samaritan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Samaritan.js index 49c590564387..85d3d189224a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Samaritan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Samaritan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Samaritan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Saurashtra.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Saurashtra.js index 9fcf8cbd9eb0..336b13c4116b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Saurashtra.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Saurashtra.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Saurashtra` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sharada.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sharada.js index 30a60bd27809..8ae1e4ff79b2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sharada.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sharada.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Sharada` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Shavian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Shavian.js index c03fa74cab8e..b66b504270ed 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Shavian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Shavian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Shavian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Siddham.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Siddham.js index 9bd65a8d418a..975affb45e79 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Siddham.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Siddham.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Siddham` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_SignWriting.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_SignWriting.js index 048430cd18c7..88ae17494e40 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_SignWriting.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_SignWriting.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=SignWriting` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sinhala.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sinhala.js index 34c5daca2b7f..edcf4f9a343f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sinhala.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sinhala.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Sinhala` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sogdian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sogdian.js index 92f778e5678e..aa7e5962eb3e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sogdian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sogdian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Sogdian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sora_Sompeng.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sora_Sompeng.js index 438b725728c6..173f7c1e178f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sora_Sompeng.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sora_Sompeng.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Sora_Sompeng` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Soyombo.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Soyombo.js index a03a2f8cf852..f8f750b46db3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Soyombo.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Soyombo.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Soyombo` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sundanese.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sundanese.js index dc57445f3b3d..e10c59c4872c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sundanese.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Sundanese.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Sundanese` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Syloti_Nagri.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Syloti_Nagri.js index ecbfc1b424d5..4f9bb1b41522 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Syloti_Nagri.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Syloti_Nagri.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Syloti_Nagri` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Syriac.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Syriac.js index 81b2fa06d534..0101753a3ad5 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Syriac.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Syriac.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Syriac` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagalog.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagalog.js index dc22a8786cac..98daf3897662 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagalog.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagalog.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,17 +7,18 @@ description: > Unicode property escapes for `Script=Tagalog` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] ---*/ const matchSymbols = buildString({ - loneCodePoints: [], + loneCodePoints: [ + 0x00171F + ], ranges: [ - [0x001700, 0x00170C], - [0x00170E, 0x001714] + [0x001700, 0x001715] ] }); testPropertyEscapes( @@ -42,13 +43,12 @@ testPropertyEscapes( ); const nonMatchSymbols = buildString({ - loneCodePoints: [ - 0x00170D - ], + loneCodePoints: [], ranges: [ [0x00DC00, 0x00DFFF], [0x000000, 0x0016FF], - [0x001715, 0x00DBFF], + [0x001716, 0x00171E], + [0x001720, 0x00DBFF], [0x00E000, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagbanwa.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagbanwa.js index 12238425b8dc..f3c862781140 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagbanwa.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagbanwa.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tagbanwa` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Le.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Le.js index 7e9f1b5b7462..2f9bc4d7c222 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Le.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Le.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tai_Le` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Tham.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Tham.js index 6fb11ceb4780..361ca6ac87ed 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Tham.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Tham.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tai_Tham` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Viet.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Viet.js index 73bffc7f7d9c..87581230b433 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Viet.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tai_Viet.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tai_Viet` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Takri.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Takri.js index 6937f6d2a609..50b9dd0fc12b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Takri.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Takri.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Takri` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -16,7 +16,7 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [], ranges: [ - [0x011680, 0x0116B8], + [0x011680, 0x0116B9], [0x0116C0, 0x0116C9] ] }); @@ -47,7 +47,7 @@ const nonMatchSymbols = buildString({ [0x00DC00, 0x00DFFF], [0x000000, 0x00DBFF], [0x00E000, 0x01167F], - [0x0116B9, 0x0116BF], + [0x0116BA, 0x0116BF], [0x0116CA, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tamil.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tamil.js index 1b21ab28f134..d01f808da115 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tamil.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tamil.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tamil` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tangsa.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tangsa.js new file mode 100644 index 000000000000..af6cffb81133 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tangsa.js @@ -0,0 +1,76 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script=Tangsa` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x016A70, 0x016ABE], + [0x016AC0, 0x016AC9] + ] +}); +testPropertyEscapes( + /^\p{Script=Tangsa}+$/u, + matchSymbols, + "\\p{Script=Tangsa}" +); +testPropertyEscapes( + /^\p{Script=Tnsa}+$/u, + matchSymbols, + "\\p{Script=Tnsa}" +); +testPropertyEscapes( + /^\p{sc=Tangsa}+$/u, + matchSymbols, + "\\p{sc=Tangsa}" +); +testPropertyEscapes( + /^\p{sc=Tnsa}+$/u, + matchSymbols, + "\\p{sc=Tnsa}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [ + 0x016ABF + ], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x016A6F], + [0x016ACA, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script=Tangsa}+$/u, + nonMatchSymbols, + "\\P{Script=Tangsa}" +); +testPropertyEscapes( + /^\P{Script=Tnsa}+$/u, + nonMatchSymbols, + "\\P{Script=Tnsa}" +); +testPropertyEscapes( + /^\P{sc=Tangsa}+$/u, + nonMatchSymbols, + "\\P{sc=Tangsa}" +); +testPropertyEscapes( + /^\P{sc=Tnsa}+$/u, + nonMatchSymbols, + "\\P{sc=Tnsa}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tangut.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tangut.js index c97ede1858a0..c00a8d8433ad 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tangut.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tangut.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tangut` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Telugu.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Telugu.js index 1a2a83ebd04e..080e39f30bd9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Telugu.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Telugu.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,20 +7,22 @@ description: > Unicode property escapes for `Script=Telugu` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] ---*/ const matchSymbols = buildString({ - loneCodePoints: [], + loneCodePoints: [ + 0x000C5D + ], ranges: [ [0x000C00, 0x000C0C], [0x000C0E, 0x000C10], [0x000C12, 0x000C28], [0x000C2A, 0x000C39], - [0x000C3D, 0x000C44], + [0x000C3C, 0x000C44], [0x000C46, 0x000C48], [0x000C4A, 0x000C4D], [0x000C55, 0x000C56], @@ -63,9 +65,10 @@ const nonMatchSymbols = buildString({ ranges: [ [0x00DC00, 0x00DFFF], [0x000000, 0x000BFF], - [0x000C3A, 0x000C3C], + [0x000C3A, 0x000C3B], [0x000C4E, 0x000C54], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C64, 0x000C65], [0x000C70, 0x000C76], [0x000C80, 0x00DBFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Thaana.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Thaana.js index 8397bbcd27b7..a60dd52420e4 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Thaana.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Thaana.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Thaana` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Thai.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Thai.js index e48020ea147f..066e220ce0d3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Thai.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Thai.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Thai` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tibetan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tibetan.js index 84ad5a499423..76e05bf32f75 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tibetan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tibetan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tibetan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tifinagh.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tifinagh.js index beef21d48a29..12f00b11160f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tifinagh.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tifinagh.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tifinagh` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tirhuta.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tirhuta.js index 99aff408a07d..7538897d387b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tirhuta.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Tirhuta.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Tirhuta` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Toto.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Toto.js new file mode 100644 index 000000000000..d40f673e7043 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Toto.js @@ -0,0 +1,73 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script=Toto` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x01E290, 0x01E2AE] + ] +}); +testPropertyEscapes( + /^\p{Script=Toto}+$/u, + matchSymbols, + "\\p{Script=Toto}" +); +testPropertyEscapes( + /^\p{Script=Toto}+$/u, + matchSymbols, + "\\p{Script=Toto}" +); +testPropertyEscapes( + /^\p{sc=Toto}+$/u, + matchSymbols, + "\\p{sc=Toto}" +); +testPropertyEscapes( + /^\p{sc=Toto}+$/u, + matchSymbols, + "\\p{sc=Toto}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x01E28F], + [0x01E2AF, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script=Toto}+$/u, + nonMatchSymbols, + "\\P{Script=Toto}" +); +testPropertyEscapes( + /^\P{Script=Toto}+$/u, + nonMatchSymbols, + "\\P{Script=Toto}" +); +testPropertyEscapes( + /^\P{sc=Toto}+$/u, + nonMatchSymbols, + "\\P{sc=Toto}" +); +testPropertyEscapes( + /^\P{sc=Toto}+$/u, + nonMatchSymbols, + "\\P{sc=Toto}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ugaritic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ugaritic.js index d3aefe01330d..6b92ecdbc892 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ugaritic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ugaritic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Ugaritic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Vai.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Vai.js index c92b8c4e8d94..4c02aad5e4cc 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Vai.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Vai.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Vai` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Vithkuqi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Vithkuqi.js new file mode 100644 index 000000000000..12e23715ac35 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Vithkuqi.js @@ -0,0 +1,88 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script=Vithkuqi` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC] + ] +}); +testPropertyEscapes( + /^\p{Script=Vithkuqi}+$/u, + matchSymbols, + "\\p{Script=Vithkuqi}" +); +testPropertyEscapes( + /^\p{Script=Vith}+$/u, + matchSymbols, + "\\p{Script=Vith}" +); +testPropertyEscapes( + /^\p{sc=Vithkuqi}+$/u, + matchSymbols, + "\\p{sc=Vithkuqi}" +); +testPropertyEscapes( + /^\p{sc=Vith}+$/u, + matchSymbols, + "\\p{sc=Vith}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [ + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA + ], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x01056F], + [0x0105BD, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script=Vithkuqi}+$/u, + nonMatchSymbols, + "\\P{Script=Vithkuqi}" +); +testPropertyEscapes( + /^\P{Script=Vith}+$/u, + nonMatchSymbols, + "\\P{Script=Vith}" +); +testPropertyEscapes( + /^\P{sc=Vithkuqi}+$/u, + nonMatchSymbols, + "\\P{sc=Vithkuqi}" +); +testPropertyEscapes( + /^\P{sc=Vith}+$/u, + nonMatchSymbols, + "\\P{sc=Vith}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Wancho.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Wancho.js index 2ea8510fbeca..476163a94209 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Wancho.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Wancho.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Wancho` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Warang_Citi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Warang_Citi.js index d354a032fd85..6ae85cf4c42e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Warang_Citi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Warang_Citi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Warang_Citi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Yezidi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Yezidi.js index a3781311d553..0af3896ac9db 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Yezidi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Yezidi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Yezidi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Yi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Yi.js index ba97345e0b09..d9518a48080c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Yi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Yi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Yi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Zanabazar_Square.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Zanabazar_Square.js index 8a9bdaa02124..32f962183dbe 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Zanabazar_Square.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Zanabazar_Square.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script=Zanabazar_Square` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Adlam.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Adlam.js index 417c47ef6e62..d3a9a04d7a15 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Adlam.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Adlam.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Adlam` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -15,6 +15,7 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [ + 0x00061F, 0x000640 ], ranges: [ @@ -48,7 +49,8 @@ const nonMatchSymbols = buildString({ loneCodePoints: [], ranges: [ [0x00DC00, 0x00DFFF], - [0x000000, 0x00063F], + [0x000000, 0x00061E], + [0x000620, 0x00063F], [0x000641, 0x00DBFF], [0x00E000, 0x01E8FF], [0x01E94C, 0x01E94F], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ahom.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ahom.js index 6ee8c90a5d35..6847295217d5 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ahom.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ahom.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Ahom` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -18,7 +18,7 @@ const matchSymbols = buildString({ ranges: [ [0x011700, 0x01171A], [0x01171D, 0x01172B], - [0x011730, 0x01173F] + [0x011730, 0x011746] ] }); testPropertyEscapes( @@ -50,7 +50,7 @@ const nonMatchSymbols = buildString({ [0x00E000, 0x0116FF], [0x01171B, 0x01171C], [0x01172C, 0x01172F], - [0x011740, 0x10FFFF] + [0x011747, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Anatolian_Hieroglyphs.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Anatolian_Hieroglyphs.js index 1bfe8dd61abb..e74096132fae 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Anatolian_Hieroglyphs.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Anatolian_Hieroglyphs.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Anatolian_Hieroglyphs` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Arabic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Arabic.js index 38503ab9be07..977fc99a7d80 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Arabic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Arabic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Arabic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -15,6 +15,7 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [ + 0x00FDCF, 0x01EE24, 0x01EE27, 0x01EE39, @@ -34,19 +35,17 @@ const matchSymbols = buildString({ ], ranges: [ [0x000600, 0x000604], - [0x000606, 0x00061C], - [0x00061E, 0x0006DC], + [0x000606, 0x0006DC], [0x0006DE, 0x0006FF], [0x000750, 0x00077F], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], - [0x0008D3, 0x0008E1], + [0x000870, 0x00088E], + [0x000890, 0x000891], + [0x000898, 0x0008E1], [0x0008E3, 0x0008FF], - [0x00FB50, 0x00FBC1], - [0x00FBD3, 0x00FD3D], - [0x00FD50, 0x00FD8F], + [0x00FB50, 0x00FBC2], + [0x00FBD3, 0x00FD8F], [0x00FD92, 0x00FDC7], - [0x00FDF0, 0x00FDFD], + [0x00FDF0, 0x00FDFF], [0x00FE70, 0x00FE74], [0x00FE76, 0x00FEFC], [0x0102E0, 0x0102FB], @@ -95,9 +94,8 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ 0x000605, - 0x00061D, 0x0006DD, - 0x0008B5, + 0x00088F, 0x0008E2, 0x00FE75, 0x01EE04, @@ -131,15 +129,15 @@ const nonMatchSymbols = buildString({ [0x00DC00, 0x00DFFF], [0x000000, 0x0005FF], [0x000700, 0x00074F], - [0x000780, 0x00089F], - [0x0008C8, 0x0008D2], + [0x000780, 0x00086F], + [0x000892, 0x000897], [0x000900, 0x00DBFF], [0x00E000, 0x00FB4F], - [0x00FBC2, 0x00FBD2], - [0x00FD3E, 0x00FD4F], + [0x00FBC3, 0x00FBD2], [0x00FD90, 0x00FD91], - [0x00FDC8, 0x00FDEF], - [0x00FDFE, 0x00FE6F], + [0x00FDC8, 0x00FDCE], + [0x00FDD0, 0x00FDEF], + [0x00FE00, 0x00FE6F], [0x00FEFD, 0x0102DF], [0x0102FC, 0x010E5F], [0x010E7F, 0x01EDFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Armenian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Armenian.js index 8bed6510d875..0c500bc36959 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Armenian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Armenian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Armenian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Avestan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Avestan.js index dfb28b365411..35b008dd34c3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Avestan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Avestan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Avestan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Balinese.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Balinese.js index bb6aadf90721..cc6d9160a307 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Balinese.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Balinese.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Balinese` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -16,8 +16,8 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [], ranges: [ - [0x001B00, 0x001B4B], - [0x001B50, 0x001B7C] + [0x001B00, 0x001B4C], + [0x001B50, 0x001B7E] ] }); testPropertyEscapes( @@ -46,8 +46,8 @@ const nonMatchSymbols = buildString({ ranges: [ [0x00DC00, 0x00DFFF], [0x000000, 0x001AFF], - [0x001B4C, 0x001B4F], - [0x001B7D, 0x00DBFF], + [0x001B4D, 0x001B4F], + [0x001B7F, 0x00DBFF], [0x00E000, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bamum.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bamum.js index 1c63cdfdf1b3..82b55a7da0d2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bamum.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bamum.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Bamum` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bassa_Vah.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bassa_Vah.js index ae6ee1d56ce3..28189560412f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bassa_Vah.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bassa_Vah.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Bassa_Vah` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Batak.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Batak.js index be6d3633fdd0..c1183f2c2da9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Batak.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Batak.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Batak` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bengali.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bengali.js index 0b13dd33dab9..9c4e0368f235 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bengali.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bengali.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Bengali` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bhaiksuki.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bhaiksuki.js index 425fe2cc8533..b620204df998 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bhaiksuki.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bhaiksuki.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Bhaiksuki` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bopomofo.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bopomofo.js index b3644f753752..6ba24346c2a3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bopomofo.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Bopomofo.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Bopomofo` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Brahmi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Brahmi.js index e898bcda102e..5c73b1f22cef 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Brahmi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Brahmi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Brahmi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -19,7 +19,7 @@ const matchSymbols = buildString({ ], ranges: [ [0x011000, 0x01104D], - [0x011052, 0x01106F] + [0x011052, 0x011075] ] }); testPropertyEscapes( @@ -50,7 +50,7 @@ const nonMatchSymbols = buildString({ [0x000000, 0x00DBFF], [0x00E000, 0x010FFF], [0x01104E, 0x011051], - [0x011070, 0x01107E], + [0x011076, 0x01107E], [0x011080, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Braille.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Braille.js index 4fb2d3f79e87..885d13f7c733 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Braille.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Braille.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Braille` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Buginese.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Buginese.js index 54df864ac644..14eaa6c72b5c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Buginese.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Buginese.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Buginese` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Buhid.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Buhid.js index e25cdfac9cca..e3828476ec1b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Buhid.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Buhid.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Buhid` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Canadian_Aboriginal.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Canadian_Aboriginal.js index 85fbe6b8f2f1..d3727e53b4b9 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Canadian_Aboriginal.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Canadian_Aboriginal.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Canadian_Aboriginal` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -17,7 +17,8 @@ const matchSymbols = buildString({ loneCodePoints: [], ranges: [ [0x001400, 0x00167F], - [0x0018B0, 0x0018F5] + [0x0018B0, 0x0018F5], + [0x011AB0, 0x011ABF] ] }); testPropertyEscapes( @@ -48,7 +49,8 @@ const nonMatchSymbols = buildString({ [0x000000, 0x0013FF], [0x001680, 0x0018AF], [0x0018F6, 0x00DBFF], - [0x00E000, 0x10FFFF] + [0x00E000, 0x011AAF], + [0x011AC0, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Carian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Carian.js index 520d8c9f1614..e409b03fe36b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Carian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Carian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Carian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Caucasian_Albanian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Caucasian_Albanian.js index 8f7c9632e513..2877762274e7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Caucasian_Albanian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Caucasian_Albanian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Caucasian_Albanian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Chakma.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Chakma.js index 8b6f09c41051..fa33083e5f4a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Chakma.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Chakma.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Chakma` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cham.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cham.js index ea1c3c171cab..8bcc3dc082c7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cham.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cham.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Cham` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cherokee.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cherokee.js index 484d87bd0489..1f3a2116884f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cherokee.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cherokee.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Cherokee` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Chorasmian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Chorasmian.js index ad66cc3d5f35..3c14f1417002 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Chorasmian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Chorasmian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Chorasmian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Common.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Common.js index 63854ab63b39..d862dd35cd44 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Common.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Common.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Common` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -37,6 +37,7 @@ const matchSymbols = buildString({ 0x01D4A2, 0x01D4BB, 0x01D546, + 0x01F7F0, 0x0E0001 ], ranges: [ @@ -56,7 +57,7 @@ const matchSymbols = buildString({ [0x002066, 0x002070], [0x002074, 0x00207E], [0x002080, 0x00208E], - [0x0020A0, 0x0020BF], + [0x0020A0, 0x0020C0], [0x002100, 0x002125], [0x002127, 0x002129], [0x00212C, 0x002131], @@ -70,7 +71,7 @@ const matchSymbols = buildString({ [0x002B76, 0x002B95], [0x002B97, 0x002BFF], [0x002E00, 0x002E42], - [0x002E44, 0x002E52], + [0x002E44, 0x002E5D], [0x002FF0, 0x002FFB], [0x003248, 0x00325F], [0x0032B1, 0x0032BF], @@ -81,7 +82,6 @@ const matchSymbols = buildString({ [0x00A708, 0x00A721], [0x00A788, 0x00A78A], [0x00AB6A, 0x00AB6B], - [0x00FD3E, 0x00FD3F], [0x00FE10, 0x00FE19], [0x00FE30, 0x00FE44], [0x00FE47, 0x00FE52], @@ -95,14 +95,14 @@ const matchSymbols = buildString({ [0x00FFF9, 0x00FFFD], [0x010190, 0x01019C], [0x0101D0, 0x0101FC], - [0x016FE2, 0x016FE3], + [0x01CF50, 0x01CFC3], [0x01D000, 0x01D0F5], [0x01D100, 0x01D126], [0x01D129, 0x01D166], [0x01D16A, 0x01D17A], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], - [0x01D1AE, 0x01D1E8], + [0x01D1AE, 0x01D1EA], [0x01D2E0, 0x01D2F3], [0x01D300, 0x01D356], [0x01D372, 0x01D378], @@ -139,7 +139,7 @@ const matchSymbols = buildString({ [0x01F240, 0x01F248], [0x01F260, 0x01F265], [0x01F300, 0x01F6D7], - [0x01F6E0, 0x01F6EC], + [0x01F6DD, 0x01F6EC], [0x01F6F0, 0x01F6FC], [0x01F700, 0x01F773], [0x01F780, 0x01F7D8], @@ -150,17 +150,17 @@ const matchSymbols = buildString({ [0x01F860, 0x01F887], [0x01F890, 0x01F8AD], [0x01F8B0, 0x01F8B1], - [0x01F900, 0x01F978], - [0x01F97A, 0x01F9CB], - [0x01F9CD, 0x01FA53], + [0x01F900, 0x01FA53], [0x01FA60, 0x01FA6D], [0x01FA70, 0x01FA74], - [0x01FA78, 0x01FA7A], + [0x01FA78, 0x01FA7C], [0x01FA80, 0x01FA86], - [0x01FA90, 0x01FAA8], - [0x01FAB0, 0x01FAB6], - [0x01FAC0, 0x01FAC2], - [0x01FAD0, 0x01FAD6], + [0x01FA90, 0x01FAAC], + [0x01FAB0, 0x01FABA], + [0x01FAC0, 0x01FAC5], + [0x01FAD0, 0x01FAD9], + [0x01FAE0, 0x01FAE7], + [0x01FAF0, 0x01FAF6], [0x01FB00, 0x01FB92], [0x01FB94, 0x01FBCA], [0x01FBF0, 0x01FBF9], @@ -221,8 +221,6 @@ const nonMatchSymbols = buildString({ 0x01F0C0, 0x01F0D0, 0x01F200, - 0x01F979, - 0x01F9CC, 0x01FB93 ], ranges: [ @@ -247,7 +245,7 @@ const nonMatchSymbols = buildString({ [0x00200C, 0x00200D], [0x002071, 0x002073], [0x00208F, 0x00209F], - [0x0020C0, 0x0020FF], + [0x0020C1, 0x0020FF], [0x00212A, 0x00212B], [0x002160, 0x002188], [0x00218C, 0x00218F], @@ -256,7 +254,7 @@ const nonMatchSymbols = buildString({ [0x002800, 0x0028FF], [0x002B74, 0x002B75], [0x002C00, 0x002DFF], - [0x002E53, 0x002FEF], + [0x002E5E, 0x002FEF], [0x002FFC, 0x002FFF], [0x003001, 0x003003], [0x003005, 0x003011], @@ -275,8 +273,7 @@ const nonMatchSymbols = buildString({ [0x00A78B, 0x00AB5A], [0x00AB5C, 0x00AB69], [0x00AB6C, 0x00DBFF], - [0x00E000, 0x00FD3D], - [0x00FD40, 0x00FE0F], + [0x00E000, 0x00FE0F], [0x00FE1A, 0x00FE2F], [0x00FE45, 0x00FE46], [0x00FE6C, 0x00FEFE], @@ -286,15 +283,15 @@ const nonMatchSymbols = buildString({ [0x00FFEF, 0x00FFF8], [0x00FFFE, 0x01018F], [0x01019D, 0x0101CF], - [0x0101FD, 0x016FE1], - [0x016FE4, 0x01CFFF], + [0x0101FD, 0x01CF4F], + [0x01CFC4, 0x01CFFF], [0x01D0F6, 0x01D0FF], [0x01D127, 0x01D128], [0x01D167, 0x01D169], [0x01D17B, 0x01D182], [0x01D185, 0x01D18B], [0x01D1AA, 0x01D1AD], - [0x01D1E9, 0x01D2DF], + [0x01D1EB, 0x01D2DF], [0x01D2F4, 0x01D2FF], [0x01D357, 0x01D371], [0x01D379, 0x01D3FF], @@ -317,12 +314,13 @@ const nonMatchSymbols = buildString({ [0x01F23C, 0x01F23F], [0x01F249, 0x01F25F], [0x01F266, 0x01F2FF], - [0x01F6D8, 0x01F6DF], + [0x01F6D8, 0x01F6DC], [0x01F6ED, 0x01F6EF], [0x01F6FD, 0x01F6FF], [0x01F774, 0x01F77F], [0x01F7D9, 0x01F7DF], - [0x01F7EC, 0x01F7FF], + [0x01F7EC, 0x01F7EF], + [0x01F7F1, 0x01F7FF], [0x01F80C, 0x01F80F], [0x01F848, 0x01F84F], [0x01F85A, 0x01F85F], @@ -332,12 +330,14 @@ const nonMatchSymbols = buildString({ [0x01FA54, 0x01FA5F], [0x01FA6E, 0x01FA6F], [0x01FA75, 0x01FA77], - [0x01FA7B, 0x01FA7F], + [0x01FA7D, 0x01FA7F], [0x01FA87, 0x01FA8F], - [0x01FAA9, 0x01FAAF], - [0x01FAB7, 0x01FABF], - [0x01FAC3, 0x01FACF], - [0x01FAD7, 0x01FAFF], + [0x01FAAD, 0x01FAAF], + [0x01FABB, 0x01FABF], + [0x01FAC6, 0x01FACF], + [0x01FADA, 0x01FADF], + [0x01FAE8, 0x01FAEF], + [0x01FAF7, 0x01FAFF], [0x01FBCB, 0x01FBEF], [0x01FBFA, 0x0E0000], [0x0E0002, 0x0E001F], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Coptic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Coptic.js index bd125561f416..fbd41b9ab9c6 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Coptic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Coptic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Coptic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cuneiform.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cuneiform.js index 1f9b1d7c5ffe..b0b13fa25ea5 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cuneiform.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cuneiform.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Cuneiform` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cypriot.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cypriot.js index a03f80971e40..2cc4e26d0cf2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cypriot.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cypriot.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Cypriot` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cypro_Minoan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cypro_Minoan.js new file mode 100644 index 000000000000..45995ae6f96d --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cypro_Minoan.js @@ -0,0 +1,75 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script_Extensions=Cypro_Minoan` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x010100, 0x010101], + [0x012F90, 0x012FF2] + ] +}); +testPropertyEscapes( + /^\p{Script_Extensions=Cypro_Minoan}+$/u, + matchSymbols, + "\\p{Script_Extensions=Cypro_Minoan}" +); +testPropertyEscapes( + /^\p{Script_Extensions=Cpmn}+$/u, + matchSymbols, + "\\p{Script_Extensions=Cpmn}" +); +testPropertyEscapes( + /^\p{scx=Cypro_Minoan}+$/u, + matchSymbols, + "\\p{scx=Cypro_Minoan}" +); +testPropertyEscapes( + /^\p{scx=Cpmn}+$/u, + matchSymbols, + "\\p{scx=Cpmn}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x0100FF], + [0x010102, 0x012F8F], + [0x012FF3, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script_Extensions=Cypro_Minoan}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Cypro_Minoan}" +); +testPropertyEscapes( + /^\P{Script_Extensions=Cpmn}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Cpmn}" +); +testPropertyEscapes( + /^\P{scx=Cypro_Minoan}+$/u, + nonMatchSymbols, + "\\P{scx=Cypro_Minoan}" +); +testPropertyEscapes( + /^\P{scx=Cpmn}+$/u, + nonMatchSymbols, + "\\P{scx=Cpmn}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cyrillic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cyrillic.js index 9f7612e613ca..01d1e80ec003 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cyrillic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Cyrillic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Cyrillic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Deseret.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Deseret.js index 35fa22e513d7..60e3c5a4b394 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Deseret.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Deseret.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Deseret` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Devanagari.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Devanagari.js index c0241a409247..a04aa669d03a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Devanagari.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Devanagari.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Devanagari` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Dives_Akuru.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Dives_Akuru.js index 19968d05e024..433e0ddf8186 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Dives_Akuru.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Dives_Akuru.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Dives_Akuru` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Dogra.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Dogra.js index 8f78f9d9a6ad..b463f87ea1ff 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Dogra.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Dogra.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Dogra` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Duployan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Duployan.js index 95ff12c35e7a..4ab8b663e366 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Duployan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Duployan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Duployan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Egyptian_Hieroglyphs.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Egyptian_Hieroglyphs.js index b9e30afa7e3c..a8525d79b45e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Egyptian_Hieroglyphs.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Egyptian_Hieroglyphs.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Egyptian_Hieroglyphs` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Elbasan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Elbasan.js index 449c7e7a405d..2b43adb26b0c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Elbasan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Elbasan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Elbasan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Elymaic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Elymaic.js index dd6f5390cac5..b3d4c41be210 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Elymaic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Elymaic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Elymaic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ethiopic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ethiopic.js index 8398b47c3641..8b827728af9f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ethiopic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ethiopic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Ethiopic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -48,7 +48,11 @@ const matchSymbols = buildString({ [0x00AB09, 0x00AB0E], [0x00AB11, 0x00AB16], [0x00AB20, 0x00AB26], - [0x00AB28, 0x00AB2E] + [0x00AB28, 0x00AB2E], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE] ] }); testPropertyEscapes( @@ -90,7 +94,10 @@ const nonMatchSymbols = buildString({ 0x002DC7, 0x002DCF, 0x002DD7, - 0x00AB27 + 0x00AB27, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF ], ranges: [ [0x00DC00, 0x00DFFF], @@ -110,7 +117,8 @@ const nonMatchSymbols = buildString({ [0x00AB0F, 0x00AB10], [0x00AB17, 0x00AB1F], [0x00AB2F, 0x00DBFF], - [0x00E000, 0x10FFFF] + [0x00E000, 0x01E7DF], + [0x01E7FF, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Georgian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Georgian.js index 077bc0c04c7b..75e114251744 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Georgian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Georgian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Georgian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Glagolitic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Glagolitic.js index 3fbe3bab34ae..b0afed45c273 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Glagolitic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Glagolitic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Glagolitic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -21,8 +21,7 @@ const matchSymbols = buildString({ 0x00A66F ], ranges: [ - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], + [0x002C00, 0x002C5F], [0x01E000, 0x01E006], [0x01E008, 0x01E018], [0x01E01B, 0x01E021], @@ -53,7 +52,6 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ - 0x002C2F, 0x01E007, 0x01E022, 0x01E025 @@ -63,7 +61,7 @@ const nonMatchSymbols = buildString({ [0x000000, 0x000483], [0x000485, 0x000486], [0x000488, 0x002BFF], - [0x002C5F, 0x002E42], + [0x002C60, 0x002E42], [0x002E44, 0x00A66E], [0x00A670, 0x00DBFF], [0x00E000, 0x01DFFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gothic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gothic.js index cea4b18b138c..6fe0b0be652f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gothic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gothic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Gothic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Grantha.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Grantha.js index 79e55a0cbe2d..2ff784773022 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Grantha.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Grantha.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Grantha` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Greek.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Greek.js index 8ff0406bc104..2194dcf695dd 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Greek.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Greek.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Greek` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gujarati.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gujarati.js index 6e3f99d9c8ef..4a979e859dd5 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gujarati.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gujarati.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Gujarati` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gunjala_Gondi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gunjala_Gondi.js index 2ed0acb15417..f2c405ee2a8b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gunjala_Gondi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gunjala_Gondi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Gunjala_Gondi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gurmukhi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gurmukhi.js index ce7547b09505..d42cd56951ce 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gurmukhi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Gurmukhi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Gurmukhi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Han.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Han.js index 5cc68a9b2c90..c34c247f17c8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Han.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Han.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Han` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -37,17 +37,18 @@ const matchSymbols = buildString({ [0x00337B, 0x00337F], [0x0033E0, 0x0033FE], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], + [0x004E00, 0x009FFF], [0x00A700, 0x00A707], [0x00F900, 0x00FA6D], [0x00FA70, 0x00FAD9], [0x00FE45, 0x00FE46], [0x00FF61, 0x00FF65], + [0x016FE2, 0x016FE3], [0x016FF0, 0x016FF1], [0x01D360, 0x01D371], [0x01F250, 0x01F251], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -102,18 +103,19 @@ const nonMatchSymbols = buildString({ [0x003371, 0x00337A], [0x003380, 0x0033DF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x00A6FF], + [0x00A000, 0x00A6FF], [0x00A708, 0x00DBFF], [0x00E000, 0x00F8FF], [0x00FA6E, 0x00FA6F], [0x00FADA, 0x00FE44], [0x00FE47, 0x00FF60], - [0x00FF66, 0x016FEF], + [0x00FF66, 0x016FE1], + [0x016FE4, 0x016FEF], [0x016FF2, 0x01D35F], [0x01D372, 0x01F24F], [0x01F252, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hangul.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hangul.js index b3365de3d461..3ea765ff34fa 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hangul.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hangul.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Hangul` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hanifi_Rohingya.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hanifi_Rohingya.js index 0afa9c3c0c7d..cec51cadb499 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hanifi_Rohingya.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hanifi_Rohingya.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Hanifi_Rohingya` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hanunoo.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hanunoo.js index d89a00d3b2b9..a985d1044640 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hanunoo.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hanunoo.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Hanunoo` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hatran.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hatran.js index 285884da7f89..7a128439cf2f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hatran.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hatran.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Hatran` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hebrew.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hebrew.js index d5b965708674..ef65903ed2fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hebrew.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hebrew.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Hebrew` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hiragana.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hiragana.js index deca5f2c8861..aba164afa432 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hiragana.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hiragana.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Hiragana` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -31,7 +31,7 @@ const matchSymbols = buildString({ [0x00FE45, 0x00FE46], [0x00FF61, 0x00FF65], [0x00FF9E, 0x00FF9F], - [0x01B001, 0x01B11E], + [0x01B001, 0x01B11F], [0x01B150, 0x01B152] ] }); @@ -76,7 +76,7 @@ const nonMatchSymbols = buildString({ [0x00FF66, 0x00FF6F], [0x00FF71, 0x00FF9D], [0x00FFA0, 0x01B000], - [0x01B11F, 0x01B14F], + [0x01B120, 0x01B14F], [0x01B153, 0x01F1FF], [0x01F201, 0x10FFFF] ] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Imperial_Aramaic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Imperial_Aramaic.js index d4e901fbf947..52c7e5f22bdd 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Imperial_Aramaic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Imperial_Aramaic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Imperial_Aramaic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inherited.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inherited.js index 4bd64b43a768..b3a1ddce1f1d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inherited.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inherited.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Inherited` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -23,13 +23,15 @@ const matchSymbols = buildString({ [0x000343, 0x000344], [0x000346, 0x000362], [0x000953, 0x000954], - [0x001AB0, 0x001AC0], + [0x001AB0, 0x001ACE], [0x001DC2, 0x001DF7], [0x001DFB, 0x001DFF], [0x00200C, 0x00200D], [0x0020D0, 0x0020EF], [0x00FE00, 0x00FE0F], [0x00FE20, 0x00FE2D], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D167, 0x01D169], [0x01D17B, 0x01D182], [0x01D185, 0x01D18B], @@ -80,14 +82,16 @@ const nonMatchSymbols = buildString({ [0x000000, 0x0002FF], [0x000363, 0x000952], [0x000955, 0x001AAF], - [0x001AC1, 0x001DC1], + [0x001ACF, 0x001DC1], [0x001E00, 0x00200B], [0x00200E, 0x0020CF], [0x0020F0, 0x00DBFF], [0x00E000, 0x00FDFF], [0x00FE10, 0x00FE1F], [0x00FE2E, 0x0101FC], - [0x0101FE, 0x01D166], + [0x0101FE, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D166], [0x01D16A, 0x01D17A], [0x01D183, 0x01D184], [0x01D18C, 0x01D1A9], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inscriptional_Pahlavi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inscriptional_Pahlavi.js index bb79ec357121..cc731f308dd2 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inscriptional_Pahlavi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inscriptional_Pahlavi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Inscriptional_Pahlavi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inscriptional_Parthian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inscriptional_Parthian.js index 87ea02a188c5..82a8c1b50b90 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inscriptional_Parthian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inscriptional_Parthian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Inscriptional_Parthian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Javanese.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Javanese.js index 0325360c9a0a..d33c4b117229 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Javanese.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Javanese.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Javanese` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kaithi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kaithi.js index 6ed47e4b70ac..f105adcaaab8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kaithi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kaithi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Kaithi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -20,7 +20,7 @@ const matchSymbols = buildString({ ranges: [ [0x000966, 0x00096F], [0x00A830, 0x00A839], - [0x011080, 0x0110C1] + [0x011080, 0x0110C2] ] }); testPropertyEscapes( @@ -52,7 +52,7 @@ const nonMatchSymbols = buildString({ [0x000970, 0x00A82F], [0x00A83A, 0x00DBFF], [0x00E000, 0x01107F], - [0x0110C2, 0x0110CC], + [0x0110C3, 0x0110CC], [0x0110CE, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kannada.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kannada.js index 8088bd05f5ba..8b1c2160a9fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kannada.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kannada.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Kannada` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -15,7 +15,6 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [ - 0x000CDE, 0x001CD0, 0x001CD2, 0x001CDA, @@ -34,6 +33,7 @@ const matchSymbols = buildString({ [0x000CC6, 0x000CC8], [0x000CCA, 0x000CCD], [0x000CD5, 0x000CD6], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE3], [0x000CE6, 0x000CEF], [0x000CF1, 0x000CF2], @@ -81,7 +81,7 @@ const nonMatchSymbols = buildString({ [0x000966, 0x000C7F], [0x000CBA, 0x000CBB], [0x000CCE, 0x000CD4], - [0x000CD7, 0x000CDD], + [0x000CD7, 0x000CDC], [0x000CE4, 0x000CE5], [0x000CF3, 0x001CCF], [0x001CD3, 0x001CD9], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Katakana.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Katakana.js index 591116531b9b..505eb4d1b3da 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Katakana.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Katakana.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Katakana` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -31,6 +31,10 @@ const matchSymbols = buildString({ [0x003300, 0x003357], [0x00FE45, 0x00FE46], [0x00FF61, 0x00FF9F], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B120, 0x01B122], [0x01B164, 0x01B167] ] }); @@ -59,7 +63,10 @@ const nonMatchSymbols = buildString({ loneCodePoints: [ 0x003012, 0x003036, - 0x0032FF + 0x0032FF, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF ], ranges: [ [0x00DC00, 0x00DFFF], @@ -74,8 +81,9 @@ const nonMatchSymbols = buildString({ [0x003358, 0x00DBFF], [0x00E000, 0x00FE44], [0x00FE47, 0x00FF60], - [0x00FFA0, 0x01AFFF], - [0x01B001, 0x01B163], + [0x00FFA0, 0x01AFEF], + [0x01B001, 0x01B11F], + [0x01B123, 0x01B163], [0x01B168, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kayah_Li.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kayah_Li.js index db6cb5aa4e42..105f1cb0c874 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kayah_Li.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kayah_Li.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Kayah_Li` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kharoshthi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kharoshthi.js index de70cde2bcbb..2c65ab3ffc6f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kharoshthi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kharoshthi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Kharoshthi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khitan_Small_Script.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khitan_Small_Script.js index 5a2ebfcc30bf..e96c47216520 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khitan_Small_Script.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khitan_Small_Script.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Khitan_Small_Script` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khmer.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khmer.js index 64c4e98b2309..d30b4c10b6f7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khmer.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khmer.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Khmer` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khojki.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khojki.js index 4b5a87598bc2..874519e97590 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khojki.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khojki.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Khojki` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khudawadi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khudawadi.js index b200453b1124..29eba477c475 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khudawadi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Khudawadi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Khudawadi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lao.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lao.js index 7f38c1f7fa5c..8496ae1fd164 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lao.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lao.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Lao` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Latin.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Latin.js index 9c0bd2e1c9f7..9e5b0eef25ee 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Latin.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Latin.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Latin` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -24,6 +24,7 @@ const matchSymbols = buildString({ 0x0020F0, 0x002132, 0x00214E, + 0x00A7D3, 0x00A92E ], ranges: [ @@ -48,15 +49,20 @@ const matchSymbols = buildString({ [0x002C60, 0x002C7F], [0x00A700, 0x00A707], [0x00A722, 0x00A787], - [0x00A78B, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A7FF], + [0x00A78B, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A7FF], [0x00AB30, 0x00AB5A], [0x00AB5C, 0x00AB64], [0x00AB66, 0x00AB69], [0x00FB00, 0x00FB06], [0x00FF21, 0x00FF3A], - [0x00FF41, 0x00FF5A] + [0x00FF41, 0x00FF5A], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], + [0x01DF00, 0x01DF1E] ] }); testPropertyEscapes( @@ -85,8 +91,12 @@ const nonMatchSymbols = buildString({ 0x0000D7, 0x0000F7, 0x001D78, + 0x00A7D2, + 0x00A7D4, 0x00AB5B, - 0x00AB65 + 0x00AB65, + 0x010786, + 0x0107B1 ], ranges: [ [0x00DC00, 0x00DFFF], @@ -118,15 +128,17 @@ const nonMatchSymbols = buildString({ [0x002C80, 0x00A6FF], [0x00A708, 0x00A721], [0x00A788, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A800, 0x00A92D], [0x00A92F, 0x00AB2F], [0x00AB6A, 0x00DBFF], [0x00E000, 0x00FAFF], [0x00FB07, 0x00FF20], [0x00FF3B, 0x00FF40], - [0x00FF5B, 0x10FFFF] + [0x00FF5B, 0x01077F], + [0x0107BB, 0x01DEFF], + [0x01DF1F, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lepcha.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lepcha.js index 284659214a96..a23fa8c18adf 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lepcha.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lepcha.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Lepcha` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Limbu.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Limbu.js index 4509fb07d614..751ecd960d8e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Limbu.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Limbu.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Limbu` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Linear_A.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Linear_A.js index bc1914c62c2c..7fd16736c24b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Linear_A.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Linear_A.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Linear_A` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Linear_B.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Linear_B.js index 922057c7b588..8b865ff62f8f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Linear_B.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Linear_B.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Linear_B` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lisu.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lisu.js index c3b34dd0f499..2860cb2456f4 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lisu.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lisu.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Lisu` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lycian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lycian.js index 9838d6d645e1..d4ca1c12b537 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lycian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lycian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Lycian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lydian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lydian.js index 9a5226e24926..8bc8dfc75fa6 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lydian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Lydian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Lydian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mahajani.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mahajani.js index c92c2a41a5c5..720c0144bc5a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mahajani.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mahajani.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Mahajani` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Makasar.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Makasar.js index 55acc125fefb..8aad6d0fa0fc 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Makasar.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Makasar.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Makasar` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Malayalam.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Malayalam.js index 4458c56c85e7..4f01233c14bb 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Malayalam.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Malayalam.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Malayalam` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mandaic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mandaic.js index dec6256671f3..775f0896c023 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mandaic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mandaic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Mandaic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Manichaean.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Manichaean.js index 7eff2d0f1128..bd8d5ff0f906 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Manichaean.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Manichaean.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Manichaean` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Marchen.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Marchen.js index 0c8ea0838130..6ac49cd65999 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Marchen.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Marchen.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Marchen` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Masaram_Gondi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Masaram_Gondi.js index f76a4403a177..b1198c5c631a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Masaram_Gondi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Masaram_Gondi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Masaram_Gondi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Medefaidrin.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Medefaidrin.js index 1b5cead30fbd..88a241beabad 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Medefaidrin.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Medefaidrin.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Medefaidrin` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meetei_Mayek.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meetei_Mayek.js index 3a528a220193..9e6f2373cc8b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meetei_Mayek.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meetei_Mayek.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Meetei_Mayek` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mende_Kikakui.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mende_Kikakui.js index 1fbf8b09035a..b563ded22de3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mende_Kikakui.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mende_Kikakui.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Mende_Kikakui` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meroitic_Cursive.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meroitic_Cursive.js index 1ce1f87223a9..c4c2c9c3e2ba 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meroitic_Cursive.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meroitic_Cursive.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Meroitic_Cursive` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meroitic_Hieroglyphs.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meroitic_Hieroglyphs.js index f8aa14d326c9..4a20250f4a70 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meroitic_Hieroglyphs.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Meroitic_Hieroglyphs.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Meroitic_Hieroglyphs` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Miao.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Miao.js index e04a0efe6bb3..21fb642b69b7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Miao.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Miao.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Miao` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Modi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Modi.js index 25a17a8aa8e6..1ec53498748e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Modi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Modi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Modi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mongolian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mongolian.js index 40a5fa0db4cf..3e046a287acb 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mongolian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mongolian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Mongolian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -18,8 +18,7 @@ const matchSymbols = buildString({ 0x00202F ], ranges: [ - [0x001800, 0x00180E], - [0x001810, 0x001819], + [0x001800, 0x001819], [0x001820, 0x001878], [0x001880, 0x0018AA], [0x011660, 0x01166C] @@ -47,9 +46,7 @@ testPropertyEscapes( ); const nonMatchSymbols = buildString({ - loneCodePoints: [ - 0x00180F - ], + loneCodePoints: [], ranges: [ [0x00DC00, 0x00DFFF], [0x000000, 0x0017FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mro.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mro.js index 88ee33669a35..536f033f93a4 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mro.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mro.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Mro` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Multani.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Multani.js index 2a04de7c5d0f..23dc042e4c45 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Multani.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Multani.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Multani` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Myanmar.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Myanmar.js index 605e7ff95a97..4face6bdb137 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Myanmar.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Myanmar.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Myanmar` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nabataean.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nabataean.js index 732279e43996..68f180dfe59d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nabataean.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nabataean.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Nabataean` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nandinagari.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nandinagari.js index 8ce415d3c4a3..e31b45669b25 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nandinagari.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nandinagari.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Nandinagari` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_New_Tai_Lue.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_New_Tai_Lue.js index 157094969e05..c4eb8a8c2f74 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_New_Tai_Lue.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_New_Tai_Lue.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=New_Tai_Lue` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Newa.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Newa.js index 6298afe766a3..8e16736ad46f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Newa.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Newa.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Newa` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nko.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nko.js index 4c714c9585ed..867521eebd07 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nko.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nko.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,17 +7,22 @@ description: > Unicode property escapes for `Script_Extensions=Nko` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] ---*/ const matchSymbols = buildString({ - loneCodePoints: [], + loneCodePoints: [ + 0x00060C, + 0x00061B, + 0x00061F + ], ranges: [ [0x0007C0, 0x0007FA], - [0x0007FD, 0x0007FF] + [0x0007FD, 0x0007FF], + [0x00FD3E, 0x00FD3F] ] }); testPropertyEscapes( @@ -45,10 +50,14 @@ const nonMatchSymbols = buildString({ loneCodePoints: [], ranges: [ [0x00DC00, 0x00DFFF], - [0x000000, 0x0007BF], + [0x000000, 0x00060B], + [0x00060D, 0x00061A], + [0x00061C, 0x00061E], + [0x000620, 0x0007BF], [0x0007FB, 0x0007FC], [0x000800, 0x00DBFF], - [0x00E000, 0x10FFFF] + [0x00E000, 0x00FD3D], + [0x00FD40, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nushu.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nushu.js index ac616433c256..5d688c4e3cea 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nushu.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nushu.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Nushu` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nyiakeng_Puachue_Hmong.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nyiakeng_Puachue_Hmong.js index 68a15272ce9e..cc856551bc2f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nyiakeng_Puachue_Hmong.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nyiakeng_Puachue_Hmong.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Nyiakeng_Puachue_Hmong` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ogham.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ogham.js index 88dc975a57ab..cb7f2f702407 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ogham.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ogham.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Ogham` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ol_Chiki.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ol_Chiki.js index e09320d48be9..b52fc00ba242 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ol_Chiki.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ol_Chiki.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Ol_Chiki` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Hungarian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Hungarian.js index f739b0f35cd9..8a90d0ad505b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Hungarian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Hungarian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Old_Hungarian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Italic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Italic.js index 21daff9906b8..4cb57d39b850 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Italic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Italic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Old_Italic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_North_Arabian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_North_Arabian.js index c6bb0ab77e5d..5c57cdef1b6f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_North_Arabian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_North_Arabian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Old_North_Arabian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Permic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Permic.js index 031329af4ce4..680826b8e7a3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Permic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Permic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Old_Permic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Persian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Persian.js index c3fe60586707..957c1d81df0d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Persian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Persian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Old_Persian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Sogdian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Sogdian.js index 03cc401bc27b..a8f83fbbf142 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Sogdian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Sogdian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Old_Sogdian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_South_Arabian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_South_Arabian.js index b9b4ac4e81cf..0f08690ca1ec 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_South_Arabian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_South_Arabian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Old_South_Arabian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Turkic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Turkic.js index e139582fef0f..9a1c090984e7 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Turkic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Turkic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Old_Turkic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Uyghur.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Uyghur.js new file mode 100644 index 000000000000..52f6cfb9df6e --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Old_Uyghur.js @@ -0,0 +1,78 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script_Extensions=Old_Uyghur` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [ + 0x000640, + 0x010AF2 + ], + ranges: [ + [0x010F70, 0x010F89] + ] +}); +testPropertyEscapes( + /^\p{Script_Extensions=Old_Uyghur}+$/u, + matchSymbols, + "\\p{Script_Extensions=Old_Uyghur}" +); +testPropertyEscapes( + /^\p{Script_Extensions=Ougr}+$/u, + matchSymbols, + "\\p{Script_Extensions=Ougr}" +); +testPropertyEscapes( + /^\p{scx=Old_Uyghur}+$/u, + matchSymbols, + "\\p{scx=Old_Uyghur}" +); +testPropertyEscapes( + /^\p{scx=Ougr}+$/u, + matchSymbols, + "\\p{scx=Ougr}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00063F], + [0x000641, 0x00DBFF], + [0x00E000, 0x010AF1], + [0x010AF3, 0x010F6F], + [0x010F8A, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script_Extensions=Old_Uyghur}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Old_Uyghur}" +); +testPropertyEscapes( + /^\P{Script_Extensions=Ougr}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Ougr}" +); +testPropertyEscapes( + /^\P{scx=Old_Uyghur}+$/u, + nonMatchSymbols, + "\\P{scx=Old_Uyghur}" +); +testPropertyEscapes( + /^\P{scx=Ougr}+$/u, + nonMatchSymbols, + "\\P{scx=Ougr}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Oriya.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Oriya.js index 25d964c01070..3b6a18541a76 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Oriya.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Oriya.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Oriya` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Osage.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Osage.js index 10ca7a2f6073..a5736e5cef2c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Osage.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Osage.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Osage` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Osmanya.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Osmanya.js index 575f884fa196..96c6e8f93fcf 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Osmanya.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Osmanya.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Osmanya` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Pahawh_Hmong.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Pahawh_Hmong.js index 45eb4f4a6119..bc2820ae4452 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Pahawh_Hmong.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Pahawh_Hmong.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Pahawh_Hmong` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Palmyrene.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Palmyrene.js index 0a77f46de6cf..a618ed4c731e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Palmyrene.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Palmyrene.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Palmyrene` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Pau_Cin_Hau.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Pau_Cin_Hau.js index 1c12f45e28a0..8692cb8f43de 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Pau_Cin_Hau.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Pau_Cin_Hau.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Pau_Cin_Hau` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Phags_Pa.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Phags_Pa.js index 138468144b96..353eaba9d9d3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Phags_Pa.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Phags_Pa.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Phags_Pa` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Phoenician.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Phoenician.js index 4a22acfa5062..3251f59d1f68 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Phoenician.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Phoenician.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Phoenician` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Psalter_Pahlavi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Psalter_Pahlavi.js index 53dade8ba333..2a94e21c0545 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Psalter_Pahlavi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Psalter_Pahlavi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Psalter_Pahlavi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Rejang.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Rejang.js index c7924c31a763..914b05d3458a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Rejang.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Rejang.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Rejang` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Runic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Runic.js index 4979521e3cff..40240dbe74f8 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Runic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Runic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Runic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Samaritan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Samaritan.js index b95ed2deff16..560549086cfe 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Samaritan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Samaritan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Samaritan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Saurashtra.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Saurashtra.js index 89ae6a56c8fc..e5258941116c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Saurashtra.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Saurashtra.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Saurashtra` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sharada.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sharada.js index 8ad6bc9da0ff..c5ffbb100f9f 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sharada.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sharada.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Sharada` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Shavian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Shavian.js index 09b9181e3875..eb2443c29091 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Shavian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Shavian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Shavian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Siddham.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Siddham.js index 74297ac1891d..34e713323d5e 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Siddham.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Siddham.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Siddham` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_SignWriting.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_SignWriting.js index 8b26452fa8fc..fd3f9fbf30be 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_SignWriting.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_SignWriting.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=SignWriting` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sinhala.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sinhala.js index 90dc13c0e1b7..7ea3dcf3ab70 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sinhala.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sinhala.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Sinhala` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sogdian.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sogdian.js index bac638bcad05..e13b9aded062 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sogdian.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sogdian.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Sogdian` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sora_Sompeng.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sora_Sompeng.js index df95e89c437c..da6957665c68 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sora_Sompeng.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sora_Sompeng.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Sora_Sompeng` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Soyombo.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Soyombo.js index 9fa516703670..e9c15c58eca0 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Soyombo.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Soyombo.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Soyombo` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sundanese.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sundanese.js index 011bd301acb8..db79667e31ee 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sundanese.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Sundanese.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Sundanese` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syloti_Nagri.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syloti_Nagri.js index 1173bc04fe1d..4c9aa03e5435 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syloti_Nagri.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syloti_Nagri.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Syloti_Nagri` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syriac.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syriac.js index 97e2bf84397e..2cecd5e488ca 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syriac.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syriac.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Syriac` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -19,7 +19,8 @@ const matchSymbols = buildString({ 0x00061F, 0x000640, 0x000670, - 0x001DF8 + 0x001DF8, + 0x001DFA ], ranges: [ [0x00061B, 0x00061C], @@ -53,7 +54,8 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ - 0x00070E + 0x00070E, + 0x001DF9 ], ranges: [ [0x00DC00, 0x00DFFF], @@ -67,7 +69,7 @@ const nonMatchSymbols = buildString({ [0x00074B, 0x00074C], [0x000750, 0x00085F], [0x00086B, 0x001DF7], - [0x001DF9, 0x00DBFF], + [0x001DFB, 0x00DBFF], [0x00E000, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagalog.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagalog.js index 8a72ece38e6c..ddcacb00f587 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagalog.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagalog.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,17 +7,18 @@ description: > Unicode property escapes for `Script_Extensions=Tagalog` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] ---*/ const matchSymbols = buildString({ - loneCodePoints: [], + loneCodePoints: [ + 0x00171F + ], ranges: [ - [0x001700, 0x00170C], - [0x00170E, 0x001714], + [0x001700, 0x001715], [0x001735, 0x001736] ] }); @@ -43,13 +44,12 @@ testPropertyEscapes( ); const nonMatchSymbols = buildString({ - loneCodePoints: [ - 0x00170D - ], + loneCodePoints: [], ranges: [ [0x00DC00, 0x00DFFF], [0x000000, 0x0016FF], - [0x001715, 0x001734], + [0x001716, 0x00171E], + [0x001720, 0x001734], [0x001737, 0x00DBFF], [0x00E000, 0x10FFFF] ] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagbanwa.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagbanwa.js index da2932b8e267..76f410368027 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagbanwa.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagbanwa.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tagbanwa` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Le.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Le.js index 211b621d3038..33c1519e8ebb 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Le.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Le.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tai_Le` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Tham.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Tham.js index 05677b45142e..5232f9ce7d58 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Tham.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Tham.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tai_Tham` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Viet.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Viet.js index a102d6d38e8a..7a3d0f68b783 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Viet.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tai_Viet.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tai_Viet` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Takri.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Takri.js index 701cea27e78f..3ac977db9ceb 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Takri.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Takri.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Takri` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -18,7 +18,7 @@ const matchSymbols = buildString({ ranges: [ [0x000964, 0x000965], [0x00A830, 0x00A839], - [0x011680, 0x0116B8], + [0x011680, 0x0116B9], [0x0116C0, 0x0116C9] ] }); @@ -51,7 +51,7 @@ const nonMatchSymbols = buildString({ [0x000966, 0x00A82F], [0x00A83A, 0x00DBFF], [0x00E000, 0x01167F], - [0x0116B9, 0x0116BF], + [0x0116BA, 0x0116BF], [0x0116CA, 0x10FFFF] ] }); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tamil.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tamil.js index d1a7023a3a99..d130cf3a1d57 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tamil.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tamil.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tamil` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tangsa.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tangsa.js new file mode 100644 index 000000000000..d2efb93e9d4f --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tangsa.js @@ -0,0 +1,76 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script_Extensions=Tangsa` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x016A70, 0x016ABE], + [0x016AC0, 0x016AC9] + ] +}); +testPropertyEscapes( + /^\p{Script_Extensions=Tangsa}+$/u, + matchSymbols, + "\\p{Script_Extensions=Tangsa}" +); +testPropertyEscapes( + /^\p{Script_Extensions=Tnsa}+$/u, + matchSymbols, + "\\p{Script_Extensions=Tnsa}" +); +testPropertyEscapes( + /^\p{scx=Tangsa}+$/u, + matchSymbols, + "\\p{scx=Tangsa}" +); +testPropertyEscapes( + /^\p{scx=Tnsa}+$/u, + matchSymbols, + "\\p{scx=Tnsa}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [ + 0x016ABF + ], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x016A6F], + [0x016ACA, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script_Extensions=Tangsa}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Tangsa}" +); +testPropertyEscapes( + /^\P{Script_Extensions=Tnsa}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Tnsa}" +); +testPropertyEscapes( + /^\P{scx=Tangsa}+$/u, + nonMatchSymbols, + "\\P{scx=Tangsa}" +); +testPropertyEscapes( + /^\P{scx=Tnsa}+$/u, + nonMatchSymbols, + "\\P{scx=Tnsa}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tangut.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tangut.js index b75c0923360f..b4d91d37a679 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tangut.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tangut.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tangut` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Telugu.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Telugu.js index f3c1988a960f..1e205c2adfa1 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Telugu.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Telugu.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Telugu` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -15,6 +15,7 @@ includes: [regExpUtils.js] const matchSymbols = buildString({ loneCodePoints: [ + 0x000C5D, 0x001CDA, 0x001CF2 ], @@ -25,7 +26,7 @@ const matchSymbols = buildString({ [0x000C0E, 0x000C10], [0x000C12, 0x000C28], [0x000C2A, 0x000C39], - [0x000C3D, 0x000C44], + [0x000C3C, 0x000C44], [0x000C46, 0x000C48], [0x000C4A, 0x000C4D], [0x000C55, 0x000C56], @@ -70,9 +71,10 @@ const nonMatchSymbols = buildString({ [0x000000, 0x000950], [0x000953, 0x000963], [0x000966, 0x000BFF], - [0x000C3A, 0x000C3C], + [0x000C3A, 0x000C3B], [0x000C4E, 0x000C54], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C64, 0x000C65], [0x000C70, 0x000C76], [0x000C80, 0x001CD9], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Thaana.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Thaana.js index ad5f03e67d19..a01a70717002 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Thaana.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Thaana.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Thaana` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Thai.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Thai.js index b7acba181fbf..5d9adcfc384a 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Thai.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Thai.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Thai` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tibetan.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tibetan.js index 8eadc68206ac..d379d04e5ea0 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tibetan.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tibetan.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tibetan` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tifinagh.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tifinagh.js index 8c03e0b088f1..0b5616ef21c6 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tifinagh.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tifinagh.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tifinagh` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tirhuta.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tirhuta.js index 712a8f5d4c05..833f862dc0d3 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tirhuta.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tirhuta.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Tirhuta` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Toto.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Toto.js new file mode 100644 index 000000000000..45e8ec746dc9 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Toto.js @@ -0,0 +1,73 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script_Extensions=Toto` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x01E290, 0x01E2AE] + ] +}); +testPropertyEscapes( + /^\p{Script_Extensions=Toto}+$/u, + matchSymbols, + "\\p{Script_Extensions=Toto}" +); +testPropertyEscapes( + /^\p{Script_Extensions=Toto}+$/u, + matchSymbols, + "\\p{Script_Extensions=Toto}" +); +testPropertyEscapes( + /^\p{scx=Toto}+$/u, + matchSymbols, + "\\p{scx=Toto}" +); +testPropertyEscapes( + /^\p{scx=Toto}+$/u, + matchSymbols, + "\\p{scx=Toto}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x01E28F], + [0x01E2AF, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script_Extensions=Toto}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Toto}" +); +testPropertyEscapes( + /^\P{Script_Extensions=Toto}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Toto}" +); +testPropertyEscapes( + /^\P{scx=Toto}+$/u, + nonMatchSymbols, + "\\P{scx=Toto}" +); +testPropertyEscapes( + /^\P{scx=Toto}+$/u, + nonMatchSymbols, + "\\P{scx=Toto}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ugaritic.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ugaritic.js index e806a496d6f1..6a8668e74532 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ugaritic.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ugaritic.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Ugaritic` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Vai.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Vai.js index 6e29d0aff6e8..8140d2b5d339 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Vai.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Vai.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Vai` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Vithkuqi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Vithkuqi.js new file mode 100644 index 000000000000..010851001ccf --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Vithkuqi.js @@ -0,0 +1,88 @@ +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Script_Extensions=Vithkuqi` +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes] +includes: [regExpUtils.js] +---*/ + +const matchSymbols = buildString({ + loneCodePoints: [], + ranges: [ + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC] + ] +}); +testPropertyEscapes( + /^\p{Script_Extensions=Vithkuqi}+$/u, + matchSymbols, + "\\p{Script_Extensions=Vithkuqi}" +); +testPropertyEscapes( + /^\p{Script_Extensions=Vith}+$/u, + matchSymbols, + "\\p{Script_Extensions=Vith}" +); +testPropertyEscapes( + /^\p{scx=Vithkuqi}+$/u, + matchSymbols, + "\\p{scx=Vithkuqi}" +); +testPropertyEscapes( + /^\p{scx=Vith}+$/u, + matchSymbols, + "\\p{scx=Vith}" +); + +const nonMatchSymbols = buildString({ + loneCodePoints: [ + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA + ], + ranges: [ + [0x00DC00, 0x00DFFF], + [0x000000, 0x00DBFF], + [0x00E000, 0x01056F], + [0x0105BD, 0x10FFFF] + ] +}); +testPropertyEscapes( + /^\P{Script_Extensions=Vithkuqi}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Vithkuqi}" +); +testPropertyEscapes( + /^\P{Script_Extensions=Vith}+$/u, + nonMatchSymbols, + "\\P{Script_Extensions=Vith}" +); +testPropertyEscapes( + /^\P{scx=Vithkuqi}+$/u, + nonMatchSymbols, + "\\P{scx=Vithkuqi}" +); +testPropertyEscapes( + /^\P{scx=Vith}+$/u, + nonMatchSymbols, + "\\P{scx=Vith}" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Wancho.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Wancho.js index 0da28f375c6e..3e77f84c77a0 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Wancho.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Wancho.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Wancho` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Warang_Citi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Warang_Citi.js index 810273f88241..35acc27d53d4 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Warang_Citi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Warang_Citi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Warang_Citi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Yezidi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Yezidi.js index 48a7b3b5f09e..c60222b0c52d 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Yezidi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Yezidi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Yezidi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Yi.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Yi.js index a8bcf9fbb692..2c30e1ebd7d5 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Yi.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Yi.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Yi` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Zanabazar_Square.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Zanabazar_Square.js index 872ed50d45c9..55039d7c5410 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Zanabazar_Square.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Zanabazar_Square.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Script_Extensions=Zanabazar_Square` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Sentence_Terminal.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Sentence_Terminal.js index 587b912b1b4f..8ea7e65901df 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Sentence_Terminal.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Sentence_Terminal.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Sentence_Terminal` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -51,7 +51,7 @@ const matchSymbols = buildString({ 0x01DA88 ], ranges: [ - [0x00061E, 0x00061F], + [0x00061D, 0x00061F], [0x000700, 0x000702], [0x00083D, 0x00083E], [0x000964, 0x000965], @@ -62,10 +62,12 @@ const matchSymbols = buildString({ [0x001AA8, 0x001AAB], [0x001B5A, 0x001B5B], [0x001B5E, 0x001B5F], + [0x001B7D, 0x001B7E], [0x001C3B, 0x001C3C], [0x001C7E, 0x001C7F], [0x00203C, 0x00203D], [0x002047, 0x002049], + [0x002E53, 0x002E54], [0x00A60E, 0x00A60F], [0x00A876, 0x00A877], [0x00A8CE, 0x00A8CF], @@ -75,6 +77,7 @@ const matchSymbols = buildString({ [0x00FE56, 0x00FE57], [0x010A56, 0x010A57], [0x010F55, 0x010F59], + [0x010F86, 0x010F89], [0x011047, 0x011048], [0x0110BE, 0x0110C1], [0x011141, 0x011143], @@ -118,7 +121,7 @@ const nonMatchSymbols = buildString({ [0x000022, 0x00002D], [0x00002F, 0x00003E], [0x000040, 0x000588], - [0x00058A, 0x00061D], + [0x00058A, 0x00061C], [0x000620, 0x0006D3], [0x0006D5, 0x0006FF], [0x000703, 0x0007F8], @@ -136,13 +139,15 @@ const nonMatchSymbols = buildString({ [0x001946, 0x001AA7], [0x001AAC, 0x001B59], [0x001B5C, 0x001B5D], - [0x001B60, 0x001C3A], + [0x001B60, 0x001B7C], + [0x001B7F, 0x001C3A], [0x001C3D, 0x001C7D], [0x001C80, 0x00203B], [0x00203E, 0x002046], [0x00204A, 0x002E2D], [0x002E2F, 0x002E3B], - [0x002E3D, 0x003001], + [0x002E3D, 0x002E52], + [0x002E55, 0x003001], [0x003003, 0x00A4FE], [0x00A500, 0x00A60D], [0x00A610, 0x00A6F2], @@ -163,7 +168,8 @@ const nonMatchSymbols = buildString({ [0x00FF20, 0x00FF60], [0x00FF62, 0x010A55], [0x010A58, 0x010F54], - [0x010F5A, 0x011046], + [0x010F5A, 0x010F85], + [0x010F8A, 0x011046], [0x011049, 0x0110BD], [0x0110C2, 0x011140], [0x011144, 0x0111C4], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Soft_Dotted.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Soft_Dotted.js index 5b862fe5dd28..fc4854c3ed04 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Soft_Dotted.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Soft_Dotted.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Soft_Dotted` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -30,7 +30,8 @@ const matchSymbols = buildString({ 0x001E2D, 0x001ECB, 0x002071, - 0x002C7C + 0x002C7C, + 0x01DF1A ], ranges: [ [0x000069, 0x00006A], @@ -98,7 +99,8 @@ const nonMatchSymbols = buildString({ [0x01D5F8, 0x01D629], [0x01D62C, 0x01D65D], [0x01D660, 0x01D691], - [0x01D694, 0x10FFFF] + [0x01D694, 0x01DF19], + [0x01DF1B, 0x10FFFF] ] }); testPropertyEscapes( diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Terminal_Punctuation.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Terminal_Punctuation.js index 7211e2779581..16c3dac90d51 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Terminal_Punctuation.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Terminal_Punctuation.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Terminal_Punctuation` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -59,7 +59,7 @@ const matchSymbols = buildString({ ], ranges: [ [0x00003A, 0x00003B], - [0x00061E, 0x00061F], + [0x00061D, 0x00061F], [0x000700, 0x00070A], [0x0007F8, 0x0007F9], [0x000830, 0x00083E], @@ -77,11 +77,13 @@ const matchSymbols = buildString({ [0x001AA8, 0x001AAB], [0x001B5A, 0x001B5B], [0x001B5D, 0x001B5F], + [0x001B7D, 0x001B7E], [0x001C3B, 0x001C3F], [0x001C7E, 0x001C7F], [0x00203C, 0x00203D], [0x002047, 0x002049], [0x002E4E, 0x002E4F], + [0x002E53, 0x002E54], [0x003001, 0x003002], [0x00A4FE, 0x00A4FF], [0x00A60D, 0x00A60F], @@ -99,6 +101,7 @@ const matchSymbols = buildString({ [0x010B3A, 0x010B3F], [0x010B99, 0x010B9C], [0x010F55, 0x010F59], + [0x010F86, 0x010F89], [0x011047, 0x01104D], [0x0110BE, 0x0110C1], [0x011141, 0x011143], @@ -137,6 +140,7 @@ testPropertyEscapes( const nonMatchSymbols = buildString({ loneCodePoints: [ 0x00002D, + 0x00061C, 0x00070B, 0x001B5C, 0x002E4D, @@ -156,7 +160,6 @@ const nonMatchSymbols = buildString({ [0x00058A, 0x0005C2], [0x0005C4, 0x00060B], [0x00060D, 0x00061A], - [0x00061C, 0x00061D], [0x000620, 0x0006D3], [0x0006D5, 0x0006FF], [0x00070D, 0x0007F7], @@ -178,7 +181,8 @@ const nonMatchSymbols = buildString({ [0x00180A, 0x001943], [0x001946, 0x001AA7], [0x001AAC, 0x001B59], - [0x001B60, 0x001C3A], + [0x001B60, 0x001B7C], + [0x001B7F, 0x001C3A], [0x001C40, 0x001C7D], [0x001C80, 0x00203B], [0x00203E, 0x002046], @@ -186,7 +190,8 @@ const nonMatchSymbols = buildString({ [0x002E2F, 0x002E3B], [0x002E3D, 0x002E40], [0x002E42, 0x002E4B], - [0x002E50, 0x003000], + [0x002E50, 0x002E52], + [0x002E55, 0x003000], [0x003003, 0x00A4FD], [0x00A500, 0x00A60C], [0x00A610, 0x00A6F2], @@ -215,7 +220,8 @@ const nonMatchSymbols = buildString({ [0x010AF6, 0x010B39], [0x010B40, 0x010B98], [0x010B9D, 0x010F54], - [0x010F5A, 0x011046], + [0x010F5A, 0x010F85], + [0x010F8A, 0x011046], [0x01104E, 0x0110BD], [0x0110C2, 0x011140], [0x011144, 0x0111C4], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Unified_Ideograph.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Unified_Ideograph.js index 6f1193788d71..109638efd670 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Unified_Ideograph.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Unified_Ideograph.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Unified_Ideograph` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -21,13 +21,13 @@ const matchSymbols = buildString({ ], ranges: [ [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], + [0x004E00, 0x009FFF], [0x00FA0E, 0x00FA0F], [0x00FA13, 0x00FA14], [0x00FA23, 0x00FA24], [0x00FA27, 0x00FA29], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -56,13 +56,13 @@ const nonMatchSymbols = buildString({ [0x00DC00, 0x00DFFF], [0x000000, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x00DBFF], + [0x00A000, 0x00DBFF], [0x00E000, 0x00FA0D], [0x00FA15, 0x00FA1E], [0x00FA25, 0x00FA26], [0x00FA2A, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02FFFF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Uppercase.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Uppercase.js index ed182161c022..9925b2bee252 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Uppercase.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Uppercase.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `Uppercase` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -554,8 +554,12 @@ const matchSymbols = buildString({ 0x00A7BA, 0x00A7BC, 0x00A7BE, + 0x00A7C0, 0x00A7C2, 0x00A7C9, + 0x00A7D0, + 0x00A7D6, + 0x00A7D8, 0x00A7F5, 0x01D49C, 0x01D4A2, @@ -615,7 +619,7 @@ const matchSymbols = buildString({ [0x00213E, 0x00213F], [0x002160, 0x00216F], [0x0024B6, 0x0024CF], - [0x002C00, 0x002C2E], + [0x002C00, 0x002C2F], [0x002C62, 0x002C64], [0x002C6D, 0x002C70], [0x002C7E, 0x002C80], @@ -626,6 +630,10 @@ const matchSymbols = buildString({ [0x00FF21, 0x00FF3A], [0x010400, 0x010427], [0x0104B0, 0x0104D3], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], [0x010C80, 0x010CB2], [0x0118A0, 0x0118BF], [0x016E40, 0x016E5F], @@ -1193,8 +1201,14 @@ const nonMatchSymbols = buildString({ 0x00A7B9, 0x00A7BB, 0x00A7BD, + 0x00A7BF, + 0x00A7C1, 0x00A7C3, 0x00A7C8, + 0x00A7D7, + 0x01057B, + 0x01058B, + 0x010593, 0x01D49D, 0x01D4AD, 0x01D506, @@ -1271,7 +1285,7 @@ const nonMatchSymbols = buildString({ [0x002170, 0x002182], [0x002184, 0x0024B5], [0x0024D0, 0x002BFF], - [0x002C2F, 0x002C5F], + [0x002C30, 0x002C5F], [0x002C65, 0x002C66], [0x002C73, 0x002C74], [0x002C76, 0x002C7D], @@ -1285,13 +1299,15 @@ const nonMatchSymbols = buildString({ [0x00A787, 0x00A78A], [0x00A78E, 0x00A78F], [0x00A793, 0x00A795], - [0x00A7BF, 0x00A7C1], - [0x00A7CA, 0x00A7F4], + [0x00A7CA, 0x00A7CF], + [0x00A7D1, 0x00A7D5], + [0x00A7D9, 0x00A7F4], [0x00A7F6, 0x00DBFF], [0x00E000, 0x00FF20], [0x00FF3B, 0x0103FF], [0x010428, 0x0104AF], - [0x0104D4, 0x010C7F], + [0x0104D4, 0x01056F], + [0x010596, 0x010C7F], [0x010CB3, 0x01189F], [0x0118C0, 0x016E3F], [0x016E60, 0x01D3FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Variation_Selector.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Variation_Selector.js index 90f8ae63c4e5..5f931ee93087 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Variation_Selector.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Variation_Selector.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,14 +7,16 @@ description: > Unicode property escapes for `Variation_Selector` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] ---*/ const matchSymbols = buildString({ - loneCodePoints: [], + loneCodePoints: [ + 0x00180F + ], ranges: [ [0x00180B, 0x00180D], [0x00FE00, 0x00FE0F], @@ -33,11 +35,13 @@ testPropertyEscapes( ); const nonMatchSymbols = buildString({ - loneCodePoints: [], + loneCodePoints: [ + 0x00180E + ], ranges: [ [0x00DC00, 0x00DFFF], [0x000000, 0x00180A], - [0x00180E, 0x00DBFF], + [0x001810, 0x00DBFF], [0x00E000, 0x00FDFF], [0x00FE10, 0x0E00FF], [0x0E01F0, 0x10FFFF] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/White_Space.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/White_Space.js index c7e819cf1fdf..da4412d0c66c 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/White_Space.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/White_Space.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `White_Space` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/XID_Continue.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/XID_Continue.js index 3d09981cf809..f00003ecb69b 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/XID_Continue.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/XID_Continue.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `XID_Continue` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -42,7 +42,7 @@ const matchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000BD7, - 0x000CDE, + 0x000C5D, 0x000DBD, 0x000DCA, 0x000DD6, @@ -78,6 +78,7 @@ const matchSymbols = buildString({ 0x002D27, 0x002D2D, 0x002D6F, + 0x00A7D3, 0x00A82C, 0x00A8FB, 0x00FB3E, @@ -94,6 +95,7 @@ const matchSymbols = buildString({ 0x01083C, 0x010A3F, 0x010F27, + 0x0110C2, 0x011176, 0x0111DC, 0x01123E, @@ -167,9 +169,9 @@ const matchSymbols = buildString({ [0x000800, 0x00082D], [0x000840, 0x00085B], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], - [0x0008D3, 0x0008E1], + [0x000870, 0x000887], + [0x000889, 0x00088E], + [0x000898, 0x0008E1], [0x0008E3, 0x000963], [0x000966, 0x00096F], [0x000971, 0x000983], @@ -241,7 +243,7 @@ const matchSymbols = buildString({ [0x000C0E, 0x000C10], [0x000C12, 0x000C28], [0x000C2A, 0x000C39], - [0x000C3D, 0x000C44], + [0x000C3C, 0x000C44], [0x000C46, 0x000C48], [0x000C4A, 0x000C4D], [0x000C55, 0x000C56], @@ -258,6 +260,7 @@ const matchSymbols = buildString({ [0x000CC6, 0x000CC8], [0x000CCA, 0x000CCD], [0x000CD5, 0x000CD6], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE3], [0x000CE6, 0x000CEF], [0x000CF1, 0x000CF2], @@ -325,9 +328,8 @@ const matchSymbols = buildString({ [0x001681, 0x00169A], [0x0016A0, 0x0016EA], [0x0016EE, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001714], - [0x001720, 0x001734], + [0x001700, 0x001715], + [0x00171F, 0x001734], [0x001740, 0x001753], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -336,7 +338,7 @@ const matchSymbols = buildString({ [0x0017DC, 0x0017DD], [0x0017E0, 0x0017E9], [0x00180B, 0x00180D], - [0x001810, 0x001819], + [0x00180F, 0x001819], [0x001820, 0x001878], [0x001880, 0x0018AA], [0x0018B0, 0x0018F5], @@ -354,8 +356,8 @@ const matchSymbols = buildString({ [0x001A7F, 0x001A89], [0x001A90, 0x001A99], [0x001AB0, 0x001ABD], - [0x001ABF, 0x001AC0], - [0x001B00, 0x001B4B], + [0x001ABF, 0x001ACE], + [0x001B00, 0x001B4C], [0x001B50, 0x001B59], [0x001B6B, 0x001B73], [0x001B80, 0x001BF3], @@ -367,8 +369,7 @@ const matchSymbols = buildString({ [0x001CBD, 0x001CBF], [0x001CD0, 0x001CD2], [0x001CD4, 0x001CFA], - [0x001D00, 0x001DF9], - [0x001DFB, 0x001F15], + [0x001D00, 0x001F15], [0x001F18, 0x001F1D], [0x001F20, 0x001F45], [0x001F48, 0x001F4D], @@ -393,9 +394,7 @@ const matchSymbols = buildString({ [0x00213C, 0x00213F], [0x002145, 0x002149], [0x002160, 0x002188], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CE4], + [0x002C00, 0x002CE4], [0x002CEB, 0x002CF3], [0x002D00, 0x002D25], [0x002D30, 0x002D67], @@ -423,8 +422,7 @@ const matchSymbols = buildString({ [0x0031A0, 0x0031BF], [0x0031F0, 0x0031FF], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], - [0x00A000, 0x00A48C], + [0x004E00, 0x00A48C], [0x00A4D0, 0x00A4FD], [0x00A500, 0x00A60C], [0x00A610, 0x00A62B], @@ -433,9 +431,10 @@ const matchSymbols = buildString({ [0x00A67F, 0x00A6F1], [0x00A717, 0x00A71F], [0x00A722, 0x00A788], - [0x00A78B, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A827], + [0x00A78B, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A827], [0x00A840, 0x00A873], [0x00A880, 0x00A8C5], [0x00A8D0, 0x00A8D9], @@ -518,9 +517,20 @@ const matchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -557,10 +567,11 @@ const matchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F1C], [0x010F30, 0x010F50], + [0x010F70, 0x010F85], [0x010FB0, 0x010FC4], [0x010FE0, 0x010FF6], [0x011000, 0x011046], - [0x011066, 0x01106F], + [0x011066, 0x011075], [0x01107F, 0x0110BA], [0x0110D0, 0x0110E8], [0x0110F0, 0x0110F9], @@ -607,6 +618,7 @@ const matchSymbols = buildString({ [0x011700, 0x01171A], [0x01171D, 0x01172B], [0x011730, 0x011739], + [0x011740, 0x011746], [0x011800, 0x01183A], [0x0118A0, 0x0118E9], [0x0118FF, 0x011906], @@ -622,7 +634,7 @@ const matchSymbols = buildString({ [0x0119E3, 0x0119E4], [0x011A00, 0x011A3E], [0x011A50, 0x011A99], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C36], [0x011C38, 0x011C40], @@ -646,11 +658,14 @@ const matchSymbols = buildString({ [0x012000, 0x012399], [0x012400, 0x01246E], [0x012480, 0x012543], + [0x012F90, 0x012FF0], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], [0x016A60, 0x016A69], + [0x016A70, 0x016ABE], + [0x016AC0, 0x016AC9], [0x016AD0, 0x016AED], [0x016AF0, 0x016AF4], [0x016B00, 0x016B36], @@ -668,7 +683,10 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -677,6 +695,8 @@ const matchSymbols = buildString({ [0x01BC80, 0x01BC88], [0x01BC90, 0x01BC99], [0x01BC9D, 0x01BC9E], + [0x01CF00, 0x01CF2D], + [0x01CF30, 0x01CF46], [0x01D165, 0x01D169], [0x01D16D, 0x01D172], [0x01D17B, 0x01D182], @@ -715,6 +735,7 @@ const matchSymbols = buildString({ [0x01DA3B, 0x01DA6C], [0x01DA9B, 0x01DA9F], [0x01DAA1, 0x01DAAF], + [0x01DF00, 0x01DF1E], [0x01E000, 0x01E006], [0x01E008, 0x01E018], [0x01E01B, 0x01E021], @@ -723,7 +744,12 @@ const matchSymbols = buildString({ [0x01E100, 0x01E12C], [0x01E130, 0x01E13D], [0x01E140, 0x01E149], + [0x01E290, 0x01E2AE], [0x01E2C0, 0x01E2F9], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E8D0, 0x01E8D6], [0x01E900, 0x01E94B], @@ -746,8 +772,8 @@ const matchSymbols = buildString({ [0x01EEA5, 0x01EEA9], [0x01EEAB, 0x01EEBB], [0x01FBF0, 0x01FBF9], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -788,7 +814,7 @@ const nonMatchSymbols = buildString({ 0x0005C6, 0x0006D4, 0x0006E9, - 0x0008B5, + 0x000888, 0x0008E2, 0x000970, 0x000984, @@ -873,14 +899,13 @@ const nonMatchSymbols = buildString({ 0x0012D7, 0x001311, 0x001680, - 0x00170D, 0x00176D, 0x001771, + 0x00180E, 0x00191F, 0x001A5F, 0x001ABE, 0x001CD3, - 0x001DFA, 0x001F58, 0x001F5A, 0x001F5C, @@ -893,8 +918,6 @@ const nonMatchSymbols = buildString({ 0x002125, 0x002127, 0x002129, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -909,6 +932,8 @@ const nonMatchSymbols = buildString({ 0x0030FB, 0x003130, 0x00A67E, + 0x00A7D2, + 0x00A7D4, 0x00A8FC, 0x00A9FF, 0x00AB27, @@ -932,6 +957,15 @@ const nonMatchSymbols = buildString({ 0x01003B, 0x01003E, 0x0103D0, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x0108F3, @@ -970,7 +1004,11 @@ const nonMatchSymbols = buildString({ 0x011D8F, 0x011D92, 0x016A5F, + 0x016ABF, 0x016FE2, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -998,6 +1036,10 @@ const nonMatchSymbols = buildString({ 0x01E007, 0x01E022, 0x01E025, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -1059,8 +1101,8 @@ const nonMatchSymbols = buildString({ [0x0007FE, 0x0007FF], [0x00082E, 0x00083F], [0x00085C, 0x00085F], - [0x00086B, 0x00089F], - [0x0008C8, 0x0008D2], + [0x00086B, 0x00086F], + [0x00088F, 0x000897], [0x000964, 0x000965], [0x00098D, 0x00098E], [0x000991, 0x000992], @@ -1107,14 +1149,15 @@ const nonMatchSymbols = buildString({ [0x000BD1, 0x000BD6], [0x000BD8, 0x000BE5], [0x000BF0, 0x000BFF], - [0x000C3A, 0x000C3C], + [0x000C3A, 0x000C3B], [0x000C4E, 0x000C54], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C64, 0x000C65], [0x000C70, 0x000C7F], [0x000CBA, 0x000CBB], [0x000CCE, 0x000CD4], - [0x000CD7, 0x000CDD], + [0x000CD7, 0x000CDC], [0x000CE4, 0x000CE5], [0x000CF3, 0x000CFF], [0x000D4F, 0x000D53], @@ -1161,7 +1204,7 @@ const nonMatchSymbols = buildString({ [0x00169B, 0x00169F], [0x0016EB, 0x0016ED], [0x0016F9, 0x0016FF], - [0x001715, 0x00171F], + [0x001716, 0x00171E], [0x001735, 0x00173F], [0x001754, 0x00175F], [0x001774, 0x00177F], @@ -1169,7 +1212,6 @@ const nonMatchSymbols = buildString({ [0x0017D8, 0x0017DB], [0x0017DE, 0x0017DF], [0x0017EA, 0x00180A], - [0x00180E, 0x00180F], [0x00181A, 0x00181F], [0x001879, 0x00187F], [0x0018AB, 0x0018AF], @@ -1186,8 +1228,8 @@ const nonMatchSymbols = buildString({ [0x001A8A, 0x001A8F], [0x001A9A, 0x001AA6], [0x001AA8, 0x001AAF], - [0x001AC1, 0x001AFF], - [0x001B4C, 0x001B4F], + [0x001ACF, 0x001AFF], + [0x001B4D, 0x001B4F], [0x001B5A, 0x001B6A], [0x001B74, 0x001B7F], [0x001BF4, 0x001BFF], @@ -1244,7 +1286,6 @@ const nonMatchSymbols = buildString({ [0x0031C0, 0x0031EF], [0x003200, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A4CF], [0x00A4FE, 0x00A4FF], [0x00A60D, 0x00A60F], @@ -1253,8 +1294,8 @@ const nonMatchSymbols = buildString({ [0x00A6F2, 0x00A716], [0x00A720, 0x00A721], [0x00A789, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A828, 0x00A82B], [0x00A82D, 0x00A83F], [0x00A874, 0x00A87F], @@ -1327,10 +1368,12 @@ const nonMatchSymbols = buildString({ [0x0104D4, 0x0104D7], [0x0104FC, 0x0104FF], [0x010528, 0x01052F], - [0x010564, 0x0105FF], + [0x010564, 0x01056F], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -1362,12 +1405,14 @@ const nonMatchSymbols = buildString({ [0x010EB2, 0x010EFF], [0x010F1D, 0x010F26], [0x010F28, 0x010F2F], - [0x010F51, 0x010FAF], + [0x010F51, 0x010F6F], + [0x010F86, 0x010FAF], [0x010FC5, 0x010FDF], [0x010FF7, 0x010FFF], [0x011047, 0x011065], - [0x011070, 0x01107E], - [0x0110BB, 0x0110CF], + [0x011076, 0x01107E], + [0x0110BB, 0x0110C1], + [0x0110C3, 0x0110CF], [0x0110E9, 0x0110EF], [0x0110FA, 0x0110FF], [0x011140, 0x011143], @@ -1406,7 +1451,8 @@ const nonMatchSymbols = buildString({ [0x0116CA, 0x0116FF], [0x01171B, 0x01171C], [0x01172C, 0x01172F], - [0x01173A, 0x0117FF], + [0x01173A, 0x01173F], + [0x011747, 0x0117FF], [0x01183B, 0x01189F], [0x0118EA, 0x0118FE], [0x011907, 0x011908], @@ -1420,7 +1466,7 @@ const nonMatchSymbols = buildString({ [0x011A3F, 0x011A46], [0x011A48, 0x011A4F], [0x011A9A, 0x011A9C], - [0x011A9E, 0x011ABF], + [0x011A9E, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C41, 0x011C4F], [0x011C5A, 0x011C71], @@ -1435,11 +1481,13 @@ const nonMatchSymbols = buildString({ [0x011FB1, 0x011FFF], [0x01239A, 0x0123FF], [0x01246F, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF1, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], - [0x016A6A, 0x016ACF], + [0x016A6A, 0x016A6F], + [0x016ACA, 0x016ACF], [0x016AEE, 0x016AEF], [0x016AF5, 0x016AFF], [0x016B37, 0x016B3F], @@ -1455,8 +1503,8 @@ const nonMatchSymbols = buildString({ [0x016FF2, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -1464,7 +1512,9 @@ const nonMatchSymbols = buildString({ [0x01BC7D, 0x01BC7F], [0x01BC89, 0x01BC8F], [0x01BC9A, 0x01BC9C], - [0x01BC9F, 0x01D164], + [0x01BC9F, 0x01CEFF], + [0x01CF2E, 0x01CF2F], + [0x01CF47, 0x01D164], [0x01D16A, 0x01D16C], [0x01D173, 0x01D17A], [0x01D183, 0x01D184], @@ -1483,14 +1533,16 @@ const nonMatchSymbols = buildString({ [0x01DA6D, 0x01DA74], [0x01DA76, 0x01DA83], [0x01DA85, 0x01DA9A], - [0x01DAB0, 0x01DFFF], + [0x01DAB0, 0x01DEFF], + [0x01DF1F, 0x01DFFF], [0x01E019, 0x01E01A], [0x01E02B, 0x01E0FF], [0x01E12D, 0x01E12F], [0x01E13E, 0x01E13F], [0x01E14A, 0x01E14D], - [0x01E14F, 0x01E2BF], - [0x01E2FA, 0x01E7FF], + [0x01E14F, 0x01E28F], + [0x01E2AF, 0x01E2BF], + [0x01E2FA, 0x01E7DF], [0x01E8C5, 0x01E8CF], [0x01E8D7, 0x01E8FF], [0x01E94C, 0x01E94F], @@ -1503,8 +1555,8 @@ const nonMatchSymbols = buildString({ [0x01EE9C, 0x01EEA0], [0x01EEBC, 0x01FBEF], [0x01FBFA, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/XID_Start.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/XID_Start.js index c2b14834d246..c4fb47151acc 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/XID_Start.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/XID_Start.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2021 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -7,7 +7,7 @@ description: > Unicode property escapes for `XID_Start` info: | Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests - Unicode v13.0.0 + Unicode v14.0.0 esid: sec-static-semantics-unicodematchproperty-p features: [regexp-unicode-property-escapes] includes: [regExpUtils.js] @@ -48,9 +48,9 @@ const matchSymbols = buildString({ 0x000B9C, 0x000BD0, 0x000C3D, + 0x000C5D, 0x000C80, 0x000CBD, - 0x000CDE, 0x000D3D, 0x000D4E, 0x000DBD, @@ -89,6 +89,7 @@ const matchSymbols = buildString({ 0x002D27, 0x002D2D, 0x002D6F, + 0x00A7D3, 0x00A8FB, 0x00A9CF, 0x00AA7A, @@ -107,6 +108,7 @@ const matchSymbols = buildString({ 0x01083C, 0x010A00, 0x010F27, + 0x011075, 0x011144, 0x011147, 0x011176, @@ -188,8 +190,9 @@ const matchSymbols = buildString({ [0x000800, 0x000815], [0x000840, 0x000858], [0x000860, 0x00086A], - [0x0008A0, 0x0008B4], - [0x0008B6, 0x0008C7], + [0x000870, 0x000887], + [0x000889, 0x00088E], + [0x0008A0, 0x0008C9], [0x000904, 0x000939], [0x000958, 0x000961], [0x000971, 0x000980], @@ -244,6 +247,7 @@ const matchSymbols = buildString({ [0x000C92, 0x000CA8], [0x000CAA, 0x000CB3], [0x000CB5, 0x000CB9], + [0x000CDD, 0x000CDE], [0x000CE0, 0x000CE1], [0x000CF1, 0x000CF2], [0x000D04, 0x000D0C], @@ -297,9 +301,8 @@ const matchSymbols = buildString({ [0x001681, 0x00169A], [0x0016A0, 0x0016EA], [0x0016EE, 0x0016F8], - [0x001700, 0x00170C], - [0x00170E, 0x001711], - [0x001720, 0x001731], + [0x001700, 0x001711], + [0x00171F, 0x001731], [0x001740, 0x001751], [0x001760, 0x00176C], [0x00176E, 0x001770], @@ -315,7 +318,7 @@ const matchSymbols = buildString({ [0x001A00, 0x001A16], [0x001A20, 0x001A54], [0x001B05, 0x001B33], - [0x001B45, 0x001B4B], + [0x001B45, 0x001B4C], [0x001B83, 0x001BA0], [0x001BAE, 0x001BAF], [0x001BBA, 0x001BE5], @@ -351,9 +354,7 @@ const matchSymbols = buildString({ [0x00213C, 0x00213F], [0x002145, 0x002149], [0x002160, 0x002188], - [0x002C00, 0x002C2E], - [0x002C30, 0x002C5E], - [0x002C60, 0x002CE4], + [0x002C00, 0x002CE4], [0x002CEB, 0x002CEE], [0x002CF2, 0x002CF3], [0x002D00, 0x002D25], @@ -380,8 +381,7 @@ const matchSymbols = buildString({ [0x0031A0, 0x0031BF], [0x0031F0, 0x0031FF], [0x003400, 0x004DBF], - [0x004E00, 0x009FFC], - [0x00A000, 0x00A48C], + [0x004E00, 0x00A48C], [0x00A4D0, 0x00A4FD], [0x00A500, 0x00A60C], [0x00A610, 0x00A61F], @@ -391,9 +391,10 @@ const matchSymbols = buildString({ [0x00A6A0, 0x00A6EF], [0x00A717, 0x00A71F], [0x00A722, 0x00A788], - [0x00A78B, 0x00A7BF], - [0x00A7C2, 0x00A7CA], - [0x00A7F5, 0x00A801], + [0x00A78B, 0x00A7CA], + [0x00A7D0, 0x00A7D1], + [0x00A7D5, 0x00A7D9], + [0x00A7F2, 0x00A801], [0x00A803, 0x00A805], [0x00A807, 0x00A80A], [0x00A80C, 0x00A822], @@ -475,9 +476,20 @@ const matchSymbols = buildString({ [0x0104D8, 0x0104FB], [0x010500, 0x010527], [0x010530, 0x010563], + [0x010570, 0x01057A], + [0x01057C, 0x01058A], + [0x01058C, 0x010592], + [0x010594, 0x010595], + [0x010597, 0x0105A1], + [0x0105A3, 0x0105B1], + [0x0105B3, 0x0105B9], + [0x0105BB, 0x0105BC], [0x010600, 0x010736], [0x010740, 0x010755], [0x010760, 0x010767], + [0x010780, 0x010785], + [0x010787, 0x0107B0], + [0x0107B2, 0x0107BA], [0x010800, 0x010805], [0x01080A, 0x010835], [0x010837, 0x010838], @@ -509,9 +521,11 @@ const matchSymbols = buildString({ [0x010EB0, 0x010EB1], [0x010F00, 0x010F1C], [0x010F30, 0x010F45], + [0x010F70, 0x010F81], [0x010FB0, 0x010FC4], [0x010FE0, 0x010FF6], [0x011003, 0x011037], + [0x011071, 0x011072], [0x011083, 0x0110AF], [0x0110D0, 0x0110E8], [0x011103, 0x011126], @@ -542,6 +556,7 @@ const matchSymbols = buildString({ [0x011600, 0x01162F], [0x011680, 0x0116AA], [0x011700, 0x01171A], + [0x011740, 0x011746], [0x011800, 0x01182B], [0x0118A0, 0x0118DF], [0x0118FF, 0x011906], @@ -552,7 +567,7 @@ const matchSymbols = buildString({ [0x0119AA, 0x0119D0], [0x011A0B, 0x011A32], [0x011A5C, 0x011A89], - [0x011AC0, 0x011AF8], + [0x011AB0, 0x011AF8], [0x011C00, 0x011C08], [0x011C0A, 0x011C2E], [0x011C72, 0x011C8F], @@ -566,10 +581,12 @@ const matchSymbols = buildString({ [0x012000, 0x012399], [0x012400, 0x01246E], [0x012480, 0x012543], + [0x012F90, 0x012FF0], [0x013000, 0x01342E], [0x014400, 0x014646], [0x016800, 0x016A38], [0x016A40, 0x016A5E], + [0x016A70, 0x016ABE], [0x016AD0, 0x016AED], [0x016B00, 0x016B2F], [0x016B40, 0x016B43], @@ -582,7 +599,10 @@ const matchSymbols = buildString({ [0x017000, 0x0187F7], [0x018800, 0x018CD5], [0x018D00, 0x018D08], - [0x01B000, 0x01B11E], + [0x01AFF0, 0x01AFF3], + [0x01AFF5, 0x01AFFB], + [0x01AFFD, 0x01AFFE], + [0x01B000, 0x01B122], [0x01B150, 0x01B152], [0x01B164, 0x01B167], [0x01B170, 0x01B2FB], @@ -617,9 +637,15 @@ const matchSymbols = buildString({ [0x01D78A, 0x01D7A8], [0x01D7AA, 0x01D7C2], [0x01D7C4, 0x01D7CB], + [0x01DF00, 0x01DF1E], [0x01E100, 0x01E12C], [0x01E137, 0x01E13D], + [0x01E290, 0x01E2AD], [0x01E2C0, 0x01E2EB], + [0x01E7E0, 0x01E7E6], + [0x01E7E8, 0x01E7EB], + [0x01E7ED, 0x01E7EE], + [0x01E7F0, 0x01E7FE], [0x01E800, 0x01E8C4], [0x01E900, 0x01E943], [0x01EE00, 0x01EE03], @@ -639,8 +665,8 @@ const matchSymbols = buildString({ [0x01EEA1, 0x01EEA3], [0x01EEA5, 0x01EEA9], [0x01EEAB, 0x01EEBB], - [0x020000, 0x02A6DD], - [0x02A700, 0x02B734], + [0x020000, 0x02A6DF], + [0x02A700, 0x02B738], [0x02B740, 0x02B81D], [0x02B820, 0x02CEA1], [0x02CEB0, 0x02EBE0], @@ -675,7 +701,7 @@ const nonMatchSymbols = buildString({ 0x000670, 0x0006D4, 0x000711, - 0x0008B5, + 0x000888, 0x0009A9, 0x0009B1, 0x0009DE, @@ -730,7 +756,6 @@ const nonMatchSymbols = buildString({ 0x0012D7, 0x001311, 0x001680, - 0x00170D, 0x00176D, 0x0018A9, 0x001CED, @@ -747,8 +772,6 @@ const nonMatchSymbols = buildString({ 0x002125, 0x002127, 0x002129, - 0x002C2F, - 0x002C5F, 0x002D26, 0x002DA7, 0x002DAF, @@ -760,6 +783,8 @@ const nonMatchSymbols = buildString({ 0x0030A0, 0x0030FB, 0x003130, + 0x00A7D2, + 0x00A7D4, 0x00A802, 0x00A806, 0x00A80B, @@ -789,6 +814,15 @@ const nonMatchSymbols = buildString({ 0x01003B, 0x01003E, 0x0103D0, + 0x01057B, + 0x01058B, + 0x010593, + 0x010596, + 0x0105A2, + 0x0105B2, + 0x0105BA, + 0x010786, + 0x0107B1, 0x010809, 0x010836, 0x0108F3, @@ -815,6 +849,9 @@ const nonMatchSymbols = buildString({ 0x011D66, 0x011D69, 0x016FE2, + 0x01AFF4, + 0x01AFFC, + 0x01AFFF, 0x01D455, 0x01D49D, 0x01D4AD, @@ -838,6 +875,10 @@ const nonMatchSymbols = buildString({ 0x01D789, 0x01D7A9, 0x01D7C3, + 0x01E7E7, + 0x01E7EC, + 0x01E7EF, + 0x01E7FF, 0x01EE04, 0x01EE20, 0x01EE23, @@ -902,8 +943,9 @@ const nonMatchSymbols = buildString({ [0x000825, 0x000827], [0x000829, 0x00083F], [0x000859, 0x00085F], - [0x00086B, 0x00089F], - [0x0008C8, 0x000903], + [0x00086B, 0x00086F], + [0x00088F, 0x00089F], + [0x0008CA, 0x000903], [0x00093A, 0x00093C], [0x00093E, 0x00094F], [0x000951, 0x000957], @@ -943,11 +985,12 @@ const nonMatchSymbols = buildString({ [0x000BD1, 0x000C04], [0x000C3A, 0x000C3C], [0x000C3E, 0x000C57], - [0x000C5B, 0x000C5F], + [0x000C5B, 0x000C5C], + [0x000C5E, 0x000C5F], [0x000C62, 0x000C7F], [0x000C81, 0x000C84], [0x000CBA, 0x000CBC], - [0x000CBE, 0x000CDD], + [0x000CBE, 0x000CDC], [0x000CE2, 0x000CF0], [0x000CF3, 0x000D03], [0x000D3B, 0x000D3C], @@ -993,7 +1036,7 @@ const nonMatchSymbols = buildString({ [0x00169B, 0x00169F], [0x0016EB, 0x0016ED], [0x0016F9, 0x0016FF], - [0x001712, 0x00171F], + [0x001712, 0x00171E], [0x001732, 0x00173F], [0x001752, 0x00175F], [0x001771, 0x00177F], @@ -1012,7 +1055,7 @@ const nonMatchSymbols = buildString({ [0x001A55, 0x001AA6], [0x001AA8, 0x001B04], [0x001B34, 0x001B44], - [0x001B4C, 0x001B82], + [0x001B4D, 0x001B82], [0x001BA1, 0x001BAD], [0x001BB0, 0x001BB9], [0x001BE6, 0x001BFF], @@ -1067,7 +1110,6 @@ const nonMatchSymbols = buildString({ [0x0031C0, 0x0031EF], [0x003200, 0x0033FF], [0x004DC0, 0x004DFF], - [0x009FFD, 0x009FFF], [0x00A48D, 0x00A4CF], [0x00A4FE, 0x00A4FF], [0x00A60D, 0x00A60F], @@ -1078,8 +1120,8 @@ const nonMatchSymbols = buildString({ [0x00A6F0, 0x00A716], [0x00A720, 0x00A721], [0x00A789, 0x00A78A], - [0x00A7C0, 0x00A7C1], - [0x00A7CB, 0x00A7F4], + [0x00A7CB, 0x00A7CF], + [0x00A7DA, 0x00A7F1], [0x00A823, 0x00A83F], [0x00A874, 0x00A881], [0x00A8B4, 0x00A8F1], @@ -1147,10 +1189,12 @@ const nonMatchSymbols = buildString({ [0x0104D4, 0x0104D7], [0x0104FC, 0x0104FF], [0x010528, 0x01052F], - [0x010564, 0x0105FF], + [0x010564, 0x01056F], + [0x0105BD, 0x0105FF], [0x010737, 0x01073F], [0x010756, 0x01075F], - [0x010768, 0x0107FF], + [0x010768, 0x01077F], + [0x0107BB, 0x0107FF], [0x010806, 0x010807], [0x010839, 0x01083B], [0x01083D, 0x01083E], @@ -1179,10 +1223,13 @@ const nonMatchSymbols = buildString({ [0x010EB2, 0x010EFF], [0x010F1D, 0x010F26], [0x010F28, 0x010F2F], - [0x010F46, 0x010FAF], + [0x010F46, 0x010F6F], + [0x010F82, 0x010FAF], [0x010FC5, 0x010FDF], [0x010FF7, 0x011002], - [0x011038, 0x011082], + [0x011038, 0x011070], + [0x011073, 0x011074], + [0x011076, 0x011082], [0x0110B0, 0x0110CF], [0x0110E9, 0x011102], [0x011127, 0x011143], @@ -1213,7 +1260,8 @@ const nonMatchSymbols = buildString({ [0x011645, 0x01167F], [0x0116AB, 0x0116B7], [0x0116B9, 0x0116FF], - [0x01171B, 0x0117FF], + [0x01171B, 0x01173F], + [0x011747, 0x0117FF], [0x01182C, 0x01189F], [0x0118E0, 0x0118FE], [0x011907, 0x011908], @@ -1228,7 +1276,7 @@ const nonMatchSymbols = buildString({ [0x011A3B, 0x011A4F], [0x011A51, 0x011A5B], [0x011A8A, 0x011A9C], - [0x011A9E, 0x011ABF], + [0x011A9E, 0x011AAF], [0x011AF9, 0x011BFF], [0x011C2F, 0x011C3F], [0x011C41, 0x011C71], @@ -1241,11 +1289,13 @@ const nonMatchSymbols = buildString({ [0x011FB1, 0x011FFF], [0x01239A, 0x0123FF], [0x01246F, 0x01247F], - [0x012544, 0x012FFF], + [0x012544, 0x012F8F], + [0x012FF1, 0x012FFF], [0x01342F, 0x0143FF], [0x014647, 0x0167FF], [0x016A39, 0x016A3F], - [0x016A5F, 0x016ACF], + [0x016A5F, 0x016A6F], + [0x016ABF, 0x016ACF], [0x016AEE, 0x016AFF], [0x016B30, 0x016B3F], [0x016B44, 0x016B62], @@ -1258,8 +1308,8 @@ const nonMatchSymbols = buildString({ [0x016FE4, 0x016FFF], [0x0187F8, 0x0187FF], [0x018CD6, 0x018CFF], - [0x018D09, 0x01AFFF], - [0x01B11F, 0x01B14F], + [0x018D09, 0x01AFEF], + [0x01B123, 0x01B14F], [0x01B153, 0x01B163], [0x01B168, 0x01B16F], [0x01B2FC, 0x01BBFF], @@ -1273,11 +1323,13 @@ const nonMatchSymbols = buildString({ [0x01D50B, 0x01D50C], [0x01D547, 0x01D549], [0x01D6A6, 0x01D6A7], - [0x01D7CC, 0x01E0FF], + [0x01D7CC, 0x01DEFF], + [0x01DF1F, 0x01E0FF], [0x01E12D, 0x01E136], [0x01E13E, 0x01E14D], - [0x01E14F, 0x01E2BF], - [0x01E2EC, 0x01E7FF], + [0x01E14F, 0x01E28F], + [0x01E2AE, 0x01E2BF], + [0x01E2EC, 0x01E7DF], [0x01E8C5, 0x01E8FF], [0x01E944, 0x01E94A], [0x01E94C, 0x01EDFF], @@ -1288,8 +1340,8 @@ const nonMatchSymbols = buildString({ [0x01EE65, 0x01EE66], [0x01EE9C, 0x01EEA0], [0x01EEBC, 0x01FFFF], - [0x02A6DE, 0x02A6FF], - [0x02B735, 0x02B73F], + [0x02A6E0, 0x02A6FF], + [0x02B739, 0x02B73F], [0x02B81E, 0x02B81F], [0x02CEA2, 0x02CEAF], [0x02EBE1, 0x02F7FF], diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/shell.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/shell.js index b21e5a8be535..1c0f4dad1409 100644 --- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/shell.js +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/shell.js @@ -5,7 +5,7 @@ /*--- description: | Collection of functions used to assert the correctness of RegExp objects. -defines: [buildString, testPropertyEscapes, matchValidator] +defines: [buildString, testPropertyEscapes, testPropertyOfStrings, matchValidator] ---*/ function buildString(args) { @@ -33,23 +33,65 @@ function buildString(args) { return result; } -function testPropertyEscapes(regex, string, expression) { - if (!regex.test(string)) { +function printCodePoint(codePoint) { + const hex = codePoint + .toString(16) + .toUpperCase() + .padStart(6, "0"); + return `U+${hex}`; +} + +function printStringCodePoints(string) { + const buf = []; + for (const symbol of string) { + const formatted = printCodePoint(symbol.codePointAt(0)); + buf.push(formatted); + } + return buf.join(' '); +} + +function testPropertyEscapes(regExp, string, expression) { + if (!regExp.test(string)) { for (const symbol of string) { - const hex = symbol - .codePointAt(0) - .toString(16) - .toUpperCase() - .padStart(6, "0"); + printCodePoint(symbol.codePointAt(0)); assert( - regex.test(symbol), + regExp.test(symbol), `\`${ expression }\` should match U+${ hex } (\`${ symbol }\`)` ); } } } -// Returns a function that will validate RegExp match result +function testPropertyOfStrings(args) { + // Use member expressions rather than destructuring `args` for improved + // compatibility with engines that only implement assignment patterns + // partially or not at all. + const regExp = args.regExp; + const expression = args.expression; + const matchStrings = args.matchStrings; + const nonMatchStrings = args.nonMatchStrings; + const allStrings = matchStrings.join(''); + if (!regExp.test(allStrings)) { + for (const string of matchStrings) { + assert( + regExp.test(string), + `\`${ expression }\` should match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } + + const allNonMatchStrings = nonMatchStrings.join(''); + if (regExp.test(allNonMatchStrings)) { + for (const string of nonMatchStrings) { + assert( + !regExp.test(string), + `\`${ expression }\` should not match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } +} + +// Returns a function that validates a RegExp match result. // // Example: // diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-CharacterClass.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-CharacterClass.js new file mode 100644 index 000000000000..a4ef02d08a4e --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-CharacterClass.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `Basic_Emoji` (property of strings) with `[^\p{…}]` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/[^\p{Basic_Emoji}]/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-P.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-P.js new file mode 100644 index 000000000000..51b59a04d6a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-P.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `Basic_Emoji` (property of strings) with `\P{…}` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\P{Basic_Emoji}/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-u.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-u.js new file mode 100644 index 000000000000..b1b54eaeef8a --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-u.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Basic_Emoji` (property of strings) with the `u` flag throws an early error. Properties of strings are only supported through the `v` flag. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-patterns-static-semantics-early-errors +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\p{Basic_Emoji}/u; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji.js new file mode 100644 index 000000000000..b60ff8828986 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji.js @@ -0,0 +1,1402 @@ +// |reftest| skip -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Basic_Emoji` (property of strings) +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes, regexp-v-flag] +includes: [regExpUtils.js] +---*/ + +testPropertyOfStrings({ + regExp: /^\p{Basic_Emoji}+$/v, + expression: "\\p{Basic_Emoji}", + matchStrings: [ + "\u231A", + "\u231B", + "\u23E9", + "\u23EA", + "\u23EB", + "\u23EC", + "\u23F0", + "\u23F3", + "\u25FD", + "\u25FE", + "\u2614", + "\u2615", + "\u2648", + "\u2649", + "\u264A", + "\u264B", + "\u264C", + "\u264D", + "\u264E", + "\u264F", + "\u2650", + "\u2651", + "\u2652", + "\u2653", + "\u267F", + "\u2693", + "\u26A1", + "\u26AA", + "\u26AB", + "\u26BD", + "\u26BE", + "\u26C4", + "\u26C5", + "\u26CE", + "\u26D4", + "\u26EA", + "\u26F2", + "\u26F3", + "\u26F5", + "\u26FA", + "\u26FD", + "\u2705", + "\u270A", + "\u270B", + "\u2728", + "\u274C", + "\u274E", + "\u2753", + "\u2754", + "\u2755", + "\u2757", + "\u2795", + "\u2796", + "\u2797", + "\u27B0", + "\u27BF", + "\u2B1B", + "\u2B1C", + "\u2B50", + "\u2B55", + "\u{1F004}", + "\u{1F0CF}", + "\u{1F18E}", + "\u{1F191}", + "\u{1F192}", + "\u{1F193}", + "\u{1F194}", + "\u{1F195}", + "\u{1F196}", + "\u{1F197}", + "\u{1F198}", + "\u{1F199}", + "\u{1F19A}", + "\u{1F201}", + "\u{1F21A}", + "\u{1F22F}", + "\u{1F232}", + "\u{1F233}", + "\u{1F234}", + "\u{1F235}", + "\u{1F236}", + "\u{1F238}", + "\u{1F239}", + "\u{1F23A}", + "\u{1F250}", + "\u{1F251}", + "\u{1F300}", + "\u{1F301}", + "\u{1F302}", + "\u{1F303}", + "\u{1F304}", + "\u{1F305}", + "\u{1F306}", + "\u{1F307}", + "\u{1F308}", + "\u{1F309}", + "\u{1F30A}", + "\u{1F30B}", + "\u{1F30C}", + "\u{1F30D}", + "\u{1F30E}", + "\u{1F30F}", + "\u{1F310}", + "\u{1F311}", + "\u{1F312}", + "\u{1F313}", + "\u{1F314}", + "\u{1F315}", + "\u{1F316}", + "\u{1F317}", + "\u{1F318}", + "\u{1F319}", + "\u{1F31A}", + "\u{1F31B}", + "\u{1F31C}", + "\u{1F31D}", + "\u{1F31E}", + "\u{1F31F}", + "\u{1F320}", + "\u{1F32D}", + "\u{1F32E}", + "\u{1F32F}", + "\u{1F330}", + "\u{1F331}", + "\u{1F332}", + "\u{1F333}", + "\u{1F334}", + "\u{1F335}", + "\u{1F337}", + "\u{1F338}", + "\u{1F339}", + "\u{1F33A}", + "\u{1F33B}", + "\u{1F33C}", + "\u{1F33D}", + "\u{1F33E}", + "\u{1F33F}", + "\u{1F340}", + "\u{1F341}", + "\u{1F342}", + "\u{1F343}", + "\u{1F344}", + "\u{1F345}", + "\u{1F346}", + "\u{1F347}", + "\u{1F348}", + "\u{1F349}", + "\u{1F34A}", + "\u{1F34B}", + "\u{1F34C}", + "\u{1F34D}", + "\u{1F34E}", + "\u{1F34F}", + "\u{1F350}", + "\u{1F351}", + "\u{1F352}", + "\u{1F353}", + "\u{1F354}", + "\u{1F355}", + "\u{1F356}", + "\u{1F357}", + "\u{1F358}", + "\u{1F359}", + "\u{1F35A}", + "\u{1F35B}", + "\u{1F35C}", + "\u{1F35D}", + "\u{1F35E}", + "\u{1F35F}", + "\u{1F360}", + "\u{1F361}", + "\u{1F362}", + "\u{1F363}", + "\u{1F364}", + "\u{1F365}", + "\u{1F366}", + "\u{1F367}", + "\u{1F368}", + "\u{1F369}", + "\u{1F36A}", + "\u{1F36B}", + "\u{1F36C}", + "\u{1F36D}", + "\u{1F36E}", + "\u{1F36F}", + "\u{1F370}", + "\u{1F371}", + "\u{1F372}", + "\u{1F373}", + "\u{1F374}", + "\u{1F375}", + "\u{1F376}", + "\u{1F377}", + "\u{1F378}", + "\u{1F379}", + "\u{1F37A}", + "\u{1F37B}", + "\u{1F37C}", + "\u{1F37E}", + "\u{1F37F}", + "\u{1F380}", + "\u{1F381}", + "\u{1F382}", + "\u{1F383}", + "\u{1F384}", + "\u{1F385}", + "\u{1F386}", + "\u{1F387}", + "\u{1F388}", + "\u{1F389}", + "\u{1F38A}", + "\u{1F38B}", + "\u{1F38C}", + "\u{1F38D}", + "\u{1F38E}", + "\u{1F38F}", + "\u{1F390}", + "\u{1F391}", + "\u{1F392}", + "\u{1F393}", + "\u{1F3A0}", + "\u{1F3A1}", + "\u{1F3A2}", + "\u{1F3A3}", + "\u{1F3A4}", + "\u{1F3A5}", + "\u{1F3A6}", + "\u{1F3A7}", + "\u{1F3A8}", + "\u{1F3A9}", + "\u{1F3AA}", + "\u{1F3AB}", + "\u{1F3AC}", + "\u{1F3AD}", + "\u{1F3AE}", + "\u{1F3AF}", + "\u{1F3B0}", + "\u{1F3B1}", + "\u{1F3B2}", + "\u{1F3B3}", + "\u{1F3B4}", + "\u{1F3B5}", + "\u{1F3B6}", + "\u{1F3B7}", + "\u{1F3B8}", + "\u{1F3B9}", + "\u{1F3BA}", + "\u{1F3BB}", + "\u{1F3BC}", + "\u{1F3BD}", + "\u{1F3BE}", + "\u{1F3BF}", + "\u{1F3C0}", + "\u{1F3C1}", + "\u{1F3C2}", + "\u{1F3C3}", + "\u{1F3C4}", + "\u{1F3C5}", + "\u{1F3C6}", + "\u{1F3C7}", + "\u{1F3C8}", + "\u{1F3C9}", + "\u{1F3CA}", + "\u{1F3CF}", + "\u{1F3D0}", + "\u{1F3D1}", + "\u{1F3D2}", + "\u{1F3D3}", + "\u{1F3E0}", + "\u{1F3E1}", + "\u{1F3E2}", + "\u{1F3E3}", + "\u{1F3E4}", + "\u{1F3E5}", + "\u{1F3E6}", + "\u{1F3E7}", + "\u{1F3E8}", + "\u{1F3E9}", + "\u{1F3EA}", + "\u{1F3EB}", + "\u{1F3EC}", + "\u{1F3ED}", + "\u{1F3EE}", + "\u{1F3EF}", + "\u{1F3F0}", + "\u{1F3F4}", + "\u{1F3F8}", + "\u{1F3F9}", + "\u{1F3FA}", + "\u{1F3FB}", + "\u{1F3FC}", + "\u{1F3FD}", + "\u{1F3FE}", + "\u{1F3FF}", + "\u{1F400}", + "\u{1F401}", + "\u{1F402}", + "\u{1F403}", + "\u{1F404}", + "\u{1F405}", + "\u{1F406}", + "\u{1F407}", + "\u{1F408}", + "\u{1F409}", + "\u{1F40A}", + "\u{1F40B}", + "\u{1F40C}", + "\u{1F40D}", + "\u{1F40E}", + "\u{1F40F}", + "\u{1F410}", + "\u{1F411}", + "\u{1F412}", + "\u{1F413}", + "\u{1F414}", + "\u{1F415}", + "\u{1F416}", + "\u{1F417}", + "\u{1F418}", + "\u{1F419}", + "\u{1F41A}", + "\u{1F41B}", + "\u{1F41C}", + "\u{1F41D}", + "\u{1F41E}", + "\u{1F41F}", + "\u{1F420}", + "\u{1F421}", + "\u{1F422}", + "\u{1F423}", + "\u{1F424}", + "\u{1F425}", + "\u{1F426}", + "\u{1F427}", + "\u{1F428}", + "\u{1F429}", + "\u{1F42A}", + "\u{1F42B}", + "\u{1F42C}", + "\u{1F42D}", + "\u{1F42E}", + "\u{1F42F}", + "\u{1F430}", + "\u{1F431}", + "\u{1F432}", + "\u{1F433}", + "\u{1F434}", + "\u{1F435}", + "\u{1F436}", + "\u{1F437}", + "\u{1F438}", + "\u{1F439}", + "\u{1F43A}", + "\u{1F43B}", + "\u{1F43C}", + "\u{1F43D}", + "\u{1F43E}", + "\u{1F440}", + "\u{1F442}", + "\u{1F443}", + "\u{1F444}", + "\u{1F445}", + "\u{1F446}", + "\u{1F447}", + "\u{1F448}", + "\u{1F449}", + "\u{1F44A}", + "\u{1F44B}", + "\u{1F44C}", + "\u{1F44D}", + "\u{1F44E}", + "\u{1F44F}", + "\u{1F450}", + "\u{1F451}", + "\u{1F452}", + "\u{1F453}", + "\u{1F454}", + "\u{1F455}", + "\u{1F456}", + "\u{1F457}", + "\u{1F458}", + "\u{1F459}", + "\u{1F45A}", + "\u{1F45B}", + "\u{1F45C}", + "\u{1F45D}", + "\u{1F45E}", + "\u{1F45F}", + "\u{1F460}", + "\u{1F461}", + "\u{1F462}", + "\u{1F463}", + "\u{1F464}", + "\u{1F465}", + "\u{1F466}", + "\u{1F467}", + "\u{1F468}", + "\u{1F469}", + "\u{1F46A}", + "\u{1F46B}", + "\u{1F46C}", + "\u{1F46D}", + "\u{1F46E}", + "\u{1F46F}", + "\u{1F470}", + "\u{1F471}", + "\u{1F472}", + "\u{1F473}", + "\u{1F474}", + "\u{1F475}", + "\u{1F476}", + "\u{1F477}", + "\u{1F478}", + "\u{1F479}", + "\u{1F47A}", + "\u{1F47B}", + "\u{1F47C}", + "\u{1F47D}", + "\u{1F47E}", + "\u{1F47F}", + "\u{1F480}", + "\u{1F481}", + "\u{1F482}", + "\u{1F483}", + "\u{1F484}", + "\u{1F485}", + "\u{1F486}", + "\u{1F487}", + "\u{1F488}", + "\u{1F489}", + "\u{1F48A}", + "\u{1F48B}", + "\u{1F48C}", + "\u{1F48D}", + "\u{1F48E}", + "\u{1F48F}", + "\u{1F490}", + "\u{1F491}", + "\u{1F492}", + "\u{1F493}", + "\u{1F494}", + "\u{1F495}", + "\u{1F496}", + "\u{1F497}", + "\u{1F498}", + "\u{1F499}", + "\u{1F49A}", + "\u{1F49B}", + "\u{1F49C}", + "\u{1F49D}", + "\u{1F49E}", + "\u{1F49F}", + "\u{1F4A0}", + "\u{1F4A1}", + "\u{1F4A2}", + "\u{1F4A3}", + "\u{1F4A4}", + "\u{1F4A5}", + "\u{1F4A6}", + "\u{1F4A7}", + "\u{1F4A8}", + "\u{1F4A9}", + "\u{1F4AA}", + "\u{1F4AB}", + "\u{1F4AC}", + "\u{1F4AD}", + "\u{1F4AE}", + "\u{1F4AF}", + "\u{1F4B0}", + "\u{1F4B1}", + "\u{1F4B2}", + "\u{1F4B3}", + "\u{1F4B4}", + "\u{1F4B5}", + "\u{1F4B6}", + "\u{1F4B7}", + "\u{1F4B8}", + "\u{1F4B9}", + "\u{1F4BA}", + "\u{1F4BB}", + "\u{1F4BC}", + "\u{1F4BD}", + "\u{1F4BE}", + "\u{1F4BF}", + "\u{1F4C0}", + "\u{1F4C1}", + "\u{1F4C2}", + "\u{1F4C3}", + "\u{1F4C4}", + "\u{1F4C5}", + "\u{1F4C6}", + "\u{1F4C7}", + "\u{1F4C8}", + "\u{1F4C9}", + "\u{1F4CA}", + "\u{1F4CB}", + "\u{1F4CC}", + "\u{1F4CD}", + "\u{1F4CE}", + "\u{1F4CF}", + "\u{1F4D0}", + "\u{1F4D1}", + "\u{1F4D2}", + "\u{1F4D3}", + "\u{1F4D4}", + "\u{1F4D5}", + "\u{1F4D6}", + "\u{1F4D7}", + "\u{1F4D8}", + "\u{1F4D9}", + "\u{1F4DA}", + "\u{1F4DB}", + "\u{1F4DC}", + "\u{1F4DD}", + "\u{1F4DE}", + "\u{1F4DF}", + "\u{1F4E0}", + "\u{1F4E1}", + "\u{1F4E2}", + "\u{1F4E3}", + "\u{1F4E4}", + "\u{1F4E5}", + "\u{1F4E6}", + "\u{1F4E7}", + "\u{1F4E8}", + "\u{1F4E9}", + "\u{1F4EA}", + "\u{1F4EB}", + "\u{1F4EC}", + "\u{1F4ED}", + "\u{1F4EE}", + "\u{1F4EF}", + "\u{1F4F0}", + "\u{1F4F1}", + "\u{1F4F2}", + "\u{1F4F3}", + "\u{1F4F4}", + "\u{1F4F5}", + "\u{1F4F6}", + "\u{1F4F7}", + "\u{1F4F8}", + "\u{1F4F9}", + "\u{1F4FA}", + "\u{1F4FB}", + "\u{1F4FC}", + "\u{1F4FF}", + "\u{1F500}", + "\u{1F501}", + "\u{1F502}", + "\u{1F503}", + "\u{1F504}", + "\u{1F505}", + "\u{1F506}", + "\u{1F507}", + "\u{1F508}", + "\u{1F509}", + "\u{1F50A}", + "\u{1F50B}", + "\u{1F50C}", + "\u{1F50D}", + "\u{1F50E}", + "\u{1F50F}", + "\u{1F510}", + "\u{1F511}", + "\u{1F512}", + "\u{1F513}", + "\u{1F514}", + "\u{1F515}", + "\u{1F516}", + "\u{1F517}", + "\u{1F518}", + "\u{1F519}", + "\u{1F51A}", + "\u{1F51B}", + "\u{1F51C}", + "\u{1F51D}", + "\u{1F51E}", + "\u{1F51F}", + "\u{1F520}", + "\u{1F521}", + "\u{1F522}", + "\u{1F523}", + "\u{1F524}", + "\u{1F525}", + "\u{1F526}", + "\u{1F527}", + "\u{1F528}", + "\u{1F529}", + "\u{1F52A}", + "\u{1F52B}", + "\u{1F52C}", + "\u{1F52D}", + "\u{1F52E}", + "\u{1F52F}", + "\u{1F530}", + "\u{1F531}", + "\u{1F532}", + "\u{1F533}", + "\u{1F534}", + "\u{1F535}", + "\u{1F536}", + "\u{1F537}", + "\u{1F538}", + "\u{1F539}", + "\u{1F53A}", + "\u{1F53B}", + "\u{1F53C}", + "\u{1F53D}", + "\u{1F54B}", + "\u{1F54C}", + "\u{1F54D}", + "\u{1F54E}", + "\u{1F550}", + "\u{1F551}", + "\u{1F552}", + "\u{1F553}", + "\u{1F554}", + "\u{1F555}", + "\u{1F556}", + "\u{1F557}", + "\u{1F558}", + "\u{1F559}", + "\u{1F55A}", + "\u{1F55B}", + "\u{1F55C}", + "\u{1F55D}", + "\u{1F55E}", + "\u{1F55F}", + "\u{1F560}", + "\u{1F561}", + "\u{1F562}", + "\u{1F563}", + "\u{1F564}", + "\u{1F565}", + "\u{1F566}", + "\u{1F567}", + "\u{1F57A}", + "\u{1F595}", + "\u{1F596}", + "\u{1F5A4}", + "\u{1F5FB}", + "\u{1F5FC}", + "\u{1F5FD}", + "\u{1F5FE}", + "\u{1F5FF}", + "\u{1F600}", + "\u{1F601}", + "\u{1F602}", + "\u{1F603}", + "\u{1F604}", + "\u{1F605}", + "\u{1F606}", + "\u{1F607}", + "\u{1F608}", + "\u{1F609}", + "\u{1F60A}", + "\u{1F60B}", + "\u{1F60C}", + "\u{1F60D}", + "\u{1F60E}", + "\u{1F60F}", + "\u{1F610}", + "\u{1F611}", + "\u{1F612}", + "\u{1F613}", + "\u{1F614}", + "\u{1F615}", + "\u{1F616}", + "\u{1F617}", + "\u{1F618}", + "\u{1F619}", + "\u{1F61A}", + "\u{1F61B}", + "\u{1F61C}", + "\u{1F61D}", + "\u{1F61E}", + "\u{1F61F}", + "\u{1F620}", + "\u{1F621}", + "\u{1F622}", + "\u{1F623}", + "\u{1F624}", + "\u{1F625}", + "\u{1F626}", + "\u{1F627}", + "\u{1F628}", + "\u{1F629}", + "\u{1F62A}", + "\u{1F62B}", + "\u{1F62C}", + "\u{1F62D}", + "\u{1F62E}", + "\u{1F62F}", + "\u{1F630}", + "\u{1F631}", + "\u{1F632}", + "\u{1F633}", + "\u{1F634}", + "\u{1F635}", + "\u{1F636}", + "\u{1F637}", + "\u{1F638}", + "\u{1F639}", + "\u{1F63A}", + "\u{1F63B}", + "\u{1F63C}", + "\u{1F63D}", + "\u{1F63E}", + "\u{1F63F}", + "\u{1F640}", + "\u{1F641}", + "\u{1F642}", + "\u{1F643}", + "\u{1F644}", + "\u{1F645}", + "\u{1F646}", + "\u{1F647}", + "\u{1F648}", + "\u{1F649}", + "\u{1F64A}", + "\u{1F64B}", + "\u{1F64C}", + "\u{1F64D}", + "\u{1F64E}", + "\u{1F64F}", + "\u{1F680}", + "\u{1F681}", + "\u{1F682}", + "\u{1F683}", + "\u{1F684}", + "\u{1F685}", + "\u{1F686}", + "\u{1F687}", + "\u{1F688}", + "\u{1F689}", + "\u{1F68A}", + "\u{1F68B}", + "\u{1F68C}", + "\u{1F68D}", + "\u{1F68E}", + "\u{1F68F}", + "\u{1F690}", + "\u{1F691}", + "\u{1F692}", + "\u{1F693}", + "\u{1F694}", + "\u{1F695}", + "\u{1F696}", + "\u{1F697}", + "\u{1F698}", + "\u{1F699}", + "\u{1F69A}", + "\u{1F69B}", + "\u{1F69C}", + "\u{1F69D}", + "\u{1F69E}", + "\u{1F69F}", + "\u{1F6A0}", + "\u{1F6A1}", + "\u{1F6A2}", + "\u{1F6A3}", + "\u{1F6A4}", + "\u{1F6A5}", + "\u{1F6A6}", + "\u{1F6A7}", + "\u{1F6A8}", + "\u{1F6A9}", + "\u{1F6AA}", + "\u{1F6AB}", + "\u{1F6AC}", + "\u{1F6AD}", + "\u{1F6AE}", + "\u{1F6AF}", + "\u{1F6B0}", + "\u{1F6B1}", + "\u{1F6B2}", + "\u{1F6B3}", + "\u{1F6B4}", + "\u{1F6B5}", + "\u{1F6B6}", + "\u{1F6B7}", + "\u{1F6B8}", + "\u{1F6B9}", + "\u{1F6BA}", + "\u{1F6BB}", + "\u{1F6BC}", + "\u{1F6BD}", + "\u{1F6BE}", + "\u{1F6BF}", + "\u{1F6C0}", + "\u{1F6C1}", + "\u{1F6C2}", + "\u{1F6C3}", + "\u{1F6C4}", + "\u{1F6C5}", + "\u{1F6CC}", + "\u{1F6D0}", + "\u{1F6D1}", + "\u{1F6D2}", + "\u{1F6D5}", + "\u{1F6D6}", + "\u{1F6D7}", + "\u{1F6DD}", + "\u{1F6DE}", + "\u{1F6DF}", + "\u{1F6EB}", + "\u{1F6EC}", + "\u{1F6F4}", + "\u{1F6F5}", + "\u{1F6F6}", + "\u{1F6F7}", + "\u{1F6F8}", + "\u{1F6F9}", + "\u{1F6FA}", + "\u{1F6FB}", + "\u{1F6FC}", + "\u{1F7E0}", + "\u{1F7E1}", + "\u{1F7E2}", + "\u{1F7E3}", + "\u{1F7E4}", + "\u{1F7E5}", + "\u{1F7E6}", + "\u{1F7E7}", + "\u{1F7E8}", + "\u{1F7E9}", + "\u{1F7EA}", + "\u{1F7EB}", + "\u{1F7F0}", + "\u{1F90C}", + "\u{1F90D}", + "\u{1F90E}", + "\u{1F90F}", + "\u{1F910}", + "\u{1F911}", + "\u{1F912}", + "\u{1F913}", + "\u{1F914}", + "\u{1F915}", + "\u{1F916}", + "\u{1F917}", + "\u{1F918}", + "\u{1F919}", + "\u{1F91A}", + "\u{1F91B}", + "\u{1F91C}", + "\u{1F91D}", + "\u{1F91E}", + "\u{1F91F}", + "\u{1F920}", + "\u{1F921}", + "\u{1F922}", + "\u{1F923}", + "\u{1F924}", + "\u{1F925}", + "\u{1F926}", + "\u{1F927}", + "\u{1F928}", + "\u{1F929}", + "\u{1F92A}", + "\u{1F92B}", + "\u{1F92C}", + "\u{1F92D}", + "\u{1F92E}", + "\u{1F92F}", + "\u{1F930}", + "\u{1F931}", + "\u{1F932}", + "\u{1F933}", + "\u{1F934}", + "\u{1F935}", + "\u{1F936}", + "\u{1F937}", + "\u{1F938}", + "\u{1F939}", + "\u{1F93A}", + "\u{1F93C}", + "\u{1F93D}", + "\u{1F93E}", + "\u{1F93F}", + "\u{1F940}", + "\u{1F941}", + "\u{1F942}", + "\u{1F943}", + "\u{1F944}", + "\u{1F945}", + "\u{1F947}", + "\u{1F948}", + "\u{1F949}", + "\u{1F94A}", + "\u{1F94B}", + "\u{1F94C}", + "\u{1F94D}", + "\u{1F94E}", + "\u{1F94F}", + "\u{1F950}", + "\u{1F951}", + "\u{1F952}", + "\u{1F953}", + "\u{1F954}", + "\u{1F955}", + "\u{1F956}", + "\u{1F957}", + "\u{1F958}", + "\u{1F959}", + "\u{1F95A}", + "\u{1F95B}", + "\u{1F95C}", + "\u{1F95D}", + "\u{1F95E}", + "\u{1F95F}", + "\u{1F960}", + "\u{1F961}", + "\u{1F962}", + "\u{1F963}", + "\u{1F964}", + "\u{1F965}", + "\u{1F966}", + "\u{1F967}", + "\u{1F968}", + "\u{1F969}", + "\u{1F96A}", + "\u{1F96B}", + "\u{1F96C}", + "\u{1F96D}", + "\u{1F96E}", + "\u{1F96F}", + "\u{1F970}", + "\u{1F971}", + "\u{1F972}", + "\u{1F973}", + "\u{1F974}", + "\u{1F975}", + "\u{1F976}", + "\u{1F977}", + "\u{1F978}", + "\u{1F979}", + "\u{1F97A}", + "\u{1F97B}", + "\u{1F97C}", + "\u{1F97D}", + "\u{1F97E}", + "\u{1F97F}", + "\u{1F980}", + "\u{1F981}", + "\u{1F982}", + "\u{1F983}", + "\u{1F984}", + "\u{1F985}", + "\u{1F986}", + "\u{1F987}", + "\u{1F988}", + "\u{1F989}", + "\u{1F98A}", + "\u{1F98B}", + "\u{1F98C}", + "\u{1F98D}", + "\u{1F98E}", + "\u{1F98F}", + "\u{1F990}", + "\u{1F991}", + "\u{1F992}", + "\u{1F993}", + "\u{1F994}", + "\u{1F995}", + "\u{1F996}", + "\u{1F997}", + "\u{1F998}", + "\u{1F999}", + "\u{1F99A}", + "\u{1F99B}", + "\u{1F99C}", + "\u{1F99D}", + "\u{1F99E}", + "\u{1F99F}", + "\u{1F9A0}", + "\u{1F9A1}", + "\u{1F9A2}", + "\u{1F9A3}", + "\u{1F9A4}", + "\u{1F9A5}", + "\u{1F9A6}", + "\u{1F9A7}", + "\u{1F9A8}", + "\u{1F9A9}", + "\u{1F9AA}", + "\u{1F9AB}", + "\u{1F9AC}", + "\u{1F9AD}", + "\u{1F9AE}", + "\u{1F9AF}", + "\u{1F9B0}", + "\u{1F9B1}", + "\u{1F9B2}", + "\u{1F9B3}", + "\u{1F9B4}", + "\u{1F9B5}", + "\u{1F9B6}", + "\u{1F9B7}", + "\u{1F9B8}", + "\u{1F9B9}", + "\u{1F9BA}", + "\u{1F9BB}", + "\u{1F9BC}", + "\u{1F9BD}", + "\u{1F9BE}", + "\u{1F9BF}", + "\u{1F9C0}", + "\u{1F9C1}", + "\u{1F9C2}", + "\u{1F9C3}", + "\u{1F9C4}", + "\u{1F9C5}", + "\u{1F9C6}", + "\u{1F9C7}", + "\u{1F9C8}", + "\u{1F9C9}", + "\u{1F9CA}", + "\u{1F9CB}", + "\u{1F9CC}", + "\u{1F9CD}", + "\u{1F9CE}", + "\u{1F9CF}", + "\u{1F9D0}", + "\u{1F9D1}", + "\u{1F9D2}", + "\u{1F9D3}", + "\u{1F9D4}", + "\u{1F9D5}", + "\u{1F9D6}", + "\u{1F9D7}", + "\u{1F9D8}", + "\u{1F9D9}", + "\u{1F9DA}", + "\u{1F9DB}", + "\u{1F9DC}", + "\u{1F9DD}", + "\u{1F9DE}", + "\u{1F9DF}", + "\u{1F9E0}", + "\u{1F9E1}", + "\u{1F9E2}", + "\u{1F9E3}", + "\u{1F9E4}", + "\u{1F9E5}", + "\u{1F9E6}", + "\u{1F9E7}", + "\u{1F9E8}", + "\u{1F9E9}", + "\u{1F9EA}", + "\u{1F9EB}", + "\u{1F9EC}", + "\u{1F9ED}", + "\u{1F9EE}", + "\u{1F9EF}", + "\u{1F9F0}", + "\u{1F9F1}", + "\u{1F9F2}", + "\u{1F9F3}", + "\u{1F9F4}", + "\u{1F9F5}", + "\u{1F9F6}", + "\u{1F9F7}", + "\u{1F9F8}", + "\u{1F9F9}", + "\u{1F9FA}", + "\u{1F9FB}", + "\u{1F9FC}", + "\u{1F9FD}", + "\u{1F9FE}", + "\u{1F9FF}", + "\u{1FA70}", + "\u{1FA71}", + "\u{1FA72}", + "\u{1FA73}", + "\u{1FA74}", + "\u{1FA78}", + "\u{1FA79}", + "\u{1FA7A}", + "\u{1FA7B}", + "\u{1FA7C}", + "\u{1FA80}", + "\u{1FA81}", + "\u{1FA82}", + "\u{1FA83}", + "\u{1FA84}", + "\u{1FA85}", + "\u{1FA86}", + "\u{1FA90}", + "\u{1FA91}", + "\u{1FA92}", + "\u{1FA93}", + "\u{1FA94}", + "\u{1FA95}", + "\u{1FA96}", + "\u{1FA97}", + "\u{1FA98}", + "\u{1FA99}", + "\u{1FA9A}", + "\u{1FA9B}", + "\u{1FA9C}", + "\u{1FA9D}", + "\u{1FA9E}", + "\u{1FA9F}", + "\u{1FAA0}", + "\u{1FAA1}", + "\u{1FAA2}", + "\u{1FAA3}", + "\u{1FAA4}", + "\u{1FAA5}", + "\u{1FAA6}", + "\u{1FAA7}", + "\u{1FAA8}", + "\u{1FAA9}", + "\u{1FAAA}", + "\u{1FAAB}", + "\u{1FAAC}", + "\u{1FAB0}", + "\u{1FAB1}", + "\u{1FAB2}", + "\u{1FAB3}", + "\u{1FAB4}", + "\u{1FAB5}", + "\u{1FAB6}", + "\u{1FAB7}", + "\u{1FAB8}", + "\u{1FAB9}", + "\u{1FABA}", + "\u{1FAC0}", + "\u{1FAC1}", + "\u{1FAC2}", + "\u{1FAC3}", + "\u{1FAC4}", + "\u{1FAC5}", + "\u{1FAD0}", + "\u{1FAD1}", + "\u{1FAD2}", + "\u{1FAD3}", + "\u{1FAD4}", + "\u{1FAD5}", + "\u{1FAD6}", + "\u{1FAD7}", + "\u{1FAD8}", + "\u{1FAD9}", + "\u{1FAE0}", + "\u{1FAE1}", + "\u{1FAE2}", + "\u{1FAE3}", + "\u{1FAE4}", + "\u{1FAE5}", + "\u{1FAE6}", + "\u{1FAE7}", + "\u{1FAF0}", + "\u{1FAF1}", + "\u{1FAF2}", + "\u{1FAF3}", + "\u{1FAF4}", + "\u{1FAF5}", + "\u{1FAF6}", + "\xA9\uFE0F", + "\xAE\uFE0F", + "\u203C\uFE0F", + "\u2049\uFE0F", + "\u2122\uFE0F", + "\u2139\uFE0F", + "\u2194\uFE0F", + "\u2195\uFE0F", + "\u2196\uFE0F", + "\u2197\uFE0F", + "\u2198\uFE0F", + "\u2199\uFE0F", + "\u21A9\uFE0F", + "\u21AA\uFE0F", + "\u2328\uFE0F", + "\u23CF\uFE0F", + "\u23ED\uFE0F", + "\u23EE\uFE0F", + "\u23EF\uFE0F", + "\u23F1\uFE0F", + "\u23F2\uFE0F", + "\u23F8\uFE0F", + "\u23F9\uFE0F", + "\u23FA\uFE0F", + "\u24C2\uFE0F", + "\u25AA\uFE0F", + "\u25AB\uFE0F", + "\u25B6\uFE0F", + "\u25C0\uFE0F", + "\u25FB\uFE0F", + "\u25FC\uFE0F", + "\u2600\uFE0F", + "\u2601\uFE0F", + "\u2602\uFE0F", + "\u2603\uFE0F", + "\u2604\uFE0F", + "\u260E\uFE0F", + "\u2611\uFE0F", + "\u2618\uFE0F", + "\u261D\uFE0F", + "\u2620\uFE0F", + "\u2622\uFE0F", + "\u2623\uFE0F", + "\u2626\uFE0F", + "\u262A\uFE0F", + "\u262E\uFE0F", + "\u262F\uFE0F", + "\u2638\uFE0F", + "\u2639\uFE0F", + "\u263A\uFE0F", + "\u2640\uFE0F", + "\u2642\uFE0F", + "\u265F\uFE0F", + "\u2660\uFE0F", + "\u2663\uFE0F", + "\u2665\uFE0F", + "\u2666\uFE0F", + "\u2668\uFE0F", + "\u267B\uFE0F", + "\u267E\uFE0F", + "\u2692\uFE0F", + "\u2694\uFE0F", + "\u2695\uFE0F", + "\u2696\uFE0F", + "\u2697\uFE0F", + "\u2699\uFE0F", + "\u269B\uFE0F", + "\u269C\uFE0F", + "\u26A0\uFE0F", + "\u26A7\uFE0F", + "\u26B0\uFE0F", + "\u26B1\uFE0F", + "\u26C8\uFE0F", + "\u26CF\uFE0F", + "\u26D1\uFE0F", + "\u26D3\uFE0F", + "\u26E9\uFE0F", + "\u26F0\uFE0F", + "\u26F1\uFE0F", + "\u26F4\uFE0F", + "\u26F7\uFE0F", + "\u26F8\uFE0F", + "\u26F9\uFE0F", + "\u2702\uFE0F", + "\u2708\uFE0F", + "\u2709\uFE0F", + "\u270C\uFE0F", + "\u270D\uFE0F", + "\u270F\uFE0F", + "\u2712\uFE0F", + "\u2714\uFE0F", + "\u2716\uFE0F", + "\u271D\uFE0F", + "\u2721\uFE0F", + "\u2733\uFE0F", + "\u2734\uFE0F", + "\u2744\uFE0F", + "\u2747\uFE0F", + "\u2763\uFE0F", + "\u2764\uFE0F", + "\u27A1\uFE0F", + "\u2934\uFE0F", + "\u2935\uFE0F", + "\u2B05\uFE0F", + "\u2B06\uFE0F", + "\u2B07\uFE0F", + "\u3030\uFE0F", + "\u303D\uFE0F", + "\u3297\uFE0F", + "\u3299\uFE0F", + "\u{1F170}\uFE0F", + "\u{1F171}\uFE0F", + "\u{1F17E}\uFE0F", + "\u{1F17F}\uFE0F", + "\u{1F202}\uFE0F", + "\u{1F237}\uFE0F", + "\u{1F321}\uFE0F", + "\u{1F324}\uFE0F", + "\u{1F325}\uFE0F", + "\u{1F326}\uFE0F", + "\u{1F327}\uFE0F", + "\u{1F328}\uFE0F", + "\u{1F329}\uFE0F", + "\u{1F32A}\uFE0F", + "\u{1F32B}\uFE0F", + "\u{1F32C}\uFE0F", + "\u{1F336}\uFE0F", + "\u{1F37D}\uFE0F", + "\u{1F396}\uFE0F", + "\u{1F397}\uFE0F", + "\u{1F399}\uFE0F", + "\u{1F39A}\uFE0F", + "\u{1F39B}\uFE0F", + "\u{1F39E}\uFE0F", + "\u{1F39F}\uFE0F", + "\u{1F3CB}\uFE0F", + "\u{1F3CC}\uFE0F", + "\u{1F3CD}\uFE0F", + "\u{1F3CE}\uFE0F", + "\u{1F3D4}\uFE0F", + "\u{1F3D5}\uFE0F", + "\u{1F3D6}\uFE0F", + "\u{1F3D7}\uFE0F", + "\u{1F3D8}\uFE0F", + "\u{1F3D9}\uFE0F", + "\u{1F3DA}\uFE0F", + "\u{1F3DB}\uFE0F", + "\u{1F3DC}\uFE0F", + "\u{1F3DD}\uFE0F", + "\u{1F3DE}\uFE0F", + "\u{1F3DF}\uFE0F", + "\u{1F3F3}\uFE0F", + "\u{1F3F5}\uFE0F", + "\u{1F3F7}\uFE0F", + "\u{1F43F}\uFE0F", + "\u{1F441}\uFE0F", + "\u{1F4FD}\uFE0F", + "\u{1F549}\uFE0F", + "\u{1F54A}\uFE0F", + "\u{1F56F}\uFE0F", + "\u{1F570}\uFE0F", + "\u{1F573}\uFE0F", + "\u{1F574}\uFE0F", + "\u{1F575}\uFE0F", + "\u{1F576}\uFE0F", + "\u{1F577}\uFE0F", + "\u{1F578}\uFE0F", + "\u{1F579}\uFE0F", + "\u{1F587}\uFE0F", + "\u{1F58A}\uFE0F", + "\u{1F58B}\uFE0F", + "\u{1F58C}\uFE0F", + "\u{1F58D}\uFE0F", + "\u{1F590}\uFE0F", + "\u{1F5A5}\uFE0F", + "\u{1F5A8}\uFE0F", + "\u{1F5B1}\uFE0F", + "\u{1F5B2}\uFE0F", + "\u{1F5BC}\uFE0F", + "\u{1F5C2}\uFE0F", + "\u{1F5C3}\uFE0F", + "\u{1F5C4}\uFE0F", + "\u{1F5D1}\uFE0F", + "\u{1F5D2}\uFE0F", + "\u{1F5D3}\uFE0F", + "\u{1F5DC}\uFE0F", + "\u{1F5DD}\uFE0F", + "\u{1F5DE}\uFE0F", + "\u{1F5E1}\uFE0F", + "\u{1F5E3}\uFE0F", + "\u{1F5E8}\uFE0F", + "\u{1F5EF}\uFE0F", + "\u{1F5F3}\uFE0F", + "\u{1F5FA}\uFE0F", + "\u{1F6CB}\uFE0F", + "\u{1F6CD}\uFE0F", + "\u{1F6CE}\uFE0F", + "\u{1F6CF}\uFE0F", + "\u{1F6E0}\uFE0F", + "\u{1F6E1}\uFE0F", + "\u{1F6E2}\uFE0F", + "\u{1F6E3}\uFE0F", + "\u{1F6E4}\uFE0F", + "\u{1F6E5}\uFE0F", + "\u{1F6E9}\uFE0F", + "\u{1F6F0}\uFE0F", + "\u{1F6F3}\uFE0F" + ], + nonMatchStrings: [ + "\uFE0F", + "\xA9", + "\uFE0F", + "\xAE", + "\uFE0F", + "\u203C", + "\uFE0F", + "\u2049", + "\uFE0F", + "\u2122" + ], +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-CharacterClass.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-CharacterClass.js new file mode 100644 index 000000000000..ed05dff7f9d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-CharacterClass.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `Emoji_Keycap_Sequence` (property of strings) with `[^\p{…}]` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/[^\p{Emoji_Keycap_Sequence}]/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-P.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-P.js new file mode 100644 index 000000000000..3e7d447206c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-P.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `Emoji_Keycap_Sequence` (property of strings) with `\P{…}` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\P{Emoji_Keycap_Sequence}/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-u.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-u.js new file mode 100644 index 000000000000..32eef16981b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-u.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Emoji_Keycap_Sequence` (property of strings) with the `u` flag throws an early error. Properties of strings are only supported through the `v` flag. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-patterns-static-semantics-early-errors +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\p{Emoji_Keycap_Sequence}/u; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence.js new file mode 100644 index 000000000000..2bdd3bb6572a --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence.js @@ -0,0 +1,53 @@ +// |reftest| skip -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Emoji_Keycap_Sequence` (property of strings) +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes, regexp-v-flag] +includes: [regExpUtils.js] +---*/ + +testPropertyOfStrings({ + regExp: /^\p{Emoji_Keycap_Sequence}+$/v, + expression: "\\p{Emoji_Keycap_Sequence}", + matchStrings: [ + "#\uFE0F\u20E3", + "*\uFE0F\u20E3", + "0\uFE0F\u20E3", + "1\uFE0F\u20E3", + "2\uFE0F\u20E3", + "3\uFE0F\u20E3", + "4\uFE0F\u20E3", + "5\uFE0F\u20E3", + "6\uFE0F\u20E3", + "7\uFE0F\u20E3", + "8\uFE0F\u20E3", + "9\uFE0F\u20E3" + ], + nonMatchStrings: [ + "\uFE0F\u20E3", + "#\uFE0F", + "#\u20E3", + "\uFE0F\u20E3", + "*\uFE0F", + "*\u20E3", + "\uFE0F\u20E3", + "0\uFE0F", + "0\u20E3", + "\uFE0F\u20E3", + "1\uFE0F", + "1\u20E3", + "\uFE0F\u20E3", + "2\uFE0F", + "2\u20E3" + ], +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-CharacterClass.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-CharacterClass.js new file mode 100644 index 000000000000..89b332c4cfee --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-CharacterClass.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `Emoji_Test` (property of strings) with `[^\p{…}]` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/[^\p{Emoji_Test}]/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-P.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-P.js new file mode 100644 index 000000000000..05bd98282837 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-P.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `Emoji_Test` (property of strings) with `\P{…}` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\P{Emoji_Test}/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-u.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-u.js new file mode 100644 index 000000000000..e15a5dfd7400 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test-negative-u.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Emoji_Test` (property of strings) with the `u` flag throws an early error. Properties of strings are only supported through the `v` flag. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-patterns-static-semantics-early-errors +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\p{Emoji_Test}/u; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test.js new file mode 100644 index 000000000000..902d0ddecb5f --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/Emoji_Test.js @@ -0,0 +1,4743 @@ +// |reftest| skip -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `Emoji_Test` (property of strings) +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes, regexp-v-flag] +includes: [regExpUtils.js] +---*/ + +testPropertyOfStrings({ + regExp: /^\p{Emoji_Test}+$/v, + expression: "\\p{Emoji_Test}", + matchStrings: [ + "\u{1F600}", + "\u{1F603}", + "\u{1F604}", + "\u{1F601}", + "\u{1F606}", + "\u{1F605}", + "\u{1F923}", + "\u{1F602}", + "\u{1F642}", + "\u{1F643}", + "\u{1FAE0}", + "\u{1F609}", + "\u{1F60A}", + "\u{1F607}", + "\u{1F970}", + "\u{1F60D}", + "\u{1F929}", + "\u{1F618}", + "\u{1F617}", + "\u263A\uFE0F", + "\u263A", + "\u{1F61A}", + "\u{1F619}", + "\u{1F972}", + "\u{1F60B}", + "\u{1F61B}", + "\u{1F61C}", + "\u{1F92A}", + "\u{1F61D}", + "\u{1F911}", + "\u{1F917}", + "\u{1F92D}", + "\u{1FAE2}", + "\u{1FAE3}", + "\u{1F92B}", + "\u{1F914}", + "\u{1FAE1}", + "\u{1F910}", + "\u{1F928}", + "\u{1F610}", + "\u{1F611}", + "\u{1F636}", + "\u{1FAE5}", + "\u{1F636}\u200D\u{1F32B}\uFE0F", + "\u{1F636}\u200D\u{1F32B}", + "\u{1F60F}", + "\u{1F612}", + "\u{1F644}", + "\u{1F62C}", + "\u{1F62E}\u200D\u{1F4A8}", + "\u{1F925}", + "\u{1F60C}", + "\u{1F614}", + "\u{1F62A}", + "\u{1F924}", + "\u{1F634}", + "\u{1F637}", + "\u{1F912}", + "\u{1F915}", + "\u{1F922}", + "\u{1F92E}", + "\u{1F927}", + "\u{1F975}", + "\u{1F976}", + "\u{1F974}", + "\u{1F635}", + "\u{1F635}\u200D\u{1F4AB}", + "\u{1F92F}", + "\u{1F920}", + "\u{1F973}", + "\u{1F978}", + "\u{1F60E}", + "\u{1F913}", + "\u{1F9D0}", + "\u{1F615}", + "\u{1FAE4}", + "\u{1F61F}", + "\u{1F641}", + "\u2639\uFE0F", + "\u2639", + "\u{1F62E}", + "\u{1F62F}", + "\u{1F632}", + "\u{1F633}", + "\u{1F97A}", + "\u{1F979}", + "\u{1F626}", + "\u{1F627}", + "\u{1F628}", + "\u{1F630}", + "\u{1F625}", + "\u{1F622}", + "\u{1F62D}", + "\u{1F631}", + "\u{1F616}", + "\u{1F623}", + "\u{1F61E}", + "\u{1F613}", + "\u{1F629}", + "\u{1F62B}", + "\u{1F971}", + "\u{1F624}", + "\u{1F621}", + "\u{1F620}", + "\u{1F92C}", + "\u{1F608}", + "\u{1F47F}", + "\u{1F480}", + "\u2620\uFE0F", + "\u2620", + "\u{1F4A9}", + "\u{1F921}", + "\u{1F479}", + "\u{1F47A}", + "\u{1F47B}", + "\u{1F47D}", + "\u{1F47E}", + "\u{1F916}", + "\u{1F63A}", + "\u{1F638}", + "\u{1F639}", + "\u{1F63B}", + "\u{1F63C}", + "\u{1F63D}", + "\u{1F640}", + "\u{1F63F}", + "\u{1F63E}", + "\u{1F648}", + "\u{1F649}", + "\u{1F64A}", + "\u{1F48B}", + "\u{1F48C}", + "\u{1F498}", + "\u{1F49D}", + "\u{1F496}", + "\u{1F497}", + "\u{1F493}", + "\u{1F49E}", + "\u{1F495}", + "\u{1F49F}", + "\u2763\uFE0F", + "\u2763", + "\u{1F494}", + "\u2764\uFE0F\u200D\u{1F525}", + "\u2764\u200D\u{1F525}", + "\u2764\uFE0F\u200D\u{1FA79}", + "\u2764\u200D\u{1FA79}", + "\u2764\uFE0F", + "\u2764", + "\u{1F9E1}", + "\u{1F49B}", + "\u{1F49A}", + "\u{1F499}", + "\u{1F49C}", + "\u{1F90E}", + "\u{1F5A4}", + "\u{1F90D}", + "\u{1F4AF}", + "\u{1F4A2}", + "\u{1F4A5}", + "\u{1F4AB}", + "\u{1F4A6}", + "\u{1F4A8}", + "\u{1F573}\uFE0F", + "\u{1F573}", + "\u{1F4A3}", + "\u{1F4AC}", + "\u{1F441}\uFE0F\u200D\u{1F5E8}\uFE0F", + "\u{1F441}\u200D\u{1F5E8}\uFE0F", + "\u{1F441}\uFE0F\u200D\u{1F5E8}", + "\u{1F441}\u200D\u{1F5E8}", + "\u{1F5E8}\uFE0F", + "\u{1F5E8}", + "\u{1F5EF}\uFE0F", + "\u{1F5EF}", + "\u{1F4AD}", + "\u{1F4A4}", + "\u{1F44B}", + "\u{1F44B}\u{1F3FB}", + "\u{1F44B}\u{1F3FC}", + "\u{1F44B}\u{1F3FD}", + "\u{1F44B}\u{1F3FE}", + "\u{1F44B}\u{1F3FF}", + "\u{1F91A}", + "\u{1F91A}\u{1F3FB}", + "\u{1F91A}\u{1F3FC}", + "\u{1F91A}\u{1F3FD}", + "\u{1F91A}\u{1F3FE}", + "\u{1F91A}\u{1F3FF}", + "\u{1F590}\uFE0F", + "\u{1F590}", + "\u{1F590}\u{1F3FB}", + "\u{1F590}\u{1F3FC}", + "\u{1F590}\u{1F3FD}", + "\u{1F590}\u{1F3FE}", + "\u{1F590}\u{1F3FF}", + "\u270B", + "\u270B\u{1F3FB}", + "\u270B\u{1F3FC}", + "\u270B\u{1F3FD}", + "\u270B\u{1F3FE}", + "\u270B\u{1F3FF}", + "\u{1F596}", + "\u{1F596}\u{1F3FB}", + "\u{1F596}\u{1F3FC}", + "\u{1F596}\u{1F3FD}", + "\u{1F596}\u{1F3FE}", + "\u{1F596}\u{1F3FF}", + "\u{1FAF1}", + "\u{1FAF1}\u{1F3FB}", + "\u{1FAF1}\u{1F3FC}", + "\u{1FAF1}\u{1F3FD}", + "\u{1FAF1}\u{1F3FE}", + "\u{1FAF1}\u{1F3FF}", + "\u{1FAF2}", + "\u{1FAF2}\u{1F3FB}", + "\u{1FAF2}\u{1F3FC}", + "\u{1FAF2}\u{1F3FD}", + "\u{1FAF2}\u{1F3FE}", + "\u{1FAF2}\u{1F3FF}", + "\u{1FAF3}", + "\u{1FAF3}\u{1F3FB}", + "\u{1FAF3}\u{1F3FC}", + "\u{1FAF3}\u{1F3FD}", + "\u{1FAF3}\u{1F3FE}", + "\u{1FAF3}\u{1F3FF}", + "\u{1FAF4}", + "\u{1FAF4}\u{1F3FB}", + "\u{1FAF4}\u{1F3FC}", + "\u{1FAF4}\u{1F3FD}", + "\u{1FAF4}\u{1F3FE}", + "\u{1FAF4}\u{1F3FF}", + "\u{1F44C}", + "\u{1F44C}\u{1F3FB}", + "\u{1F44C}\u{1F3FC}", + "\u{1F44C}\u{1F3FD}", + "\u{1F44C}\u{1F3FE}", + "\u{1F44C}\u{1F3FF}", + "\u{1F90C}", + "\u{1F90C}\u{1F3FB}", + "\u{1F90C}\u{1F3FC}", + "\u{1F90C}\u{1F3FD}", + "\u{1F90C}\u{1F3FE}", + "\u{1F90C}\u{1F3FF}", + "\u{1F90F}", + "\u{1F90F}\u{1F3FB}", + "\u{1F90F}\u{1F3FC}", + "\u{1F90F}\u{1F3FD}", + "\u{1F90F}\u{1F3FE}", + "\u{1F90F}\u{1F3FF}", + "\u270C\uFE0F", + "\u270C", + "\u270C\u{1F3FB}", + "\u270C\u{1F3FC}", + "\u270C\u{1F3FD}", + "\u270C\u{1F3FE}", + "\u270C\u{1F3FF}", + "\u{1F91E}", + "\u{1F91E}\u{1F3FB}", + "\u{1F91E}\u{1F3FC}", + "\u{1F91E}\u{1F3FD}", + "\u{1F91E}\u{1F3FE}", + "\u{1F91E}\u{1F3FF}", + "\u{1FAF0}", + "\u{1FAF0}\u{1F3FB}", + "\u{1FAF0}\u{1F3FC}", + "\u{1FAF0}\u{1F3FD}", + "\u{1FAF0}\u{1F3FE}", + "\u{1FAF0}\u{1F3FF}", + "\u{1F91F}", + "\u{1F91F}\u{1F3FB}", + "\u{1F91F}\u{1F3FC}", + "\u{1F91F}\u{1F3FD}", + "\u{1F91F}\u{1F3FE}", + "\u{1F91F}\u{1F3FF}", + "\u{1F918}", + "\u{1F918}\u{1F3FB}", + "\u{1F918}\u{1F3FC}", + "\u{1F918}\u{1F3FD}", + "\u{1F918}\u{1F3FE}", + "\u{1F918}\u{1F3FF}", + "\u{1F919}", + "\u{1F919}\u{1F3FB}", + "\u{1F919}\u{1F3FC}", + "\u{1F919}\u{1F3FD}", + "\u{1F919}\u{1F3FE}", + "\u{1F919}\u{1F3FF}", + "\u{1F448}", + "\u{1F448}\u{1F3FB}", + "\u{1F448}\u{1F3FC}", + "\u{1F448}\u{1F3FD}", + "\u{1F448}\u{1F3FE}", + "\u{1F448}\u{1F3FF}", + "\u{1F449}", + "\u{1F449}\u{1F3FB}", + "\u{1F449}\u{1F3FC}", + "\u{1F449}\u{1F3FD}", + "\u{1F449}\u{1F3FE}", + "\u{1F449}\u{1F3FF}", + "\u{1F446}", + "\u{1F446}\u{1F3FB}", + "\u{1F446}\u{1F3FC}", + "\u{1F446}\u{1F3FD}", + "\u{1F446}\u{1F3FE}", + "\u{1F446}\u{1F3FF}", + "\u{1F595}", + "\u{1F595}\u{1F3FB}", + "\u{1F595}\u{1F3FC}", + "\u{1F595}\u{1F3FD}", + "\u{1F595}\u{1F3FE}", + "\u{1F595}\u{1F3FF}", + "\u{1F447}", + "\u{1F447}\u{1F3FB}", + "\u{1F447}\u{1F3FC}", + "\u{1F447}\u{1F3FD}", + "\u{1F447}\u{1F3FE}", + "\u{1F447}\u{1F3FF}", + "\u261D\uFE0F", + "\u261D", + "\u261D\u{1F3FB}", + "\u261D\u{1F3FC}", + "\u261D\u{1F3FD}", + "\u261D\u{1F3FE}", + "\u261D\u{1F3FF}", + "\u{1FAF5}", + "\u{1FAF5}\u{1F3FB}", + "\u{1FAF5}\u{1F3FC}", + "\u{1FAF5}\u{1F3FD}", + "\u{1FAF5}\u{1F3FE}", + "\u{1FAF5}\u{1F3FF}", + "\u{1F44D}", + "\u{1F44D}\u{1F3FB}", + "\u{1F44D}\u{1F3FC}", + "\u{1F44D}\u{1F3FD}", + "\u{1F44D}\u{1F3FE}", + "\u{1F44D}\u{1F3FF}", + "\u{1F44E}", + "\u{1F44E}\u{1F3FB}", + "\u{1F44E}\u{1F3FC}", + "\u{1F44E}\u{1F3FD}", + "\u{1F44E}\u{1F3FE}", + "\u{1F44E}\u{1F3FF}", + "\u270A", + "\u270A\u{1F3FB}", + "\u270A\u{1F3FC}", + "\u270A\u{1F3FD}", + "\u270A\u{1F3FE}", + "\u270A\u{1F3FF}", + "\u{1F44A}", + "\u{1F44A}\u{1F3FB}", + "\u{1F44A}\u{1F3FC}", + "\u{1F44A}\u{1F3FD}", + "\u{1F44A}\u{1F3FE}", + "\u{1F44A}\u{1F3FF}", + "\u{1F91B}", + "\u{1F91B}\u{1F3FB}", + "\u{1F91B}\u{1F3FC}", + "\u{1F91B}\u{1F3FD}", + "\u{1F91B}\u{1F3FE}", + "\u{1F91B}\u{1F3FF}", + "\u{1F91C}", + "\u{1F91C}\u{1F3FB}", + "\u{1F91C}\u{1F3FC}", + "\u{1F91C}\u{1F3FD}", + "\u{1F91C}\u{1F3FE}", + "\u{1F91C}\u{1F3FF}", + "\u{1F44F}", + "\u{1F44F}\u{1F3FB}", + "\u{1F44F}\u{1F3FC}", + "\u{1F44F}\u{1F3FD}", + "\u{1F44F}\u{1F3FE}", + "\u{1F44F}\u{1F3FF}", + "\u{1F64C}", + "\u{1F64C}\u{1F3FB}", + "\u{1F64C}\u{1F3FC}", + "\u{1F64C}\u{1F3FD}", + "\u{1F64C}\u{1F3FE}", + "\u{1F64C}\u{1F3FF}", + "\u{1FAF6}", + "\u{1FAF6}\u{1F3FB}", + "\u{1FAF6}\u{1F3FC}", + "\u{1FAF6}\u{1F3FD}", + "\u{1FAF6}\u{1F3FE}", + "\u{1FAF6}\u{1F3FF}", + "\u{1F450}", + "\u{1F450}\u{1F3FB}", + "\u{1F450}\u{1F3FC}", + "\u{1F450}\u{1F3FD}", + "\u{1F450}\u{1F3FE}", + "\u{1F450}\u{1F3FF}", + "\u{1F932}", + "\u{1F932}\u{1F3FB}", + "\u{1F932}\u{1F3FC}", + "\u{1F932}\u{1F3FD}", + "\u{1F932}\u{1F3FE}", + "\u{1F932}\u{1F3FF}", + "\u{1F91D}", + "\u{1F91D}\u{1F3FB}", + "\u{1F91D}\u{1F3FC}", + "\u{1F91D}\u{1F3FD}", + "\u{1F91D}\u{1F3FE}", + "\u{1F91D}\u{1F3FF}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1F64F}", + "\u{1F64F}\u{1F3FB}", + "\u{1F64F}\u{1F3FC}", + "\u{1F64F}\u{1F3FD}", + "\u{1F64F}\u{1F3FE}", + "\u{1F64F}\u{1F3FF}", + "\u270D\uFE0F", + "\u270D", + "\u270D\u{1F3FB}", + "\u270D\u{1F3FC}", + "\u270D\u{1F3FD}", + "\u270D\u{1F3FE}", + "\u270D\u{1F3FF}", + "\u{1F485}", + "\u{1F485}\u{1F3FB}", + "\u{1F485}\u{1F3FC}", + "\u{1F485}\u{1F3FD}", + "\u{1F485}\u{1F3FE}", + "\u{1F485}\u{1F3FF}", + "\u{1F933}", + "\u{1F933}\u{1F3FB}", + "\u{1F933}\u{1F3FC}", + "\u{1F933}\u{1F3FD}", + "\u{1F933}\u{1F3FE}", + "\u{1F933}\u{1F3FF}", + "\u{1F4AA}", + "\u{1F4AA}\u{1F3FB}", + "\u{1F4AA}\u{1F3FC}", + "\u{1F4AA}\u{1F3FD}", + "\u{1F4AA}\u{1F3FE}", + "\u{1F4AA}\u{1F3FF}", + "\u{1F9BE}", + "\u{1F9BF}", + "\u{1F9B5}", + "\u{1F9B5}\u{1F3FB}", + "\u{1F9B5}\u{1F3FC}", + "\u{1F9B5}\u{1F3FD}", + "\u{1F9B5}\u{1F3FE}", + "\u{1F9B5}\u{1F3FF}", + "\u{1F9B6}", + "\u{1F9B6}\u{1F3FB}", + "\u{1F9B6}\u{1F3FC}", + "\u{1F9B6}\u{1F3FD}", + "\u{1F9B6}\u{1F3FE}", + "\u{1F9B6}\u{1F3FF}", + "\u{1F442}", + "\u{1F442}\u{1F3FB}", + "\u{1F442}\u{1F3FC}", + "\u{1F442}\u{1F3FD}", + "\u{1F442}\u{1F3FE}", + "\u{1F442}\u{1F3FF}", + "\u{1F9BB}", + "\u{1F9BB}\u{1F3FB}", + "\u{1F9BB}\u{1F3FC}", + "\u{1F9BB}\u{1F3FD}", + "\u{1F9BB}\u{1F3FE}", + "\u{1F9BB}\u{1F3FF}", + "\u{1F443}", + "\u{1F443}\u{1F3FB}", + "\u{1F443}\u{1F3FC}", + "\u{1F443}\u{1F3FD}", + "\u{1F443}\u{1F3FE}", + "\u{1F443}\u{1F3FF}", + "\u{1F9E0}", + "\u{1FAC0}", + "\u{1FAC1}", + "\u{1F9B7}", + "\u{1F9B4}", + "\u{1F440}", + "\u{1F441}\uFE0F", + "\u{1F441}", + "\u{1F445}", + "\u{1F444}", + "\u{1FAE6}", + "\u{1F476}", + "\u{1F476}\u{1F3FB}", + "\u{1F476}\u{1F3FC}", + "\u{1F476}\u{1F3FD}", + "\u{1F476}\u{1F3FE}", + "\u{1F476}\u{1F3FF}", + "\u{1F9D2}", + "\u{1F9D2}\u{1F3FB}", + "\u{1F9D2}\u{1F3FC}", + "\u{1F9D2}\u{1F3FD}", + "\u{1F9D2}\u{1F3FE}", + "\u{1F9D2}\u{1F3FF}", + "\u{1F466}", + "\u{1F466}\u{1F3FB}", + "\u{1F466}\u{1F3FC}", + "\u{1F466}\u{1F3FD}", + "\u{1F466}\u{1F3FE}", + "\u{1F466}\u{1F3FF}", + "\u{1F467}", + "\u{1F467}\u{1F3FB}", + "\u{1F467}\u{1F3FC}", + "\u{1F467}\u{1F3FD}", + "\u{1F467}\u{1F3FE}", + "\u{1F467}\u{1F3FF}", + "\u{1F9D1}", + "\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}", + "\u{1F471}", + "\u{1F471}\u{1F3FB}", + "\u{1F471}\u{1F3FC}", + "\u{1F471}\u{1F3FD}", + "\u{1F471}\u{1F3FE}", + "\u{1F471}\u{1F3FF}", + "\u{1F468}", + "\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}", + "\u{1F9D4}", + "\u{1F9D4}\u{1F3FB}", + "\u{1F9D4}\u{1F3FC}", + "\u{1F9D4}\u{1F3FD}", + "\u{1F9D4}\u{1F3FE}", + "\u{1F9D4}\u{1F3FF}", + "\u{1F9D4}\u200D\u2642\uFE0F", + "\u{1F9D4}\u200D\u2642", + "\u{1F9D4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FB}\u200D\u2642", + "\u{1F9D4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FC}\u200D\u2642", + "\u{1F9D4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FD}\u200D\u2642", + "\u{1F9D4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FE}\u200D\u2642", + "\u{1F9D4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FF}\u200D\u2642", + "\u{1F9D4}\u200D\u2640\uFE0F", + "\u{1F9D4}\u200D\u2640", + "\u{1F9D4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FB}\u200D\u2640", + "\u{1F9D4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FC}\u200D\u2640", + "\u{1F9D4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FD}\u200D\u2640", + "\u{1F9D4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FE}\u200D\u2640", + "\u{1F9D4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FF}\u200D\u2640", + "\u{1F468}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F468}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F468}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B3}", + "\u{1F468}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F469}", + "\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}", + "\u{1F469}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F9D1}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F469}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F9D1}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F469}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B3}", + "\u{1F9D1}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B3}", + "\u{1F469}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F9D1}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F471}\u200D\u2640\uFE0F", + "\u{1F471}\u200D\u2640", + "\u{1F471}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FB}\u200D\u2640", + "\u{1F471}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FC}\u200D\u2640", + "\u{1F471}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FD}\u200D\u2640", + "\u{1F471}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FE}\u200D\u2640", + "\u{1F471}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FF}\u200D\u2640", + "\u{1F471}\u200D\u2642\uFE0F", + "\u{1F471}\u200D\u2642", + "\u{1F471}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FB}\u200D\u2642", + "\u{1F471}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FC}\u200D\u2642", + "\u{1F471}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FD}\u200D\u2642", + "\u{1F471}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FE}\u200D\u2642", + "\u{1F471}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FF}\u200D\u2642", + "\u{1F9D3}", + "\u{1F9D3}\u{1F3FB}", + "\u{1F9D3}\u{1F3FC}", + "\u{1F9D3}\u{1F3FD}", + "\u{1F9D3}\u{1F3FE}", + "\u{1F9D3}\u{1F3FF}", + "\u{1F474}", + "\u{1F474}\u{1F3FB}", + "\u{1F474}\u{1F3FC}", + "\u{1F474}\u{1F3FD}", + "\u{1F474}\u{1F3FE}", + "\u{1F474}\u{1F3FF}", + "\u{1F475}", + "\u{1F475}\u{1F3FB}", + "\u{1F475}\u{1F3FC}", + "\u{1F475}\u{1F3FD}", + "\u{1F475}\u{1F3FE}", + "\u{1F475}\u{1F3FF}", + "\u{1F64D}", + "\u{1F64D}\u{1F3FB}", + "\u{1F64D}\u{1F3FC}", + "\u{1F64D}\u{1F3FD}", + "\u{1F64D}\u{1F3FE}", + "\u{1F64D}\u{1F3FF}", + "\u{1F64D}\u200D\u2642\uFE0F", + "\u{1F64D}\u200D\u2642", + "\u{1F64D}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FB}\u200D\u2642", + "\u{1F64D}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FC}\u200D\u2642", + "\u{1F64D}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FD}\u200D\u2642", + "\u{1F64D}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FE}\u200D\u2642", + "\u{1F64D}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FF}\u200D\u2642", + "\u{1F64D}\u200D\u2640\uFE0F", + "\u{1F64D}\u200D\u2640", + "\u{1F64D}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FB}\u200D\u2640", + "\u{1F64D}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FC}\u200D\u2640", + "\u{1F64D}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FD}\u200D\u2640", + "\u{1F64D}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FE}\u200D\u2640", + "\u{1F64D}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FF}\u200D\u2640", + "\u{1F64E}", + "\u{1F64E}\u{1F3FB}", + "\u{1F64E}\u{1F3FC}", + "\u{1F64E}\u{1F3FD}", + "\u{1F64E}\u{1F3FE}", + "\u{1F64E}\u{1F3FF}", + "\u{1F64E}\u200D\u2642\uFE0F", + "\u{1F64E}\u200D\u2642", + "\u{1F64E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FB}\u200D\u2642", + "\u{1F64E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FC}\u200D\u2642", + "\u{1F64E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FD}\u200D\u2642", + "\u{1F64E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FE}\u200D\u2642", + "\u{1F64E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FF}\u200D\u2642", + "\u{1F64E}\u200D\u2640\uFE0F", + "\u{1F64E}\u200D\u2640", + "\u{1F64E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FB}\u200D\u2640", + "\u{1F64E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FC}\u200D\u2640", + "\u{1F64E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FD}\u200D\u2640", + "\u{1F64E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FE}\u200D\u2640", + "\u{1F64E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FF}\u200D\u2640", + "\u{1F645}", + "\u{1F645}\u{1F3FB}", + "\u{1F645}\u{1F3FC}", + "\u{1F645}\u{1F3FD}", + "\u{1F645}\u{1F3FE}", + "\u{1F645}\u{1F3FF}", + "\u{1F645}\u200D\u2642\uFE0F", + "\u{1F645}\u200D\u2642", + "\u{1F645}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FB}\u200D\u2642", + "\u{1F645}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FC}\u200D\u2642", + "\u{1F645}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FD}\u200D\u2642", + "\u{1F645}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FE}\u200D\u2642", + "\u{1F645}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FF}\u200D\u2642", + "\u{1F645}\u200D\u2640\uFE0F", + "\u{1F645}\u200D\u2640", + "\u{1F645}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FB}\u200D\u2640", + "\u{1F645}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FC}\u200D\u2640", + "\u{1F645}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FD}\u200D\u2640", + "\u{1F645}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FE}\u200D\u2640", + "\u{1F645}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FF}\u200D\u2640", + "\u{1F646}", + "\u{1F646}\u{1F3FB}", + "\u{1F646}\u{1F3FC}", + "\u{1F646}\u{1F3FD}", + "\u{1F646}\u{1F3FE}", + "\u{1F646}\u{1F3FF}", + "\u{1F646}\u200D\u2642\uFE0F", + "\u{1F646}\u200D\u2642", + "\u{1F646}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FB}\u200D\u2642", + "\u{1F646}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FC}\u200D\u2642", + "\u{1F646}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FD}\u200D\u2642", + "\u{1F646}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FE}\u200D\u2642", + "\u{1F646}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FF}\u200D\u2642", + "\u{1F646}\u200D\u2640\uFE0F", + "\u{1F646}\u200D\u2640", + "\u{1F646}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FB}\u200D\u2640", + "\u{1F646}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FC}\u200D\u2640", + "\u{1F646}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FD}\u200D\u2640", + "\u{1F646}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FE}\u200D\u2640", + "\u{1F646}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FF}\u200D\u2640", + "\u{1F481}", + "\u{1F481}\u{1F3FB}", + "\u{1F481}\u{1F3FC}", + "\u{1F481}\u{1F3FD}", + "\u{1F481}\u{1F3FE}", + "\u{1F481}\u{1F3FF}", + "\u{1F481}\u200D\u2642\uFE0F", + "\u{1F481}\u200D\u2642", + "\u{1F481}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FB}\u200D\u2642", + "\u{1F481}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FC}\u200D\u2642", + "\u{1F481}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FD}\u200D\u2642", + "\u{1F481}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FE}\u200D\u2642", + "\u{1F481}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FF}\u200D\u2642", + "\u{1F481}\u200D\u2640\uFE0F", + "\u{1F481}\u200D\u2640", + "\u{1F481}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FB}\u200D\u2640", + "\u{1F481}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FC}\u200D\u2640", + "\u{1F481}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FD}\u200D\u2640", + "\u{1F481}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FE}\u200D\u2640", + "\u{1F481}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FF}\u200D\u2640", + "\u{1F64B}", + "\u{1F64B}\u{1F3FB}", + "\u{1F64B}\u{1F3FC}", + "\u{1F64B}\u{1F3FD}", + "\u{1F64B}\u{1F3FE}", + "\u{1F64B}\u{1F3FF}", + "\u{1F64B}\u200D\u2642\uFE0F", + "\u{1F64B}\u200D\u2642", + "\u{1F64B}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FB}\u200D\u2642", + "\u{1F64B}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FC}\u200D\u2642", + "\u{1F64B}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FD}\u200D\u2642", + "\u{1F64B}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FE}\u200D\u2642", + "\u{1F64B}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FF}\u200D\u2642", + "\u{1F64B}\u200D\u2640\uFE0F", + "\u{1F64B}\u200D\u2640", + "\u{1F64B}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FB}\u200D\u2640", + "\u{1F64B}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FC}\u200D\u2640", + "\u{1F64B}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FD}\u200D\u2640", + "\u{1F64B}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FE}\u200D\u2640", + "\u{1F64B}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FF}\u200D\u2640", + "\u{1F9CF}", + "\u{1F9CF}\u{1F3FB}", + "\u{1F9CF}\u{1F3FC}", + "\u{1F9CF}\u{1F3FD}", + "\u{1F9CF}\u{1F3FE}", + "\u{1F9CF}\u{1F3FF}", + "\u{1F9CF}\u200D\u2642\uFE0F", + "\u{1F9CF}\u200D\u2642", + "\u{1F9CF}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FB}\u200D\u2642", + "\u{1F9CF}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FC}\u200D\u2642", + "\u{1F9CF}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FD}\u200D\u2642", + "\u{1F9CF}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FE}\u200D\u2642", + "\u{1F9CF}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FF}\u200D\u2642", + "\u{1F9CF}\u200D\u2640\uFE0F", + "\u{1F9CF}\u200D\u2640", + "\u{1F9CF}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FB}\u200D\u2640", + "\u{1F9CF}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FC}\u200D\u2640", + "\u{1F9CF}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FD}\u200D\u2640", + "\u{1F9CF}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FE}\u200D\u2640", + "\u{1F9CF}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FF}\u200D\u2640", + "\u{1F647}", + "\u{1F647}\u{1F3FB}", + "\u{1F647}\u{1F3FC}", + "\u{1F647}\u{1F3FD}", + "\u{1F647}\u{1F3FE}", + "\u{1F647}\u{1F3FF}", + "\u{1F647}\u200D\u2642\uFE0F", + "\u{1F647}\u200D\u2642", + "\u{1F647}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FB}\u200D\u2642", + "\u{1F647}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FC}\u200D\u2642", + "\u{1F647}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FD}\u200D\u2642", + "\u{1F647}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FE}\u200D\u2642", + "\u{1F647}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FF}\u200D\u2642", + "\u{1F647}\u200D\u2640\uFE0F", + "\u{1F647}\u200D\u2640", + "\u{1F647}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FB}\u200D\u2640", + "\u{1F647}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FC}\u200D\u2640", + "\u{1F647}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FD}\u200D\u2640", + "\u{1F647}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FE}\u200D\u2640", + "\u{1F647}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FF}\u200D\u2640", + "\u{1F926}", + "\u{1F926}\u{1F3FB}", + "\u{1F926}\u{1F3FC}", + "\u{1F926}\u{1F3FD}", + "\u{1F926}\u{1F3FE}", + "\u{1F926}\u{1F3FF}", + "\u{1F926}\u200D\u2642\uFE0F", + "\u{1F926}\u200D\u2642", + "\u{1F926}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FB}\u200D\u2642", + "\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FC}\u200D\u2642", + "\u{1F926}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FD}\u200D\u2642", + "\u{1F926}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FE}\u200D\u2642", + "\u{1F926}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FF}\u200D\u2642", + "\u{1F926}\u200D\u2640\uFE0F", + "\u{1F926}\u200D\u2640", + "\u{1F926}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FB}\u200D\u2640", + "\u{1F926}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FC}\u200D\u2640", + "\u{1F926}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FD}\u200D\u2640", + "\u{1F926}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FE}\u200D\u2640", + "\u{1F926}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FF}\u200D\u2640", + "\u{1F937}", + "\u{1F937}\u{1F3FB}", + "\u{1F937}\u{1F3FC}", + "\u{1F937}\u{1F3FD}", + "\u{1F937}\u{1F3FE}", + "\u{1F937}\u{1F3FF}", + "\u{1F937}\u200D\u2642\uFE0F", + "\u{1F937}\u200D\u2642", + "\u{1F937}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FB}\u200D\u2642", + "\u{1F937}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FC}\u200D\u2642", + "\u{1F937}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FD}\u200D\u2642", + "\u{1F937}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FE}\u200D\u2642", + "\u{1F937}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FF}\u200D\u2642", + "\u{1F937}\u200D\u2640\uFE0F", + "\u{1F937}\u200D\u2640", + "\u{1F937}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FB}\u200D\u2640", + "\u{1F937}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FC}\u200D\u2640", + "\u{1F937}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FD}\u200D\u2640", + "\u{1F937}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FE}\u200D\u2640", + "\u{1F937}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FF}\u200D\u2640", + "\u{1F9D1}\u200D\u2695\uFE0F", + "\u{1F9D1}\u200D\u2695", + "\u{1F9D1}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u2695", + "\u{1F9D1}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u2695", + "\u{1F9D1}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u2695", + "\u{1F9D1}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u2695", + "\u{1F9D1}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u2695", + "\u{1F468}\u200D\u2695\uFE0F", + "\u{1F468}\u200D\u2695", + "\u{1F468}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u2695", + "\u{1F468}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u2695", + "\u{1F468}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u2695", + "\u{1F468}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u2695", + "\u{1F468}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u2695", + "\u{1F469}\u200D\u2695\uFE0F", + "\u{1F469}\u200D\u2695", + "\u{1F469}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u2695", + "\u{1F469}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u2695", + "\u{1F469}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u2695", + "\u{1F469}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u2695", + "\u{1F469}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u2695", + "\u{1F9D1}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F393}", + "\u{1F468}\u200D\u{1F393}", + "\u{1F468}\u{1F3FB}\u200D\u{1F393}", + "\u{1F468}\u{1F3FC}\u200D\u{1F393}", + "\u{1F468}\u{1F3FD}\u200D\u{1F393}", + "\u{1F468}\u{1F3FE}\u200D\u{1F393}", + "\u{1F468}\u{1F3FF}\u200D\u{1F393}", + "\u{1F469}\u200D\u{1F393}", + "\u{1F469}\u{1F3FB}\u200D\u{1F393}", + "\u{1F469}\u{1F3FC}\u200D\u{1F393}", + "\u{1F469}\u{1F3FD}\u200D\u{1F393}", + "\u{1F469}\u{1F3FE}\u200D\u{1F393}", + "\u{1F469}\u{1F3FF}\u200D\u{1F393}", + "\u{1F9D1}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F468}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F469}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F9D1}\u200D\u2696\uFE0F", + "\u{1F9D1}\u200D\u2696", + "\u{1F9D1}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u2696", + "\u{1F9D1}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u2696", + "\u{1F9D1}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u2696", + "\u{1F9D1}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u2696", + "\u{1F9D1}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u2696", + "\u{1F468}\u200D\u2696\uFE0F", + "\u{1F468}\u200D\u2696", + "\u{1F468}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u2696", + "\u{1F468}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u2696", + "\u{1F468}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u2696", + "\u{1F468}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u2696", + "\u{1F468}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u2696", + "\u{1F469}\u200D\u2696\uFE0F", + "\u{1F469}\u200D\u2696", + "\u{1F469}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u2696", + "\u{1F469}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u2696", + "\u{1F469}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u2696", + "\u{1F469}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u2696", + "\u{1F469}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u2696", + "\u{1F9D1}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F468}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F469}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F9D1}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F373}", + "\u{1F468}\u200D\u{1F373}", + "\u{1F468}\u{1F3FB}\u200D\u{1F373}", + "\u{1F468}\u{1F3FC}\u200D\u{1F373}", + "\u{1F468}\u{1F3FD}\u200D\u{1F373}", + "\u{1F468}\u{1F3FE}\u200D\u{1F373}", + "\u{1F468}\u{1F3FF}\u200D\u{1F373}", + "\u{1F469}\u200D\u{1F373}", + "\u{1F469}\u{1F3FB}\u200D\u{1F373}", + "\u{1F469}\u{1F3FC}\u200D\u{1F373}", + "\u{1F469}\u{1F3FD}\u200D\u{1F373}", + "\u{1F469}\u{1F3FE}\u200D\u{1F373}", + "\u{1F469}\u{1F3FF}\u200D\u{1F373}", + "\u{1F9D1}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F527}", + "\u{1F468}\u200D\u{1F527}", + "\u{1F468}\u{1F3FB}\u200D\u{1F527}", + "\u{1F468}\u{1F3FC}\u200D\u{1F527}", + "\u{1F468}\u{1F3FD}\u200D\u{1F527}", + "\u{1F468}\u{1F3FE}\u200D\u{1F527}", + "\u{1F468}\u{1F3FF}\u200D\u{1F527}", + "\u{1F469}\u200D\u{1F527}", + "\u{1F469}\u{1F3FB}\u200D\u{1F527}", + "\u{1F469}\u{1F3FC}\u200D\u{1F527}", + "\u{1F469}\u{1F3FD}\u200D\u{1F527}", + "\u{1F469}\u{1F3FE}\u200D\u{1F527}", + "\u{1F469}\u{1F3FF}\u200D\u{1F527}", + "\u{1F9D1}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F468}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F469}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F9D1}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F468}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F469}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F9D1}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F468}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F469}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F9D1}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F468}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F469}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F9D1}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F468}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F469}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F9D1}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F468}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F469}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F9D1}\u200D\u2708\uFE0F", + "\u{1F9D1}\u200D\u2708", + "\u{1F9D1}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u2708", + "\u{1F9D1}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u2708", + "\u{1F9D1}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u2708", + "\u{1F9D1}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u2708", + "\u{1F9D1}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u2708", + "\u{1F468}\u200D\u2708\uFE0F", + "\u{1F468}\u200D\u2708", + "\u{1F468}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u2708", + "\u{1F468}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u2708", + "\u{1F468}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u2708", + "\u{1F468}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u2708", + "\u{1F468}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u2708", + "\u{1F469}\u200D\u2708\uFE0F", + "\u{1F469}\u200D\u2708", + "\u{1F469}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u2708", + "\u{1F469}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u2708", + "\u{1F469}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u2708", + "\u{1F469}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u2708", + "\u{1F469}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u2708", + "\u{1F9D1}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F680}", + "\u{1F468}\u200D\u{1F680}", + "\u{1F468}\u{1F3FB}\u200D\u{1F680}", + "\u{1F468}\u{1F3FC}\u200D\u{1F680}", + "\u{1F468}\u{1F3FD}\u200D\u{1F680}", + "\u{1F468}\u{1F3FE}\u200D\u{1F680}", + "\u{1F468}\u{1F3FF}\u200D\u{1F680}", + "\u{1F469}\u200D\u{1F680}", + "\u{1F469}\u{1F3FB}\u200D\u{1F680}", + "\u{1F469}\u{1F3FC}\u200D\u{1F680}", + "\u{1F469}\u{1F3FD}\u200D\u{1F680}", + "\u{1F469}\u{1F3FE}\u200D\u{1F680}", + "\u{1F469}\u{1F3FF}\u200D\u{1F680}", + "\u{1F9D1}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F692}", + "\u{1F468}\u200D\u{1F692}", + "\u{1F468}\u{1F3FB}\u200D\u{1F692}", + "\u{1F468}\u{1F3FC}\u200D\u{1F692}", + "\u{1F468}\u{1F3FD}\u200D\u{1F692}", + "\u{1F468}\u{1F3FE}\u200D\u{1F692}", + "\u{1F468}\u{1F3FF}\u200D\u{1F692}", + "\u{1F469}\u200D\u{1F692}", + "\u{1F469}\u{1F3FB}\u200D\u{1F692}", + "\u{1F469}\u{1F3FC}\u200D\u{1F692}", + "\u{1F469}\u{1F3FD}\u200D\u{1F692}", + "\u{1F469}\u{1F3FE}\u200D\u{1F692}", + "\u{1F469}\u{1F3FF}\u200D\u{1F692}", + "\u{1F46E}", + "\u{1F46E}\u{1F3FB}", + "\u{1F46E}\u{1F3FC}", + "\u{1F46E}\u{1F3FD}", + "\u{1F46E}\u{1F3FE}", + "\u{1F46E}\u{1F3FF}", + "\u{1F46E}\u200D\u2642\uFE0F", + "\u{1F46E}\u200D\u2642", + "\u{1F46E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FB}\u200D\u2642", + "\u{1F46E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FC}\u200D\u2642", + "\u{1F46E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FD}\u200D\u2642", + "\u{1F46E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FE}\u200D\u2642", + "\u{1F46E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FF}\u200D\u2642", + "\u{1F46E}\u200D\u2640\uFE0F", + "\u{1F46E}\u200D\u2640", + "\u{1F46E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FB}\u200D\u2640", + "\u{1F46E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FC}\u200D\u2640", + "\u{1F46E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FD}\u200D\u2640", + "\u{1F46E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FE}\u200D\u2640", + "\u{1F46E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FF}\u200D\u2640", + "\u{1F575}\uFE0F", + "\u{1F575}", + "\u{1F575}\u{1F3FB}", + "\u{1F575}\u{1F3FC}", + "\u{1F575}\u{1F3FD}", + "\u{1F575}\u{1F3FE}", + "\u{1F575}\u{1F3FF}", + "\u{1F575}\uFE0F\u200D\u2642\uFE0F", + "\u{1F575}\u200D\u2642\uFE0F", + "\u{1F575}\uFE0F\u200D\u2642", + "\u{1F575}\u200D\u2642", + "\u{1F575}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FB}\u200D\u2642", + "\u{1F575}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FC}\u200D\u2642", + "\u{1F575}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FD}\u200D\u2642", + "\u{1F575}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FE}\u200D\u2642", + "\u{1F575}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FF}\u200D\u2642", + "\u{1F575}\uFE0F\u200D\u2640\uFE0F", + "\u{1F575}\u200D\u2640\uFE0F", + "\u{1F575}\uFE0F\u200D\u2640", + "\u{1F575}\u200D\u2640", + "\u{1F575}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FB}\u200D\u2640", + "\u{1F575}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FC}\u200D\u2640", + "\u{1F575}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FD}\u200D\u2640", + "\u{1F575}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FE}\u200D\u2640", + "\u{1F575}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FF}\u200D\u2640", + "\u{1F482}", + "\u{1F482}\u{1F3FB}", + "\u{1F482}\u{1F3FC}", + "\u{1F482}\u{1F3FD}", + "\u{1F482}\u{1F3FE}", + "\u{1F482}\u{1F3FF}", + "\u{1F482}\u200D\u2642\uFE0F", + "\u{1F482}\u200D\u2642", + "\u{1F482}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FB}\u200D\u2642", + "\u{1F482}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FC}\u200D\u2642", + "\u{1F482}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FD}\u200D\u2642", + "\u{1F482}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FE}\u200D\u2642", + "\u{1F482}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FF}\u200D\u2642", + "\u{1F482}\u200D\u2640\uFE0F", + "\u{1F482}\u200D\u2640", + "\u{1F482}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FB}\u200D\u2640", + "\u{1F482}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FC}\u200D\u2640", + "\u{1F482}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FD}\u200D\u2640", + "\u{1F482}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FE}\u200D\u2640", + "\u{1F482}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FF}\u200D\u2640", + "\u{1F977}", + "\u{1F977}\u{1F3FB}", + "\u{1F977}\u{1F3FC}", + "\u{1F977}\u{1F3FD}", + "\u{1F977}\u{1F3FE}", + "\u{1F977}\u{1F3FF}", + "\u{1F477}", + "\u{1F477}\u{1F3FB}", + "\u{1F477}\u{1F3FC}", + "\u{1F477}\u{1F3FD}", + "\u{1F477}\u{1F3FE}", + "\u{1F477}\u{1F3FF}", + "\u{1F477}\u200D\u2642\uFE0F", + "\u{1F477}\u200D\u2642", + "\u{1F477}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FB}\u200D\u2642", + "\u{1F477}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FC}\u200D\u2642", + "\u{1F477}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FD}\u200D\u2642", + "\u{1F477}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FE}\u200D\u2642", + "\u{1F477}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FF}\u200D\u2642", + "\u{1F477}\u200D\u2640\uFE0F", + "\u{1F477}\u200D\u2640", + "\u{1F477}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FB}\u200D\u2640", + "\u{1F477}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FC}\u200D\u2640", + "\u{1F477}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FD}\u200D\u2640", + "\u{1F477}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FE}\u200D\u2640", + "\u{1F477}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FF}\u200D\u2640", + "\u{1FAC5}", + "\u{1FAC5}\u{1F3FB}", + "\u{1FAC5}\u{1F3FC}", + "\u{1FAC5}\u{1F3FD}", + "\u{1FAC5}\u{1F3FE}", + "\u{1FAC5}\u{1F3FF}", + "\u{1F934}", + "\u{1F934}\u{1F3FB}", + "\u{1F934}\u{1F3FC}", + "\u{1F934}\u{1F3FD}", + "\u{1F934}\u{1F3FE}", + "\u{1F934}\u{1F3FF}", + "\u{1F478}", + "\u{1F478}\u{1F3FB}", + "\u{1F478}\u{1F3FC}", + "\u{1F478}\u{1F3FD}", + "\u{1F478}\u{1F3FE}", + "\u{1F478}\u{1F3FF}", + "\u{1F473}", + "\u{1F473}\u{1F3FB}", + "\u{1F473}\u{1F3FC}", + "\u{1F473}\u{1F3FD}", + "\u{1F473}\u{1F3FE}", + "\u{1F473}\u{1F3FF}", + "\u{1F473}\u200D\u2642\uFE0F", + "\u{1F473}\u200D\u2642", + "\u{1F473}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FB}\u200D\u2642", + "\u{1F473}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FC}\u200D\u2642", + "\u{1F473}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FD}\u200D\u2642", + "\u{1F473}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FE}\u200D\u2642", + "\u{1F473}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FF}\u200D\u2642", + "\u{1F473}\u200D\u2640\uFE0F", + "\u{1F473}\u200D\u2640", + "\u{1F473}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FB}\u200D\u2640", + "\u{1F473}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FC}\u200D\u2640", + "\u{1F473}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FD}\u200D\u2640", + "\u{1F473}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FE}\u200D\u2640", + "\u{1F473}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FF}\u200D\u2640", + "\u{1F472}", + "\u{1F472}\u{1F3FB}", + "\u{1F472}\u{1F3FC}", + "\u{1F472}\u{1F3FD}", + "\u{1F472}\u{1F3FE}", + "\u{1F472}\u{1F3FF}", + "\u{1F9D5}", + "\u{1F9D5}\u{1F3FB}", + "\u{1F9D5}\u{1F3FC}", + "\u{1F9D5}\u{1F3FD}", + "\u{1F9D5}\u{1F3FE}", + "\u{1F9D5}\u{1F3FF}", + "\u{1F935}", + "\u{1F935}\u{1F3FB}", + "\u{1F935}\u{1F3FC}", + "\u{1F935}\u{1F3FD}", + "\u{1F935}\u{1F3FE}", + "\u{1F935}\u{1F3FF}", + "\u{1F935}\u200D\u2642\uFE0F", + "\u{1F935}\u200D\u2642", + "\u{1F935}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FB}\u200D\u2642", + "\u{1F935}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FC}\u200D\u2642", + "\u{1F935}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FD}\u200D\u2642", + "\u{1F935}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FE}\u200D\u2642", + "\u{1F935}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FF}\u200D\u2642", + "\u{1F935}\u200D\u2640\uFE0F", + "\u{1F935}\u200D\u2640", + "\u{1F935}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FB}\u200D\u2640", + "\u{1F935}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FC}\u200D\u2640", + "\u{1F935}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FD}\u200D\u2640", + "\u{1F935}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FE}\u200D\u2640", + "\u{1F935}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FF}\u200D\u2640", + "\u{1F470}", + "\u{1F470}\u{1F3FB}", + "\u{1F470}\u{1F3FC}", + "\u{1F470}\u{1F3FD}", + "\u{1F470}\u{1F3FE}", + "\u{1F470}\u{1F3FF}", + "\u{1F470}\u200D\u2642\uFE0F", + "\u{1F470}\u200D\u2642", + "\u{1F470}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FB}\u200D\u2642", + "\u{1F470}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FC}\u200D\u2642", + "\u{1F470}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FD}\u200D\u2642", + "\u{1F470}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FE}\u200D\u2642", + "\u{1F470}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FF}\u200D\u2642", + "\u{1F470}\u200D\u2640\uFE0F", + "\u{1F470}\u200D\u2640", + "\u{1F470}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FB}\u200D\u2640", + "\u{1F470}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FC}\u200D\u2640", + "\u{1F470}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FD}\u200D\u2640", + "\u{1F470}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FE}\u200D\u2640", + "\u{1F470}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FF}\u200D\u2640", + "\u{1F930}", + "\u{1F930}\u{1F3FB}", + "\u{1F930}\u{1F3FC}", + "\u{1F930}\u{1F3FD}", + "\u{1F930}\u{1F3FE}", + "\u{1F930}\u{1F3FF}", + "\u{1FAC3}", + "\u{1FAC3}\u{1F3FB}", + "\u{1FAC3}\u{1F3FC}", + "\u{1FAC3}\u{1F3FD}", + "\u{1FAC3}\u{1F3FE}", + "\u{1FAC3}\u{1F3FF}", + "\u{1FAC4}", + "\u{1FAC4}\u{1F3FB}", + "\u{1FAC4}\u{1F3FC}", + "\u{1FAC4}\u{1F3FD}", + "\u{1FAC4}\u{1F3FE}", + "\u{1FAC4}\u{1F3FF}", + "\u{1F931}", + "\u{1F931}\u{1F3FB}", + "\u{1F931}\u{1F3FC}", + "\u{1F931}\u{1F3FD}", + "\u{1F931}\u{1F3FE}", + "\u{1F931}\u{1F3FF}", + "\u{1F469}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F468}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F9D1}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F47C}", + "\u{1F47C}\u{1F3FB}", + "\u{1F47C}\u{1F3FC}", + "\u{1F47C}\u{1F3FD}", + "\u{1F47C}\u{1F3FE}", + "\u{1F47C}\u{1F3FF}", + "\u{1F385}", + "\u{1F385}\u{1F3FB}", + "\u{1F385}\u{1F3FC}", + "\u{1F385}\u{1F3FD}", + "\u{1F385}\u{1F3FE}", + "\u{1F385}\u{1F3FF}", + "\u{1F936}", + "\u{1F936}\u{1F3FB}", + "\u{1F936}\u{1F3FC}", + "\u{1F936}\u{1F3FD}", + "\u{1F936}\u{1F3FE}", + "\u{1F936}\u{1F3FF}", + "\u{1F9D1}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F384}", + "\u{1F9B8}", + "\u{1F9B8}\u{1F3FB}", + "\u{1F9B8}\u{1F3FC}", + "\u{1F9B8}\u{1F3FD}", + "\u{1F9B8}\u{1F3FE}", + "\u{1F9B8}\u{1F3FF}", + "\u{1F9B8}\u200D\u2642\uFE0F", + "\u{1F9B8}\u200D\u2642", + "\u{1F9B8}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FB}\u200D\u2642", + "\u{1F9B8}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FC}\u200D\u2642", + "\u{1F9B8}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FD}\u200D\u2642", + "\u{1F9B8}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FE}\u200D\u2642", + "\u{1F9B8}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FF}\u200D\u2642", + "\u{1F9B8}\u200D\u2640\uFE0F", + "\u{1F9B8}\u200D\u2640", + "\u{1F9B8}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FB}\u200D\u2640", + "\u{1F9B8}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FC}\u200D\u2640", + "\u{1F9B8}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FD}\u200D\u2640", + "\u{1F9B8}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FE}\u200D\u2640", + "\u{1F9B8}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FF}\u200D\u2640", + "\u{1F9B9}", + "\u{1F9B9}\u{1F3FB}", + "\u{1F9B9}\u{1F3FC}", + "\u{1F9B9}\u{1F3FD}", + "\u{1F9B9}\u{1F3FE}", + "\u{1F9B9}\u{1F3FF}", + "\u{1F9B9}\u200D\u2642\uFE0F", + "\u{1F9B9}\u200D\u2642", + "\u{1F9B9}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FB}\u200D\u2642", + "\u{1F9B9}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FC}\u200D\u2642", + "\u{1F9B9}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FD}\u200D\u2642", + "\u{1F9B9}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FE}\u200D\u2642", + "\u{1F9B9}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FF}\u200D\u2642", + "\u{1F9B9}\u200D\u2640\uFE0F", + "\u{1F9B9}\u200D\u2640", + "\u{1F9B9}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FB}\u200D\u2640", + "\u{1F9B9}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FC}\u200D\u2640", + "\u{1F9B9}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FD}\u200D\u2640", + "\u{1F9B9}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FE}\u200D\u2640", + "\u{1F9B9}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FF}\u200D\u2640", + "\u{1F9D9}", + "\u{1F9D9}\u{1F3FB}", + "\u{1F9D9}\u{1F3FC}", + "\u{1F9D9}\u{1F3FD}", + "\u{1F9D9}\u{1F3FE}", + "\u{1F9D9}\u{1F3FF}", + "\u{1F9D9}\u200D\u2642\uFE0F", + "\u{1F9D9}\u200D\u2642", + "\u{1F9D9}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FB}\u200D\u2642", + "\u{1F9D9}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FC}\u200D\u2642", + "\u{1F9D9}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FD}\u200D\u2642", + "\u{1F9D9}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FE}\u200D\u2642", + "\u{1F9D9}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FF}\u200D\u2642", + "\u{1F9D9}\u200D\u2640\uFE0F", + "\u{1F9D9}\u200D\u2640", + "\u{1F9D9}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FB}\u200D\u2640", + "\u{1F9D9}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FC}\u200D\u2640", + "\u{1F9D9}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FD}\u200D\u2640", + "\u{1F9D9}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FE}\u200D\u2640", + "\u{1F9D9}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FF}\u200D\u2640", + "\u{1F9DA}", + "\u{1F9DA}\u{1F3FB}", + "\u{1F9DA}\u{1F3FC}", + "\u{1F9DA}\u{1F3FD}", + "\u{1F9DA}\u{1F3FE}", + "\u{1F9DA}\u{1F3FF}", + "\u{1F9DA}\u200D\u2642\uFE0F", + "\u{1F9DA}\u200D\u2642", + "\u{1F9DA}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FB}\u200D\u2642", + "\u{1F9DA}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FC}\u200D\u2642", + "\u{1F9DA}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FD}\u200D\u2642", + "\u{1F9DA}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FE}\u200D\u2642", + "\u{1F9DA}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FF}\u200D\u2642", + "\u{1F9DA}\u200D\u2640\uFE0F", + "\u{1F9DA}\u200D\u2640", + "\u{1F9DA}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FB}\u200D\u2640", + "\u{1F9DA}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FC}\u200D\u2640", + "\u{1F9DA}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FD}\u200D\u2640", + "\u{1F9DA}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FE}\u200D\u2640", + "\u{1F9DA}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FF}\u200D\u2640", + "\u{1F9DB}", + "\u{1F9DB}\u{1F3FB}", + "\u{1F9DB}\u{1F3FC}", + "\u{1F9DB}\u{1F3FD}", + "\u{1F9DB}\u{1F3FE}", + "\u{1F9DB}\u{1F3FF}", + "\u{1F9DB}\u200D\u2642\uFE0F", + "\u{1F9DB}\u200D\u2642", + "\u{1F9DB}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FB}\u200D\u2642", + "\u{1F9DB}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FC}\u200D\u2642", + "\u{1F9DB}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FD}\u200D\u2642", + "\u{1F9DB}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FE}\u200D\u2642", + "\u{1F9DB}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FF}\u200D\u2642", + "\u{1F9DB}\u200D\u2640\uFE0F", + "\u{1F9DB}\u200D\u2640", + "\u{1F9DB}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FB}\u200D\u2640", + "\u{1F9DB}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FC}\u200D\u2640", + "\u{1F9DB}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FD}\u200D\u2640", + "\u{1F9DB}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FE}\u200D\u2640", + "\u{1F9DB}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FF}\u200D\u2640", + "\u{1F9DC}", + "\u{1F9DC}\u{1F3FB}", + "\u{1F9DC}\u{1F3FC}", + "\u{1F9DC}\u{1F3FD}", + "\u{1F9DC}\u{1F3FE}", + "\u{1F9DC}\u{1F3FF}", + "\u{1F9DC}\u200D\u2642\uFE0F", + "\u{1F9DC}\u200D\u2642", + "\u{1F9DC}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FB}\u200D\u2642", + "\u{1F9DC}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FC}\u200D\u2642", + "\u{1F9DC}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FD}\u200D\u2642", + "\u{1F9DC}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FE}\u200D\u2642", + "\u{1F9DC}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FF}\u200D\u2642", + "\u{1F9DC}\u200D\u2640\uFE0F", + "\u{1F9DC}\u200D\u2640", + "\u{1F9DC}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FB}\u200D\u2640", + "\u{1F9DC}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FC}\u200D\u2640", + "\u{1F9DC}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FD}\u200D\u2640", + "\u{1F9DC}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FE}\u200D\u2640", + "\u{1F9DC}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FF}\u200D\u2640", + "\u{1F9DD}", + "\u{1F9DD}\u{1F3FB}", + "\u{1F9DD}\u{1F3FC}", + "\u{1F9DD}\u{1F3FD}", + "\u{1F9DD}\u{1F3FE}", + "\u{1F9DD}\u{1F3FF}", + "\u{1F9DD}\u200D\u2642\uFE0F", + "\u{1F9DD}\u200D\u2642", + "\u{1F9DD}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FB}\u200D\u2642", + "\u{1F9DD}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FC}\u200D\u2642", + "\u{1F9DD}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FD}\u200D\u2642", + "\u{1F9DD}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FE}\u200D\u2642", + "\u{1F9DD}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FF}\u200D\u2642", + "\u{1F9DD}\u200D\u2640\uFE0F", + "\u{1F9DD}\u200D\u2640", + "\u{1F9DD}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FB}\u200D\u2640", + "\u{1F9DD}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FC}\u200D\u2640", + "\u{1F9DD}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FD}\u200D\u2640", + "\u{1F9DD}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FE}\u200D\u2640", + "\u{1F9DD}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FF}\u200D\u2640", + "\u{1F9DE}", + "\u{1F9DE}\u200D\u2642\uFE0F", + "\u{1F9DE}\u200D\u2642", + "\u{1F9DE}\u200D\u2640\uFE0F", + "\u{1F9DE}\u200D\u2640", + "\u{1F9DF}", + "\u{1F9DF}\u200D\u2642\uFE0F", + "\u{1F9DF}\u200D\u2642", + "\u{1F9DF}\u200D\u2640\uFE0F", + "\u{1F9DF}\u200D\u2640", + "\u{1F9CC}", + "\u{1F486}", + "\u{1F486}\u{1F3FB}", + "\u{1F486}\u{1F3FC}", + "\u{1F486}\u{1F3FD}", + "\u{1F486}\u{1F3FE}", + "\u{1F486}\u{1F3FF}", + "\u{1F486}\u200D\u2642\uFE0F", + "\u{1F486}\u200D\u2642", + "\u{1F486}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FB}\u200D\u2642", + "\u{1F486}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FC}\u200D\u2642", + "\u{1F486}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FD}\u200D\u2642", + "\u{1F486}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FE}\u200D\u2642", + "\u{1F486}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FF}\u200D\u2642", + "\u{1F486}\u200D\u2640\uFE0F", + "\u{1F486}\u200D\u2640", + "\u{1F486}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FB}\u200D\u2640", + "\u{1F486}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FC}\u200D\u2640", + "\u{1F486}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FD}\u200D\u2640", + "\u{1F486}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FE}\u200D\u2640", + "\u{1F486}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FF}\u200D\u2640", + "\u{1F487}", + "\u{1F487}\u{1F3FB}", + "\u{1F487}\u{1F3FC}", + "\u{1F487}\u{1F3FD}", + "\u{1F487}\u{1F3FE}", + "\u{1F487}\u{1F3FF}", + "\u{1F487}\u200D\u2642\uFE0F", + "\u{1F487}\u200D\u2642", + "\u{1F487}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FB}\u200D\u2642", + "\u{1F487}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FC}\u200D\u2642", + "\u{1F487}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FD}\u200D\u2642", + "\u{1F487}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FE}\u200D\u2642", + "\u{1F487}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FF}\u200D\u2642", + "\u{1F487}\u200D\u2640\uFE0F", + "\u{1F487}\u200D\u2640", + "\u{1F487}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FB}\u200D\u2640", + "\u{1F487}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FC}\u200D\u2640", + "\u{1F487}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FD}\u200D\u2640", + "\u{1F487}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FE}\u200D\u2640", + "\u{1F487}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FF}\u200D\u2640", + "\u{1F6B6}", + "\u{1F6B6}\u{1F3FB}", + "\u{1F6B6}\u{1F3FC}", + "\u{1F6B6}\u{1F3FD}", + "\u{1F6B6}\u{1F3FE}", + "\u{1F6B6}\u{1F3FF}", + "\u{1F6B6}\u200D\u2642\uFE0F", + "\u{1F6B6}\u200D\u2642", + "\u{1F6B6}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FB}\u200D\u2642", + "\u{1F6B6}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FC}\u200D\u2642", + "\u{1F6B6}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FD}\u200D\u2642", + "\u{1F6B6}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FE}\u200D\u2642", + "\u{1F6B6}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FF}\u200D\u2642", + "\u{1F6B6}\u200D\u2640\uFE0F", + "\u{1F6B6}\u200D\u2640", + "\u{1F6B6}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FB}\u200D\u2640", + "\u{1F6B6}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FC}\u200D\u2640", + "\u{1F6B6}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FD}\u200D\u2640", + "\u{1F6B6}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FE}\u200D\u2640", + "\u{1F6B6}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FF}\u200D\u2640", + "\u{1F9CD}", + "\u{1F9CD}\u{1F3FB}", + "\u{1F9CD}\u{1F3FC}", + "\u{1F9CD}\u{1F3FD}", + "\u{1F9CD}\u{1F3FE}", + "\u{1F9CD}\u{1F3FF}", + "\u{1F9CD}\u200D\u2642\uFE0F", + "\u{1F9CD}\u200D\u2642", + "\u{1F9CD}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FB}\u200D\u2642", + "\u{1F9CD}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FC}\u200D\u2642", + "\u{1F9CD}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FD}\u200D\u2642", + "\u{1F9CD}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FE}\u200D\u2642", + "\u{1F9CD}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FF}\u200D\u2642", + "\u{1F9CD}\u200D\u2640\uFE0F", + "\u{1F9CD}\u200D\u2640", + "\u{1F9CD}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FB}\u200D\u2640", + "\u{1F9CD}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FC}\u200D\u2640", + "\u{1F9CD}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FD}\u200D\u2640", + "\u{1F9CD}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FE}\u200D\u2640", + "\u{1F9CD}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FF}\u200D\u2640", + "\u{1F9CE}", + "\u{1F9CE}\u{1F3FB}", + "\u{1F9CE}\u{1F3FC}", + "\u{1F9CE}\u{1F3FD}", + "\u{1F9CE}\u{1F3FE}", + "\u{1F9CE}\u{1F3FF}", + "\u{1F9CE}\u200D\u2642\uFE0F", + "\u{1F9CE}\u200D\u2642", + "\u{1F9CE}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FB}\u200D\u2642", + "\u{1F9CE}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FC}\u200D\u2642", + "\u{1F9CE}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FD}\u200D\u2642", + "\u{1F9CE}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FE}\u200D\u2642", + "\u{1F9CE}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FF}\u200D\u2642", + "\u{1F9CE}\u200D\u2640\uFE0F", + "\u{1F9CE}\u200D\u2640", + "\u{1F9CE}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FB}\u200D\u2640", + "\u{1F9CE}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FC}\u200D\u2640", + "\u{1F9CE}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FD}\u200D\u2640", + "\u{1F9CE}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FE}\u200D\u2640", + "\u{1F9CE}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FF}\u200D\u2640", + "\u{1F9D1}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F468}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F469}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F9D1}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F468}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F469}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F9D1}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BD}", + "\u{1F468}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9BD}", + "\u{1F469}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9BD}", + "\u{1F3C3}", + "\u{1F3C3}\u{1F3FB}", + "\u{1F3C3}\u{1F3FC}", + "\u{1F3C3}\u{1F3FD}", + "\u{1F3C3}\u{1F3FE}", + "\u{1F3C3}\u{1F3FF}", + "\u{1F3C3}\u200D\u2642\uFE0F", + "\u{1F3C3}\u200D\u2642", + "\u{1F3C3}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FB}\u200D\u2642", + "\u{1F3C3}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FC}\u200D\u2642", + "\u{1F3C3}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FD}\u200D\u2642", + "\u{1F3C3}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FE}\u200D\u2642", + "\u{1F3C3}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FF}\u200D\u2642", + "\u{1F3C3}\u200D\u2640\uFE0F", + "\u{1F3C3}\u200D\u2640", + "\u{1F3C3}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FB}\u200D\u2640", + "\u{1F3C3}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FC}\u200D\u2640", + "\u{1F3C3}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FD}\u200D\u2640", + "\u{1F3C3}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FE}\u200D\u2640", + "\u{1F3C3}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FF}\u200D\u2640", + "\u{1F483}", + "\u{1F483}\u{1F3FB}", + "\u{1F483}\u{1F3FC}", + "\u{1F483}\u{1F3FD}", + "\u{1F483}\u{1F3FE}", + "\u{1F483}\u{1F3FF}", + "\u{1F57A}", + "\u{1F57A}\u{1F3FB}", + "\u{1F57A}\u{1F3FC}", + "\u{1F57A}\u{1F3FD}", + "\u{1F57A}\u{1F3FE}", + "\u{1F57A}\u{1F3FF}", + "\u{1F574}\uFE0F", + "\u{1F574}", + "\u{1F574}\u{1F3FB}", + "\u{1F574}\u{1F3FC}", + "\u{1F574}\u{1F3FD}", + "\u{1F574}\u{1F3FE}", + "\u{1F574}\u{1F3FF}", + "\u{1F46F}", + "\u{1F46F}\u200D\u2642\uFE0F", + "\u{1F46F}\u200D\u2642", + "\u{1F46F}\u200D\u2640\uFE0F", + "\u{1F46F}\u200D\u2640", + "\u{1F9D6}", + "\u{1F9D6}\u{1F3FB}", + "\u{1F9D6}\u{1F3FC}", + "\u{1F9D6}\u{1F3FD}", + "\u{1F9D6}\u{1F3FE}", + "\u{1F9D6}\u{1F3FF}", + "\u{1F9D6}\u200D\u2642\uFE0F", + "\u{1F9D6}\u200D\u2642", + "\u{1F9D6}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FB}\u200D\u2642", + "\u{1F9D6}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FC}\u200D\u2642", + "\u{1F9D6}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FD}\u200D\u2642", + "\u{1F9D6}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FE}\u200D\u2642", + "\u{1F9D6}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FF}\u200D\u2642", + "\u{1F9D6}\u200D\u2640\uFE0F", + "\u{1F9D6}\u200D\u2640", + "\u{1F9D6}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FB}\u200D\u2640", + "\u{1F9D6}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FC}\u200D\u2640", + "\u{1F9D6}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FD}\u200D\u2640", + "\u{1F9D6}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FE}\u200D\u2640", + "\u{1F9D6}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FF}\u200D\u2640", + "\u{1F9D7}", + "\u{1F9D7}\u{1F3FB}", + "\u{1F9D7}\u{1F3FC}", + "\u{1F9D7}\u{1F3FD}", + "\u{1F9D7}\u{1F3FE}", + "\u{1F9D7}\u{1F3FF}", + "\u{1F9D7}\u200D\u2642\uFE0F", + "\u{1F9D7}\u200D\u2642", + "\u{1F9D7}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FB}\u200D\u2642", + "\u{1F9D7}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FC}\u200D\u2642", + "\u{1F9D7}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FD}\u200D\u2642", + "\u{1F9D7}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FE}\u200D\u2642", + "\u{1F9D7}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FF}\u200D\u2642", + "\u{1F9D7}\u200D\u2640\uFE0F", + "\u{1F9D7}\u200D\u2640", + "\u{1F9D7}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FB}\u200D\u2640", + "\u{1F9D7}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FC}\u200D\u2640", + "\u{1F9D7}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FD}\u200D\u2640", + "\u{1F9D7}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FE}\u200D\u2640", + "\u{1F9D7}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FF}\u200D\u2640", + "\u{1F93A}", + "\u{1F3C7}", + "\u{1F3C7}\u{1F3FB}", + "\u{1F3C7}\u{1F3FC}", + "\u{1F3C7}\u{1F3FD}", + "\u{1F3C7}\u{1F3FE}", + "\u{1F3C7}\u{1F3FF}", + "\u26F7\uFE0F", + "\u26F7", + "\u{1F3C2}", + "\u{1F3C2}\u{1F3FB}", + "\u{1F3C2}\u{1F3FC}", + "\u{1F3C2}\u{1F3FD}", + "\u{1F3C2}\u{1F3FE}", + "\u{1F3C2}\u{1F3FF}", + "\u{1F3CC}\uFE0F", + "\u{1F3CC}", + "\u{1F3CC}\u{1F3FB}", + "\u{1F3CC}\u{1F3FC}", + "\u{1F3CC}\u{1F3FD}", + "\u{1F3CC}\u{1F3FE}", + "\u{1F3CC}\u{1F3FF}", + "\u{1F3CC}\uFE0F\u200D\u2642\uFE0F", + "\u{1F3CC}\u200D\u2642\uFE0F", + "\u{1F3CC}\uFE0F\u200D\u2642", + "\u{1F3CC}\u200D\u2642", + "\u{1F3CC}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FB}\u200D\u2642", + "\u{1F3CC}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FC}\u200D\u2642", + "\u{1F3CC}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FD}\u200D\u2642", + "\u{1F3CC}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FE}\u200D\u2642", + "\u{1F3CC}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FF}\u200D\u2642", + "\u{1F3CC}\uFE0F\u200D\u2640\uFE0F", + "\u{1F3CC}\u200D\u2640\uFE0F", + "\u{1F3CC}\uFE0F\u200D\u2640", + "\u{1F3CC}\u200D\u2640", + "\u{1F3CC}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FB}\u200D\u2640", + "\u{1F3CC}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FC}\u200D\u2640", + "\u{1F3CC}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FD}\u200D\u2640", + "\u{1F3CC}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FE}\u200D\u2640", + "\u{1F3CC}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FF}\u200D\u2640", + "\u{1F3C4}", + "\u{1F3C4}\u{1F3FB}", + "\u{1F3C4}\u{1F3FC}", + "\u{1F3C4}\u{1F3FD}", + "\u{1F3C4}\u{1F3FE}", + "\u{1F3C4}\u{1F3FF}", + "\u{1F3C4}\u200D\u2642\uFE0F", + "\u{1F3C4}\u200D\u2642", + "\u{1F3C4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FB}\u200D\u2642", + "\u{1F3C4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FC}\u200D\u2642", + "\u{1F3C4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FD}\u200D\u2642", + "\u{1F3C4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FE}\u200D\u2642", + "\u{1F3C4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FF}\u200D\u2642", + "\u{1F3C4}\u200D\u2640\uFE0F", + "\u{1F3C4}\u200D\u2640", + "\u{1F3C4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FB}\u200D\u2640", + "\u{1F3C4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FC}\u200D\u2640", + "\u{1F3C4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FD}\u200D\u2640", + "\u{1F3C4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FE}\u200D\u2640", + "\u{1F3C4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FF}\u200D\u2640", + "\u{1F6A3}", + "\u{1F6A3}\u{1F3FB}", + "\u{1F6A3}\u{1F3FC}", + "\u{1F6A3}\u{1F3FD}", + "\u{1F6A3}\u{1F3FE}", + "\u{1F6A3}\u{1F3FF}", + "\u{1F6A3}\u200D\u2642\uFE0F", + "\u{1F6A3}\u200D\u2642", + "\u{1F6A3}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FB}\u200D\u2642", + "\u{1F6A3}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FC}\u200D\u2642", + "\u{1F6A3}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FD}\u200D\u2642", + "\u{1F6A3}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FE}\u200D\u2642", + "\u{1F6A3}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FF}\u200D\u2642", + "\u{1F6A3}\u200D\u2640\uFE0F", + "\u{1F6A3}\u200D\u2640", + "\u{1F6A3}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FB}\u200D\u2640", + "\u{1F6A3}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FC}\u200D\u2640", + "\u{1F6A3}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FD}\u200D\u2640", + "\u{1F6A3}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FE}\u200D\u2640", + "\u{1F6A3}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FF}\u200D\u2640", + "\u{1F3CA}", + "\u{1F3CA}\u{1F3FB}", + "\u{1F3CA}\u{1F3FC}", + "\u{1F3CA}\u{1F3FD}", + "\u{1F3CA}\u{1F3FE}", + "\u{1F3CA}\u{1F3FF}", + "\u{1F3CA}\u200D\u2642\uFE0F", + "\u{1F3CA}\u200D\u2642", + "\u{1F3CA}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FB}\u200D\u2642", + "\u{1F3CA}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FC}\u200D\u2642", + "\u{1F3CA}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FD}\u200D\u2642", + "\u{1F3CA}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FE}\u200D\u2642", + "\u{1F3CA}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FF}\u200D\u2642", + "\u{1F3CA}\u200D\u2640\uFE0F", + "\u{1F3CA}\u200D\u2640", + "\u{1F3CA}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FB}\u200D\u2640", + "\u{1F3CA}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FC}\u200D\u2640", + "\u{1F3CA}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FD}\u200D\u2640", + "\u{1F3CA}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FE}\u200D\u2640", + "\u{1F3CA}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FF}\u200D\u2640", + "\u26F9\uFE0F", + "\u26F9", + "\u26F9\u{1F3FB}", + "\u26F9\u{1F3FC}", + "\u26F9\u{1F3FD}", + "\u26F9\u{1F3FE}", + "\u26F9\u{1F3FF}", + "\u26F9\uFE0F\u200D\u2642\uFE0F", + "\u26F9\u200D\u2642\uFE0F", + "\u26F9\uFE0F\u200D\u2642", + "\u26F9\u200D\u2642", + "\u26F9\u{1F3FB}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FB}\u200D\u2642", + "\u26F9\u{1F3FC}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FC}\u200D\u2642", + "\u26F9\u{1F3FD}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FD}\u200D\u2642", + "\u26F9\u{1F3FE}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FE}\u200D\u2642", + "\u26F9\u{1F3FF}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FF}\u200D\u2642", + "\u26F9\uFE0F\u200D\u2640\uFE0F", + "\u26F9\u200D\u2640\uFE0F", + "\u26F9\uFE0F\u200D\u2640", + "\u26F9\u200D\u2640", + "\u26F9\u{1F3FB}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FB}\u200D\u2640", + "\u26F9\u{1F3FC}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FC}\u200D\u2640", + "\u26F9\u{1F3FD}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FD}\u200D\u2640", + "\u26F9\u{1F3FE}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FE}\u200D\u2640", + "\u26F9\u{1F3FF}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FF}\u200D\u2640", + "\u{1F3CB}\uFE0F", + "\u{1F3CB}", + "\u{1F3CB}\u{1F3FB}", + "\u{1F3CB}\u{1F3FC}", + "\u{1F3CB}\u{1F3FD}", + "\u{1F3CB}\u{1F3FE}", + "\u{1F3CB}\u{1F3FF}", + "\u{1F3CB}\uFE0F\u200D\u2642\uFE0F", + "\u{1F3CB}\u200D\u2642\uFE0F", + "\u{1F3CB}\uFE0F\u200D\u2642", + "\u{1F3CB}\u200D\u2642", + "\u{1F3CB}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FB}\u200D\u2642", + "\u{1F3CB}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FC}\u200D\u2642", + "\u{1F3CB}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FD}\u200D\u2642", + "\u{1F3CB}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FE}\u200D\u2642", + "\u{1F3CB}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FF}\u200D\u2642", + "\u{1F3CB}\uFE0F\u200D\u2640\uFE0F", + "\u{1F3CB}\u200D\u2640\uFE0F", + "\u{1F3CB}\uFE0F\u200D\u2640", + "\u{1F3CB}\u200D\u2640", + "\u{1F3CB}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FB}\u200D\u2640", + "\u{1F3CB}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FC}\u200D\u2640", + "\u{1F3CB}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FD}\u200D\u2640", + "\u{1F3CB}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FE}\u200D\u2640", + "\u{1F3CB}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FF}\u200D\u2640", + "\u{1F6B4}", + "\u{1F6B4}\u{1F3FB}", + "\u{1F6B4}\u{1F3FC}", + "\u{1F6B4}\u{1F3FD}", + "\u{1F6B4}\u{1F3FE}", + "\u{1F6B4}\u{1F3FF}", + "\u{1F6B4}\u200D\u2642\uFE0F", + "\u{1F6B4}\u200D\u2642", + "\u{1F6B4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FB}\u200D\u2642", + "\u{1F6B4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FC}\u200D\u2642", + "\u{1F6B4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FD}\u200D\u2642", + "\u{1F6B4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FE}\u200D\u2642", + "\u{1F6B4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FF}\u200D\u2642", + "\u{1F6B4}\u200D\u2640\uFE0F", + "\u{1F6B4}\u200D\u2640", + "\u{1F6B4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FB}\u200D\u2640", + "\u{1F6B4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FC}\u200D\u2640", + "\u{1F6B4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FD}\u200D\u2640", + "\u{1F6B4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FE}\u200D\u2640", + "\u{1F6B4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FF}\u200D\u2640", + "\u{1F6B5}", + "\u{1F6B5}\u{1F3FB}", + "\u{1F6B5}\u{1F3FC}", + "\u{1F6B5}\u{1F3FD}", + "\u{1F6B5}\u{1F3FE}", + "\u{1F6B5}\u{1F3FF}", + "\u{1F6B5}\u200D\u2642\uFE0F", + "\u{1F6B5}\u200D\u2642", + "\u{1F6B5}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FB}\u200D\u2642", + "\u{1F6B5}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FC}\u200D\u2642", + "\u{1F6B5}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FD}\u200D\u2642", + "\u{1F6B5}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FE}\u200D\u2642", + "\u{1F6B5}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FF}\u200D\u2642", + "\u{1F6B5}\u200D\u2640\uFE0F", + "\u{1F6B5}\u200D\u2640", + "\u{1F6B5}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FB}\u200D\u2640", + "\u{1F6B5}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FC}\u200D\u2640", + "\u{1F6B5}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FD}\u200D\u2640", + "\u{1F6B5}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FE}\u200D\u2640", + "\u{1F6B5}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FF}\u200D\u2640", + "\u{1F938}", + "\u{1F938}\u{1F3FB}", + "\u{1F938}\u{1F3FC}", + "\u{1F938}\u{1F3FD}", + "\u{1F938}\u{1F3FE}", + "\u{1F938}\u{1F3FF}", + "\u{1F938}\u200D\u2642\uFE0F", + "\u{1F938}\u200D\u2642", + "\u{1F938}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FB}\u200D\u2642", + "\u{1F938}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FC}\u200D\u2642", + "\u{1F938}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FD}\u200D\u2642", + "\u{1F938}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FE}\u200D\u2642", + "\u{1F938}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FF}\u200D\u2642", + "\u{1F938}\u200D\u2640\uFE0F", + "\u{1F938}\u200D\u2640", + "\u{1F938}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FB}\u200D\u2640", + "\u{1F938}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FC}\u200D\u2640", + "\u{1F938}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FD}\u200D\u2640", + "\u{1F938}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FE}\u200D\u2640", + "\u{1F938}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FF}\u200D\u2640", + "\u{1F93C}", + "\u{1F93C}\u200D\u2642\uFE0F", + "\u{1F93C}\u200D\u2642", + "\u{1F93C}\u200D\u2640\uFE0F", + "\u{1F93C}\u200D\u2640", + "\u{1F93D}", + "\u{1F93D}\u{1F3FB}", + "\u{1F93D}\u{1F3FC}", + "\u{1F93D}\u{1F3FD}", + "\u{1F93D}\u{1F3FE}", + "\u{1F93D}\u{1F3FF}", + "\u{1F93D}\u200D\u2642\uFE0F", + "\u{1F93D}\u200D\u2642", + "\u{1F93D}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FB}\u200D\u2642", + "\u{1F93D}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FC}\u200D\u2642", + "\u{1F93D}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FD}\u200D\u2642", + "\u{1F93D}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FE}\u200D\u2642", + "\u{1F93D}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FF}\u200D\u2642", + "\u{1F93D}\u200D\u2640\uFE0F", + "\u{1F93D}\u200D\u2640", + "\u{1F93D}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FB}\u200D\u2640", + "\u{1F93D}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FC}\u200D\u2640", + "\u{1F93D}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FD}\u200D\u2640", + "\u{1F93D}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FE}\u200D\u2640", + "\u{1F93D}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FF}\u200D\u2640", + "\u{1F93E}", + "\u{1F93E}\u{1F3FB}", + "\u{1F93E}\u{1F3FC}", + "\u{1F93E}\u{1F3FD}", + "\u{1F93E}\u{1F3FE}", + "\u{1F93E}\u{1F3FF}", + "\u{1F93E}\u200D\u2642\uFE0F", + "\u{1F93E}\u200D\u2642", + "\u{1F93E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FB}\u200D\u2642", + "\u{1F93E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FC}\u200D\u2642", + "\u{1F93E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FD}\u200D\u2642", + "\u{1F93E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FE}\u200D\u2642", + "\u{1F93E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FF}\u200D\u2642", + "\u{1F93E}\u200D\u2640\uFE0F", + "\u{1F93E}\u200D\u2640", + "\u{1F93E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FB}\u200D\u2640", + "\u{1F93E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FC}\u200D\u2640", + "\u{1F93E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FD}\u200D\u2640", + "\u{1F93E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FE}\u200D\u2640", + "\u{1F93E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FF}\u200D\u2640", + "\u{1F939}", + "\u{1F939}\u{1F3FB}", + "\u{1F939}\u{1F3FC}", + "\u{1F939}\u{1F3FD}", + "\u{1F939}\u{1F3FE}", + "\u{1F939}\u{1F3FF}", + "\u{1F939}\u200D\u2642\uFE0F", + "\u{1F939}\u200D\u2642", + "\u{1F939}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FB}\u200D\u2642", + "\u{1F939}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FC}\u200D\u2642", + "\u{1F939}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FD}\u200D\u2642", + "\u{1F939}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FE}\u200D\u2642", + "\u{1F939}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FF}\u200D\u2642", + "\u{1F939}\u200D\u2640\uFE0F", + "\u{1F939}\u200D\u2640", + "\u{1F939}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FB}\u200D\u2640", + "\u{1F939}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FC}\u200D\u2640", + "\u{1F939}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FD}\u200D\u2640", + "\u{1F939}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FE}\u200D\u2640", + "\u{1F939}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FF}\u200D\u2640", + "\u{1F9D8}", + "\u{1F9D8}\u{1F3FB}", + "\u{1F9D8}\u{1F3FC}", + "\u{1F9D8}\u{1F3FD}", + "\u{1F9D8}\u{1F3FE}", + "\u{1F9D8}\u{1F3FF}", + "\u{1F9D8}\u200D\u2642\uFE0F", + "\u{1F9D8}\u200D\u2642", + "\u{1F9D8}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FB}\u200D\u2642", + "\u{1F9D8}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FC}\u200D\u2642", + "\u{1F9D8}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FD}\u200D\u2642", + "\u{1F9D8}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FE}\u200D\u2642", + "\u{1F9D8}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FF}\u200D\u2642", + "\u{1F9D8}\u200D\u2640\uFE0F", + "\u{1F9D8}\u200D\u2640", + "\u{1F9D8}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FB}\u200D\u2640", + "\u{1F9D8}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FC}\u200D\u2640", + "\u{1F9D8}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FD}\u200D\u2640", + "\u{1F9D8}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FE}\u200D\u2640", + "\u{1F9D8}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FF}\u200D\u2640", + "\u{1F6C0}", + "\u{1F6C0}\u{1F3FB}", + "\u{1F6C0}\u{1F3FC}", + "\u{1F6C0}\u{1F3FD}", + "\u{1F6C0}\u{1F3FE}", + "\u{1F6C0}\u{1F3FF}", + "\u{1F6CC}", + "\u{1F6CC}\u{1F3FB}", + "\u{1F6CC}\u{1F3FC}", + "\u{1F6CC}\u{1F3FD}", + "\u{1F6CC}\u{1F3FE}", + "\u{1F6CC}\u{1F3FF}", + "\u{1F9D1}\u200D\u{1F91D}\u200D\u{1F9D1}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F46D}", + "\u{1F46D}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F46D}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F46D}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F46D}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F46D}\u{1F3FF}", + "\u{1F46B}", + "\u{1F46B}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F46B}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F46B}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F46B}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F46B}\u{1F3FF}", + "\u{1F46C}", + "\u{1F46C}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F46C}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F46C}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F46C}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F46C}\u{1F3FF}", + "\u{1F48F}", + "\u{1F48F}\u{1F3FB}", + "\u{1F48F}\u{1F3FC}", + "\u{1F48F}\u{1F3FD}", + "\u{1F48F}\u{1F3FE}", + "\u{1F48F}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F469}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}", + "\u{1F469}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F491}", + "\u{1F491}\u{1F3FB}", + "\u{1F491}\u{1F3FC}", + "\u{1F491}\u{1F3FD}", + "\u{1F491}\u{1F3FE}", + "\u{1F491}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F468}", + "\u{1F469}\u200D\u2764\u200D\u{1F468}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\u200D\u{1F468}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u2764\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F469}", + "\u{1F469}\u200D\u2764\u200D\u{1F469}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\u200D\u{1F469}\u{1F3FF}", + "\u{1F46A}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F5E3}\uFE0F", + "\u{1F5E3}", + "\u{1F464}", + "\u{1F465}", + "\u{1FAC2}", + "\u{1F463}", + "\u{1F3FB}", + "\u{1F3FC}", + "\u{1F3FD}", + "\u{1F3FE}", + "\u{1F3FF}", + "\u{1F9B0}", + "\u{1F9B1}", + "\u{1F9B3}", + "\u{1F9B2}", + "\u{1F435}", + "\u{1F412}", + "\u{1F98D}", + "\u{1F9A7}", + "\u{1F436}", + "\u{1F415}", + "\u{1F9AE}", + "\u{1F415}\u200D\u{1F9BA}", + "\u{1F429}", + "\u{1F43A}", + "\u{1F98A}", + "\u{1F99D}", + "\u{1F431}", + "\u{1F408}", + "\u{1F408}\u200D\u2B1B", + "\u{1F981}", + "\u{1F42F}", + "\u{1F405}", + "\u{1F406}", + "\u{1F434}", + "\u{1F40E}", + "\u{1F984}", + "\u{1F993}", + "\u{1F98C}", + "\u{1F9AC}", + "\u{1F42E}", + "\u{1F402}", + "\u{1F403}", + "\u{1F404}", + "\u{1F437}", + "\u{1F416}", + "\u{1F417}", + "\u{1F43D}", + "\u{1F40F}", + "\u{1F411}", + "\u{1F410}", + "\u{1F42A}", + "\u{1F42B}", + "\u{1F999}", + "\u{1F992}", + "\u{1F418}", + "\u{1F9A3}", + "\u{1F98F}", + "\u{1F99B}", + "\u{1F42D}", + "\u{1F401}", + "\u{1F400}", + "\u{1F439}", + "\u{1F430}", + "\u{1F407}", + "\u{1F43F}\uFE0F", + "\u{1F43F}", + "\u{1F9AB}", + "\u{1F994}", + "\u{1F987}", + "\u{1F43B}", + "\u{1F43B}\u200D\u2744\uFE0F", + "\u{1F43B}\u200D\u2744", + "\u{1F428}", + "\u{1F43C}", + "\u{1F9A5}", + "\u{1F9A6}", + "\u{1F9A8}", + "\u{1F998}", + "\u{1F9A1}", + "\u{1F43E}", + "\u{1F983}", + "\u{1F414}", + "\u{1F413}", + "\u{1F423}", + "\u{1F424}", + "\u{1F425}", + "\u{1F426}", + "\u{1F427}", + "\u{1F54A}\uFE0F", + "\u{1F54A}", + "\u{1F985}", + "\u{1F986}", + "\u{1F9A2}", + "\u{1F989}", + "\u{1F9A4}", + "\u{1FAB6}", + "\u{1F9A9}", + "\u{1F99A}", + "\u{1F99C}", + "\u{1F438}", + "\u{1F40A}", + "\u{1F422}", + "\u{1F98E}", + "\u{1F40D}", + "\u{1F432}", + "\u{1F409}", + "\u{1F995}", + "\u{1F996}", + "\u{1F433}", + "\u{1F40B}", + "\u{1F42C}", + "\u{1F9AD}", + "\u{1F41F}", + "\u{1F420}", + "\u{1F421}", + "\u{1F988}", + "\u{1F419}", + "\u{1F41A}", + "\u{1FAB8}", + "\u{1F40C}", + "\u{1F98B}", + "\u{1F41B}", + "\u{1F41C}", + "\u{1F41D}", + "\u{1FAB2}", + "\u{1F41E}", + "\u{1F997}", + "\u{1FAB3}", + "\u{1F577}\uFE0F", + "\u{1F577}", + "\u{1F578}\uFE0F", + "\u{1F578}", + "\u{1F982}", + "\u{1F99F}", + "\u{1FAB0}", + "\u{1FAB1}", + "\u{1F9A0}", + "\u{1F490}", + "\u{1F338}", + "\u{1F4AE}", + "\u{1FAB7}", + "\u{1F3F5}\uFE0F", + "\u{1F3F5}", + "\u{1F339}", + "\u{1F940}", + "\u{1F33A}", + "\u{1F33B}", + "\u{1F33C}", + "\u{1F337}", + "\u{1F331}", + "\u{1FAB4}", + "\u{1F332}", + "\u{1F333}", + "\u{1F334}", + "\u{1F335}", + "\u{1F33E}", + "\u{1F33F}", + "\u2618\uFE0F", + "\u2618", + "\u{1F340}", + "\u{1F341}", + "\u{1F342}", + "\u{1F343}", + "\u{1FAB9}", + "\u{1FABA}", + "\u{1F347}", + "\u{1F348}", + "\u{1F349}", + "\u{1F34A}", + "\u{1F34B}", + "\u{1F34C}", + "\u{1F34D}", + "\u{1F96D}", + "\u{1F34E}", + "\u{1F34F}", + "\u{1F350}", + "\u{1F351}", + "\u{1F352}", + "\u{1F353}", + "\u{1FAD0}", + "\u{1F95D}", + "\u{1F345}", + "\u{1FAD2}", + "\u{1F965}", + "\u{1F951}", + "\u{1F346}", + "\u{1F954}", + "\u{1F955}", + "\u{1F33D}", + "\u{1F336}\uFE0F", + "\u{1F336}", + "\u{1FAD1}", + "\u{1F952}", + "\u{1F96C}", + "\u{1F966}", + "\u{1F9C4}", + "\u{1F9C5}", + "\u{1F344}", + "\u{1F95C}", + "\u{1FAD8}", + "\u{1F330}", + "\u{1F35E}", + "\u{1F950}", + "\u{1F956}", + "\u{1FAD3}", + "\u{1F968}", + "\u{1F96F}", + "\u{1F95E}", + "\u{1F9C7}", + "\u{1F9C0}", + "\u{1F356}", + "\u{1F357}", + "\u{1F969}", + "\u{1F953}", + "\u{1F354}", + "\u{1F35F}", + "\u{1F355}", + "\u{1F32D}", + "\u{1F96A}", + "\u{1F32E}", + "\u{1F32F}", + "\u{1FAD4}", + "\u{1F959}", + "\u{1F9C6}", + "\u{1F95A}", + "\u{1F373}", + "\u{1F958}", + "\u{1F372}", + "\u{1FAD5}", + "\u{1F963}", + "\u{1F957}", + "\u{1F37F}", + "\u{1F9C8}", + "\u{1F9C2}", + "\u{1F96B}", + "\u{1F371}", + "\u{1F358}", + "\u{1F359}", + "\u{1F35A}", + "\u{1F35B}", + "\u{1F35C}", + "\u{1F35D}", + "\u{1F360}", + "\u{1F362}", + "\u{1F363}", + "\u{1F364}", + "\u{1F365}", + "\u{1F96E}", + "\u{1F361}", + "\u{1F95F}", + "\u{1F960}", + "\u{1F961}", + "\u{1F980}", + "\u{1F99E}", + "\u{1F990}", + "\u{1F991}", + "\u{1F9AA}", + "\u{1F366}", + "\u{1F367}", + "\u{1F368}", + "\u{1F369}", + "\u{1F36A}", + "\u{1F382}", + "\u{1F370}", + "\u{1F9C1}", + "\u{1F967}", + "\u{1F36B}", + "\u{1F36C}", + "\u{1F36D}", + "\u{1F36E}", + "\u{1F36F}", + "\u{1F37C}", + "\u{1F95B}", + "\u2615", + "\u{1FAD6}", + "\u{1F375}", + "\u{1F376}", + "\u{1F37E}", + "\u{1F377}", + "\u{1F378}", + "\u{1F379}", + "\u{1F37A}", + "\u{1F37B}", + "\u{1F942}", + "\u{1F943}", + "\u{1FAD7}", + "\u{1F964}", + "\u{1F9CB}", + "\u{1F9C3}", + "\u{1F9C9}", + "\u{1F9CA}", + "\u{1F962}", + "\u{1F37D}\uFE0F", + "\u{1F37D}", + "\u{1F374}", + "\u{1F944}", + "\u{1F52A}", + "\u{1FAD9}", + "\u{1F3FA}", + "\u{1F30D}", + "\u{1F30E}", + "\u{1F30F}", + "\u{1F310}", + "\u{1F5FA}\uFE0F", + "\u{1F5FA}", + "\u{1F5FE}", + "\u{1F9ED}", + "\u{1F3D4}\uFE0F", + "\u{1F3D4}", + "\u26F0\uFE0F", + "\u26F0", + "\u{1F30B}", + "\u{1F5FB}", + "\u{1F3D5}\uFE0F", + "\u{1F3D5}", + "\u{1F3D6}\uFE0F", + "\u{1F3D6}", + "\u{1F3DC}\uFE0F", + "\u{1F3DC}", + "\u{1F3DD}\uFE0F", + "\u{1F3DD}", + "\u{1F3DE}\uFE0F", + "\u{1F3DE}", + "\u{1F3DF}\uFE0F", + "\u{1F3DF}", + "\u{1F3DB}\uFE0F", + "\u{1F3DB}", + "\u{1F3D7}\uFE0F", + "\u{1F3D7}", + "\u{1F9F1}", + "\u{1FAA8}", + "\u{1FAB5}", + "\u{1F6D6}", + "\u{1F3D8}\uFE0F", + "\u{1F3D8}", + "\u{1F3DA}\uFE0F", + "\u{1F3DA}", + "\u{1F3E0}", + "\u{1F3E1}", + "\u{1F3E2}", + "\u{1F3E3}", + "\u{1F3E4}", + "\u{1F3E5}", + "\u{1F3E6}", + "\u{1F3E8}", + "\u{1F3E9}", + "\u{1F3EA}", + "\u{1F3EB}", + "\u{1F3EC}", + "\u{1F3ED}", + "\u{1F3EF}", + "\u{1F3F0}", + "\u{1F492}", + "\u{1F5FC}", + "\u{1F5FD}", + "\u26EA", + "\u{1F54C}", + "\u{1F6D5}", + "\u{1F54D}", + "\u26E9\uFE0F", + "\u26E9", + "\u{1F54B}", + "\u26F2", + "\u26FA", + "\u{1F301}", + "\u{1F303}", + "\u{1F3D9}\uFE0F", + "\u{1F3D9}", + "\u{1F304}", + "\u{1F305}", + "\u{1F306}", + "\u{1F307}", + "\u{1F309}", + "\u2668\uFE0F", + "\u2668", + "\u{1F3A0}", + "\u{1F6DD}", + "\u{1F3A1}", + "\u{1F3A2}", + "\u{1F488}", + "\u{1F3AA}", + "\u{1F682}", + "\u{1F683}", + "\u{1F684}", + "\u{1F685}", + "\u{1F686}", + "\u{1F687}", + "\u{1F688}", + "\u{1F689}", + "\u{1F68A}", + "\u{1F69D}", + "\u{1F69E}", + "\u{1F68B}", + "\u{1F68C}", + "\u{1F68D}", + "\u{1F68E}", + "\u{1F690}", + "\u{1F691}", + "\u{1F692}", + "\u{1F693}", + "\u{1F694}", + "\u{1F695}", + "\u{1F696}", + "\u{1F697}", + "\u{1F698}", + "\u{1F699}", + "\u{1F6FB}", + "\u{1F69A}", + "\u{1F69B}", + "\u{1F69C}", + "\u{1F3CE}\uFE0F", + "\u{1F3CE}", + "\u{1F3CD}\uFE0F", + "\u{1F3CD}", + "\u{1F6F5}", + "\u{1F9BD}", + "\u{1F9BC}", + "\u{1F6FA}", + "\u{1F6B2}", + "\u{1F6F4}", + "\u{1F6F9}", + "\u{1F6FC}", + "\u{1F68F}", + "\u{1F6E3}\uFE0F", + "\u{1F6E3}", + "\u{1F6E4}\uFE0F", + "\u{1F6E4}", + "\u{1F6E2}\uFE0F", + "\u{1F6E2}", + "\u26FD", + "\u{1F6DE}", + "\u{1F6A8}", + "\u{1F6A5}", + "\u{1F6A6}", + "\u{1F6D1}", + "\u{1F6A7}", + "\u2693", + "\u{1F6DF}", + "\u26F5", + "\u{1F6F6}", + "\u{1F6A4}", + "\u{1F6F3}\uFE0F", + "\u{1F6F3}", + "\u26F4\uFE0F", + "\u26F4", + "\u{1F6E5}\uFE0F", + "\u{1F6E5}", + "\u{1F6A2}", + "\u2708\uFE0F", + "\u2708", + "\u{1F6E9}\uFE0F", + "\u{1F6E9}", + "\u{1F6EB}", + "\u{1F6EC}", + "\u{1FA82}", + "\u{1F4BA}", + "\u{1F681}", + "\u{1F69F}", + "\u{1F6A0}", + "\u{1F6A1}", + "\u{1F6F0}\uFE0F", + "\u{1F6F0}", + "\u{1F680}", + "\u{1F6F8}", + "\u{1F6CE}\uFE0F", + "\u{1F6CE}", + "\u{1F9F3}", + "\u231B", + "\u23F3", + "\u231A", + "\u23F0", + "\u23F1\uFE0F", + "\u23F1", + "\u23F2\uFE0F", + "\u23F2", + "\u{1F570}\uFE0F", + "\u{1F570}", + "\u{1F55B}", + "\u{1F567}", + "\u{1F550}", + "\u{1F55C}", + "\u{1F551}", + "\u{1F55D}", + "\u{1F552}", + "\u{1F55E}", + "\u{1F553}", + "\u{1F55F}", + "\u{1F554}", + "\u{1F560}", + "\u{1F555}", + "\u{1F561}", + "\u{1F556}", + "\u{1F562}", + "\u{1F557}", + "\u{1F563}", + "\u{1F558}", + "\u{1F564}", + "\u{1F559}", + "\u{1F565}", + "\u{1F55A}", + "\u{1F566}", + "\u{1F311}", + "\u{1F312}", + "\u{1F313}", + "\u{1F314}", + "\u{1F315}", + "\u{1F316}", + "\u{1F317}", + "\u{1F318}", + "\u{1F319}", + "\u{1F31A}", + "\u{1F31B}", + "\u{1F31C}", + "\u{1F321}\uFE0F", + "\u{1F321}", + "\u2600\uFE0F", + "\u2600", + "\u{1F31D}", + "\u{1F31E}", + "\u{1FA90}", + "\u2B50", + "\u{1F31F}", + "\u{1F320}", + "\u{1F30C}", + "\u2601\uFE0F", + "\u2601", + "\u26C5", + "\u26C8\uFE0F", + "\u26C8", + "\u{1F324}\uFE0F", + "\u{1F324}", + "\u{1F325}\uFE0F", + "\u{1F325}", + "\u{1F326}\uFE0F", + "\u{1F326}", + "\u{1F327}\uFE0F", + "\u{1F327}", + "\u{1F328}\uFE0F", + "\u{1F328}", + "\u{1F329}\uFE0F", + "\u{1F329}", + "\u{1F32A}\uFE0F", + "\u{1F32A}", + "\u{1F32B}\uFE0F", + "\u{1F32B}", + "\u{1F32C}\uFE0F", + "\u{1F32C}", + "\u{1F300}", + "\u{1F308}", + "\u{1F302}", + "\u2602\uFE0F", + "\u2602", + "\u2614", + "\u26F1\uFE0F", + "\u26F1", + "\u26A1", + "\u2744\uFE0F", + "\u2744", + "\u2603\uFE0F", + "\u2603", + "\u26C4", + "\u2604\uFE0F", + "\u2604", + "\u{1F525}", + "\u{1F4A7}", + "\u{1F30A}", + "\u{1F383}", + "\u{1F384}", + "\u{1F386}", + "\u{1F387}", + "\u{1F9E8}", + "\u2728", + "\u{1F388}", + "\u{1F389}", + "\u{1F38A}", + "\u{1F38B}", + "\u{1F38D}", + "\u{1F38E}", + "\u{1F38F}", + "\u{1F390}", + "\u{1F391}", + "\u{1F9E7}", + "\u{1F380}", + "\u{1F381}", + "\u{1F397}\uFE0F", + "\u{1F397}", + "\u{1F39F}\uFE0F", + "\u{1F39F}", + "\u{1F3AB}", + "\u{1F396}\uFE0F", + "\u{1F396}", + "\u{1F3C6}", + "\u{1F3C5}", + "\u{1F947}", + "\u{1F948}", + "\u{1F949}", + "\u26BD", + "\u26BE", + "\u{1F94E}", + "\u{1F3C0}", + "\u{1F3D0}", + "\u{1F3C8}", + "\u{1F3C9}", + "\u{1F3BE}", + "\u{1F94F}", + "\u{1F3B3}", + "\u{1F3CF}", + "\u{1F3D1}", + "\u{1F3D2}", + "\u{1F94D}", + "\u{1F3D3}", + "\u{1F3F8}", + "\u{1F94A}", + "\u{1F94B}", + "\u{1F945}", + "\u26F3", + "\u26F8\uFE0F", + "\u26F8", + "\u{1F3A3}", + "\u{1F93F}", + "\u{1F3BD}", + "\u{1F3BF}", + "\u{1F6F7}", + "\u{1F94C}", + "\u{1F3AF}", + "\u{1FA80}", + "\u{1FA81}", + "\u{1F3B1}", + "\u{1F52E}", + "\u{1FA84}", + "\u{1F9FF}", + "\u{1FAAC}", + "\u{1F3AE}", + "\u{1F579}\uFE0F", + "\u{1F579}", + "\u{1F3B0}", + "\u{1F3B2}", + "\u{1F9E9}", + "\u{1F9F8}", + "\u{1FA85}", + "\u{1FAA9}", + "\u{1FA86}", + "\u2660\uFE0F", + "\u2660", + "\u2665\uFE0F", + "\u2665", + "\u2666\uFE0F", + "\u2666", + "\u2663\uFE0F", + "\u2663", + "\u265F\uFE0F", + "\u265F", + "\u{1F0CF}", + "\u{1F004}", + "\u{1F3B4}", + "\u{1F3AD}", + "\u{1F5BC}\uFE0F", + "\u{1F5BC}", + "\u{1F3A8}", + "\u{1F9F5}", + "\u{1FAA1}", + "\u{1F9F6}", + "\u{1FAA2}", + "\u{1F453}", + "\u{1F576}\uFE0F", + "\u{1F576}", + "\u{1F97D}", + "\u{1F97C}", + "\u{1F9BA}", + "\u{1F454}", + "\u{1F455}", + "\u{1F456}", + "\u{1F9E3}", + "\u{1F9E4}", + "\u{1F9E5}", + "\u{1F9E6}", + "\u{1F457}", + "\u{1F458}", + "\u{1F97B}", + "\u{1FA71}", + "\u{1FA72}", + "\u{1FA73}", + "\u{1F459}", + "\u{1F45A}", + "\u{1F45B}", + "\u{1F45C}", + "\u{1F45D}", + "\u{1F6CD}\uFE0F", + "\u{1F6CD}", + "\u{1F392}", + "\u{1FA74}", + "\u{1F45E}", + "\u{1F45F}", + "\u{1F97E}", + "\u{1F97F}", + "\u{1F460}", + "\u{1F461}", + "\u{1FA70}", + "\u{1F462}", + "\u{1F451}", + "\u{1F452}", + "\u{1F3A9}", + "\u{1F393}", + "\u{1F9E2}", + "\u{1FA96}", + "\u26D1\uFE0F", + "\u26D1", + "\u{1F4FF}", + "\u{1F484}", + "\u{1F48D}", + "\u{1F48E}", + "\u{1F507}", + "\u{1F508}", + "\u{1F509}", + "\u{1F50A}", + "\u{1F4E2}", + "\u{1F4E3}", + "\u{1F4EF}", + "\u{1F514}", + "\u{1F515}", + "\u{1F3BC}", + "\u{1F3B5}", + "\u{1F3B6}", + "\u{1F399}\uFE0F", + "\u{1F399}", + "\u{1F39A}\uFE0F", + "\u{1F39A}", + "\u{1F39B}\uFE0F", + "\u{1F39B}", + "\u{1F3A4}", + "\u{1F3A7}", + "\u{1F4FB}", + "\u{1F3B7}", + "\u{1FA97}", + "\u{1F3B8}", + "\u{1F3B9}", + "\u{1F3BA}", + "\u{1F3BB}", + "\u{1FA95}", + "\u{1F941}", + "\u{1FA98}", + "\u{1F4F1}", + "\u{1F4F2}", + "\u260E\uFE0F", + "\u260E", + "\u{1F4DE}", + "\u{1F4DF}", + "\u{1F4E0}", + "\u{1F50B}", + "\u{1FAAB}", + "\u{1F50C}", + "\u{1F4BB}", + "\u{1F5A5}\uFE0F", + "\u{1F5A5}", + "\u{1F5A8}\uFE0F", + "\u{1F5A8}", + "\u2328\uFE0F", + "\u2328", + "\u{1F5B1}\uFE0F", + "\u{1F5B1}", + "\u{1F5B2}\uFE0F", + "\u{1F5B2}", + "\u{1F4BD}", + "\u{1F4BE}", + "\u{1F4BF}", + "\u{1F4C0}", + "\u{1F9EE}", + "\u{1F3A5}", + "\u{1F39E}\uFE0F", + "\u{1F39E}", + "\u{1F4FD}\uFE0F", + "\u{1F4FD}", + "\u{1F3AC}", + "\u{1F4FA}", + "\u{1F4F7}", + "\u{1F4F8}", + "\u{1F4F9}", + "\u{1F4FC}", + "\u{1F50D}", + "\u{1F50E}", + "\u{1F56F}\uFE0F", + "\u{1F56F}", + "\u{1F4A1}", + "\u{1F526}", + "\u{1F3EE}", + "\u{1FA94}", + "\u{1F4D4}", + "\u{1F4D5}", + "\u{1F4D6}", + "\u{1F4D7}", + "\u{1F4D8}", + "\u{1F4D9}", + "\u{1F4DA}", + "\u{1F4D3}", + "\u{1F4D2}", + "\u{1F4C3}", + "\u{1F4DC}", + "\u{1F4C4}", + "\u{1F4F0}", + "\u{1F5DE}\uFE0F", + "\u{1F5DE}", + "\u{1F4D1}", + "\u{1F516}", + "\u{1F3F7}\uFE0F", + "\u{1F3F7}", + "\u{1F4B0}", + "\u{1FA99}", + "\u{1F4B4}", + "\u{1F4B5}", + "\u{1F4B6}", + "\u{1F4B7}", + "\u{1F4B8}", + "\u{1F4B3}", + "\u{1F9FE}", + "\u{1F4B9}", + "\u2709\uFE0F", + "\u2709", + "\u{1F4E7}", + "\u{1F4E8}", + "\u{1F4E9}", + "\u{1F4E4}", + "\u{1F4E5}", + "\u{1F4E6}", + "\u{1F4EB}", + "\u{1F4EA}", + "\u{1F4EC}", + "\u{1F4ED}", + "\u{1F4EE}", + "\u{1F5F3}\uFE0F", + "\u{1F5F3}", + "\u270F\uFE0F", + "\u270F", + "\u2712\uFE0F", + "\u2712", + "\u{1F58B}\uFE0F", + "\u{1F58B}", + "\u{1F58A}\uFE0F", + "\u{1F58A}", + "\u{1F58C}\uFE0F", + "\u{1F58C}", + "\u{1F58D}\uFE0F", + "\u{1F58D}", + "\u{1F4DD}", + "\u{1F4BC}", + "\u{1F4C1}", + "\u{1F4C2}", + "\u{1F5C2}\uFE0F", + "\u{1F5C2}", + "\u{1F4C5}", + "\u{1F4C6}", + "\u{1F5D2}\uFE0F", + "\u{1F5D2}", + "\u{1F5D3}\uFE0F", + "\u{1F5D3}", + "\u{1F4C7}", + "\u{1F4C8}", + "\u{1F4C9}", + "\u{1F4CA}", + "\u{1F4CB}", + "\u{1F4CC}", + "\u{1F4CD}", + "\u{1F4CE}", + "\u{1F587}\uFE0F", + "\u{1F587}", + "\u{1F4CF}", + "\u{1F4D0}", + "\u2702\uFE0F", + "\u2702", + "\u{1F5C3}\uFE0F", + "\u{1F5C3}", + "\u{1F5C4}\uFE0F", + "\u{1F5C4}", + "\u{1F5D1}\uFE0F", + "\u{1F5D1}", + "\u{1F512}", + "\u{1F513}", + "\u{1F50F}", + "\u{1F510}", + "\u{1F511}", + "\u{1F5DD}\uFE0F", + "\u{1F5DD}", + "\u{1F528}", + "\u{1FA93}", + "\u26CF\uFE0F", + "\u26CF", + "\u2692\uFE0F", + "\u2692", + "\u{1F6E0}\uFE0F", + "\u{1F6E0}", + "\u{1F5E1}\uFE0F", + "\u{1F5E1}", + "\u2694\uFE0F", + "\u2694", + "\u{1F52B}", + "\u{1FA83}", + "\u{1F3F9}", + "\u{1F6E1}\uFE0F", + "\u{1F6E1}", + "\u{1FA9A}", + "\u{1F527}", + "\u{1FA9B}", + "\u{1F529}", + "\u2699\uFE0F", + "\u2699", + "\u{1F5DC}\uFE0F", + "\u{1F5DC}", + "\u2696\uFE0F", + "\u2696", + "\u{1F9AF}", + "\u{1F517}", + "\u26D3\uFE0F", + "\u26D3", + "\u{1FA9D}", + "\u{1F9F0}", + "\u{1F9F2}", + "\u{1FA9C}", + "\u2697\uFE0F", + "\u2697", + "\u{1F9EA}", + "\u{1F9EB}", + "\u{1F9EC}", + "\u{1F52C}", + "\u{1F52D}", + "\u{1F4E1}", + "\u{1F489}", + "\u{1FA78}", + "\u{1F48A}", + "\u{1FA79}", + "\u{1FA7C}", + "\u{1FA7A}", + "\u{1FA7B}", + "\u{1F6AA}", + "\u{1F6D7}", + "\u{1FA9E}", + "\u{1FA9F}", + "\u{1F6CF}\uFE0F", + "\u{1F6CF}", + "\u{1F6CB}\uFE0F", + "\u{1F6CB}", + "\u{1FA91}", + "\u{1F6BD}", + "\u{1FAA0}", + "\u{1F6BF}", + "\u{1F6C1}", + "\u{1FAA4}", + "\u{1FA92}", + "\u{1F9F4}", + "\u{1F9F7}", + "\u{1F9F9}", + "\u{1F9FA}", + "\u{1F9FB}", + "\u{1FAA3}", + "\u{1F9FC}", + "\u{1FAE7}", + "\u{1FAA5}", + "\u{1F9FD}", + "\u{1F9EF}", + "\u{1F6D2}", + "\u{1F6AC}", + "\u26B0\uFE0F", + "\u26B0", + "\u{1FAA6}", + "\u26B1\uFE0F", + "\u26B1", + "\u{1F5FF}", + "\u{1FAA7}", + "\u{1FAAA}", + "\u{1F3E7}", + "\u{1F6AE}", + "\u{1F6B0}", + "\u267F", + "\u{1F6B9}", + "\u{1F6BA}", + "\u{1F6BB}", + "\u{1F6BC}", + "\u{1F6BE}", + "\u{1F6C2}", + "\u{1F6C3}", + "\u{1F6C4}", + "\u{1F6C5}", + "\u26A0\uFE0F", + "\u26A0", + "\u{1F6B8}", + "\u26D4", + "\u{1F6AB}", + "\u{1F6B3}", + "\u{1F6AD}", + "\u{1F6AF}", + "\u{1F6B1}", + "\u{1F6B7}", + "\u{1F4F5}", + "\u{1F51E}", + "\u2622\uFE0F", + "\u2622", + "\u2623\uFE0F", + "\u2623", + "\u2B06\uFE0F", + "\u2B06", + "\u2197\uFE0F", + "\u2197", + "\u27A1\uFE0F", + "\u27A1", + "\u2198\uFE0F", + "\u2198", + "\u2B07\uFE0F", + "\u2B07", + "\u2199\uFE0F", + "\u2199", + "\u2B05\uFE0F", + "\u2B05", + "\u2196\uFE0F", + "\u2196", + "\u2195\uFE0F", + "\u2195", + "\u2194\uFE0F", + "\u2194", + "\u21A9\uFE0F", + "\u21A9", + "\u21AA\uFE0F", + "\u21AA", + "\u2934\uFE0F", + "\u2934", + "\u2935\uFE0F", + "\u2935", + "\u{1F503}", + "\u{1F504}", + "\u{1F519}", + "\u{1F51A}", + "\u{1F51B}", + "\u{1F51C}", + "\u{1F51D}", + "\u{1F6D0}", + "\u269B\uFE0F", + "\u269B", + "\u{1F549}\uFE0F", + "\u{1F549}", + "\u2721\uFE0F", + "\u2721", + "\u2638\uFE0F", + "\u2638", + "\u262F\uFE0F", + "\u262F", + "\u271D\uFE0F", + "\u271D", + "\u2626\uFE0F", + "\u2626", + "\u262A\uFE0F", + "\u262A", + "\u262E\uFE0F", + "\u262E", + "\u{1F54E}", + "\u{1F52F}", + "\u2648", + "\u2649", + "\u264A", + "\u264B", + "\u264C", + "\u264D", + "\u264E", + "\u264F", + "\u2650", + "\u2651", + "\u2652", + "\u2653", + "\u26CE", + "\u{1F500}", + "\u{1F501}", + "\u{1F502}", + "\u25B6\uFE0F", + "\u25B6", + "\u23E9", + "\u23ED\uFE0F", + "\u23ED", + "\u23EF\uFE0F", + "\u23EF", + "\u25C0\uFE0F", + "\u25C0", + "\u23EA", + "\u23EE\uFE0F", + "\u23EE", + "\u{1F53C}", + "\u23EB", + "\u{1F53D}", + "\u23EC", + "\u23F8\uFE0F", + "\u23F8", + "\u23F9\uFE0F", + "\u23F9", + "\u23FA\uFE0F", + "\u23FA", + "\u23CF\uFE0F", + "\u23CF", + "\u{1F3A6}", + "\u{1F505}", + "\u{1F506}", + "\u{1F4F6}", + "\u{1F4F3}", + "\u{1F4F4}", + "\u2640\uFE0F", + "\u2640", + "\u2642\uFE0F", + "\u2642", + "\u26A7\uFE0F", + "\u26A7", + "\u2716\uFE0F", + "\u2716", + "\u2795", + "\u2796", + "\u2797", + "\u{1F7F0}", + "\u267E\uFE0F", + "\u267E", + "\u203C\uFE0F", + "\u203C", + "\u2049\uFE0F", + "\u2049", + "\u2753", + "\u2754", + "\u2755", + "\u2757", + "\u3030\uFE0F", + "\u3030", + "\u{1F4B1}", + "\u{1F4B2}", + "\u2695\uFE0F", + "\u2695", + "\u267B\uFE0F", + "\u267B", + "\u269C\uFE0F", + "\u269C", + "\u{1F531}", + "\u{1F4DB}", + "\u{1F530}", + "\u2B55", + "\u2705", + "\u2611\uFE0F", + "\u2611", + "\u2714\uFE0F", + "\u2714", + "\u274C", + "\u274E", + "\u27B0", + "\u27BF", + "\u303D\uFE0F", + "\u303D", + "\u2733\uFE0F", + "\u2733", + "\u2734\uFE0F", + "\u2734", + "\u2747\uFE0F", + "\u2747", + "\xA9\uFE0F", + "\xA9", + "\xAE\uFE0F", + "\xAE", + "\u2122\uFE0F", + "\u2122", + "#\uFE0F\u20E3", + "#\u20E3", + "*\uFE0F\u20E3", + "*\u20E3", + "0\uFE0F\u20E3", + "0\u20E3", + "1\uFE0F\u20E3", + "1\u20E3", + "2\uFE0F\u20E3", + "2\u20E3", + "3\uFE0F\u20E3", + "3\u20E3", + "4\uFE0F\u20E3", + "4\u20E3", + "5\uFE0F\u20E3", + "5\u20E3", + "6\uFE0F\u20E3", + "6\u20E3", + "7\uFE0F\u20E3", + "7\u20E3", + "8\uFE0F\u20E3", + "8\u20E3", + "9\uFE0F\u20E3", + "9\u20E3", + "\u{1F51F}", + "\u{1F520}", + "\u{1F521}", + "\u{1F522}", + "\u{1F523}", + "\u{1F524}", + "\u{1F170}\uFE0F", + "\u{1F170}", + "\u{1F18E}", + "\u{1F171}\uFE0F", + "\u{1F171}", + "\u{1F191}", + "\u{1F192}", + "\u{1F193}", + "\u2139\uFE0F", + "\u2139", + "\u{1F194}", + "\u24C2\uFE0F", + "\u24C2", + "\u{1F195}", + "\u{1F196}", + "\u{1F17E}\uFE0F", + "\u{1F17E}", + "\u{1F197}", + "\u{1F17F}\uFE0F", + "\u{1F17F}", + "\u{1F198}", + "\u{1F199}", + "\u{1F19A}", + "\u{1F201}", + "\u{1F202}\uFE0F", + "\u{1F202}", + "\u{1F237}\uFE0F", + "\u{1F237}", + "\u{1F236}", + "\u{1F22F}", + "\u{1F250}", + "\u{1F239}", + "\u{1F21A}", + "\u{1F232}", + "\u{1F251}", + "\u{1F238}", + "\u{1F234}", + "\u{1F233}", + "\u3297\uFE0F", + "\u3297", + "\u3299\uFE0F", + "\u3299", + "\u{1F23A}", + "\u{1F235}", + "\u{1F534}", + "\u{1F7E0}", + "\u{1F7E1}", + "\u{1F7E2}", + "\u{1F535}", + "\u{1F7E3}", + "\u{1F7E4}", + "\u26AB", + "\u26AA", + "\u{1F7E5}", + "\u{1F7E7}", + "\u{1F7E8}", + "\u{1F7E9}", + "\u{1F7E6}", + "\u{1F7EA}", + "\u{1F7EB}", + "\u2B1B", + "\u2B1C", + "\u25FC\uFE0F", + "\u25FC", + "\u25FB\uFE0F", + "\u25FB", + "\u25FE", + "\u25FD", + "\u25AA\uFE0F", + "\u25AA", + "\u25AB\uFE0F", + "\u25AB", + "\u{1F536}", + "\u{1F537}", + "\u{1F538}", + "\u{1F539}", + "\u{1F53A}", + "\u{1F53B}", + "\u{1F4A0}", + "\u{1F518}", + "\u{1F533}", + "\u{1F532}", + "\u{1F3C1}", + "\u{1F6A9}", + "\u{1F38C}", + "\u{1F3F4}", + "\u{1F3F3}\uFE0F", + "\u{1F3F3}", + "\u{1F3F3}\uFE0F\u200D\u{1F308}", + "\u{1F3F3}\u200D\u{1F308}", + "\u{1F3F3}\uFE0F\u200D\u26A7\uFE0F", + "\u{1F3F3}\u200D\u26A7\uFE0F", + "\u{1F3F3}\uFE0F\u200D\u26A7", + "\u{1F3F3}\u200D\u26A7", + "\u{1F3F4}\u200D\u2620\uFE0F", + "\u{1F3F4}\u200D\u2620", + "\u{1F1E6}\u{1F1E8}", + "\u{1F1E6}\u{1F1E9}", + "\u{1F1E6}\u{1F1EA}", + "\u{1F1E6}\u{1F1EB}", + "\u{1F1E6}\u{1F1EC}", + "\u{1F1E6}\u{1F1EE}", + "\u{1F1E6}\u{1F1F1}", + "\u{1F1E6}\u{1F1F2}", + "\u{1F1E6}\u{1F1F4}", + "\u{1F1E6}\u{1F1F6}", + "\u{1F1E6}\u{1F1F7}", + "\u{1F1E6}\u{1F1F8}", + "\u{1F1E6}\u{1F1F9}", + "\u{1F1E6}\u{1F1FA}", + "\u{1F1E6}\u{1F1FC}", + "\u{1F1E6}\u{1F1FD}", + "\u{1F1E6}\u{1F1FF}", + "\u{1F1E7}\u{1F1E6}", + "\u{1F1E7}\u{1F1E7}", + "\u{1F1E7}\u{1F1E9}", + "\u{1F1E7}\u{1F1EA}", + "\u{1F1E7}\u{1F1EB}", + "\u{1F1E7}\u{1F1EC}", + "\u{1F1E7}\u{1F1ED}", + "\u{1F1E7}\u{1F1EE}", + "\u{1F1E7}\u{1F1EF}", + "\u{1F1E7}\u{1F1F1}", + "\u{1F1E7}\u{1F1F2}", + "\u{1F1E7}\u{1F1F3}", + "\u{1F1E7}\u{1F1F4}", + "\u{1F1E7}\u{1F1F6}", + "\u{1F1E7}\u{1F1F7}", + "\u{1F1E7}\u{1F1F8}", + "\u{1F1E7}\u{1F1F9}", + "\u{1F1E7}\u{1F1FB}", + "\u{1F1E7}\u{1F1FC}", + "\u{1F1E7}\u{1F1FE}", + "\u{1F1E7}\u{1F1FF}", + "\u{1F1E8}\u{1F1E6}", + "\u{1F1E8}\u{1F1E8}", + "\u{1F1E8}\u{1F1E9}", + "\u{1F1E8}\u{1F1EB}", + "\u{1F1E8}\u{1F1EC}", + "\u{1F1E8}\u{1F1ED}", + "\u{1F1E8}\u{1F1EE}", + "\u{1F1E8}\u{1F1F0}", + "\u{1F1E8}\u{1F1F1}", + "\u{1F1E8}\u{1F1F2}", + "\u{1F1E8}\u{1F1F3}", + "\u{1F1E8}\u{1F1F4}", + "\u{1F1E8}\u{1F1F5}", + "\u{1F1E8}\u{1F1F7}", + "\u{1F1E8}\u{1F1FA}", + "\u{1F1E8}\u{1F1FB}", + "\u{1F1E8}\u{1F1FC}", + "\u{1F1E8}\u{1F1FD}", + "\u{1F1E8}\u{1F1FE}", + "\u{1F1E8}\u{1F1FF}", + "\u{1F1E9}\u{1F1EA}", + "\u{1F1E9}\u{1F1EC}", + "\u{1F1E9}\u{1F1EF}", + "\u{1F1E9}\u{1F1F0}", + "\u{1F1E9}\u{1F1F2}", + "\u{1F1E9}\u{1F1F4}", + "\u{1F1E9}\u{1F1FF}", + "\u{1F1EA}\u{1F1E6}", + "\u{1F1EA}\u{1F1E8}", + "\u{1F1EA}\u{1F1EA}", + "\u{1F1EA}\u{1F1EC}", + "\u{1F1EA}\u{1F1ED}", + "\u{1F1EA}\u{1F1F7}", + "\u{1F1EA}\u{1F1F8}", + "\u{1F1EA}\u{1F1F9}", + "\u{1F1EA}\u{1F1FA}", + "\u{1F1EB}\u{1F1EE}", + "\u{1F1EB}\u{1F1EF}", + "\u{1F1EB}\u{1F1F0}", + "\u{1F1EB}\u{1F1F2}", + "\u{1F1EB}\u{1F1F4}", + "\u{1F1EB}\u{1F1F7}", + "\u{1F1EC}\u{1F1E6}", + "\u{1F1EC}\u{1F1E7}", + "\u{1F1EC}\u{1F1E9}", + "\u{1F1EC}\u{1F1EA}", + "\u{1F1EC}\u{1F1EB}", + "\u{1F1EC}\u{1F1EC}", + "\u{1F1EC}\u{1F1ED}", + "\u{1F1EC}\u{1F1EE}", + "\u{1F1EC}\u{1F1F1}", + "\u{1F1EC}\u{1F1F2}", + "\u{1F1EC}\u{1F1F3}", + "\u{1F1EC}\u{1F1F5}", + "\u{1F1EC}\u{1F1F6}", + "\u{1F1EC}\u{1F1F7}", + "\u{1F1EC}\u{1F1F8}", + "\u{1F1EC}\u{1F1F9}", + "\u{1F1EC}\u{1F1FA}", + "\u{1F1EC}\u{1F1FC}", + "\u{1F1EC}\u{1F1FE}", + "\u{1F1ED}\u{1F1F0}", + "\u{1F1ED}\u{1F1F2}", + "\u{1F1ED}\u{1F1F3}", + "\u{1F1ED}\u{1F1F7}", + "\u{1F1ED}\u{1F1F9}", + "\u{1F1ED}\u{1F1FA}", + "\u{1F1EE}\u{1F1E8}", + "\u{1F1EE}\u{1F1E9}", + "\u{1F1EE}\u{1F1EA}", + "\u{1F1EE}\u{1F1F1}", + "\u{1F1EE}\u{1F1F2}", + "\u{1F1EE}\u{1F1F3}", + "\u{1F1EE}\u{1F1F4}", + "\u{1F1EE}\u{1F1F6}", + "\u{1F1EE}\u{1F1F7}", + "\u{1F1EE}\u{1F1F8}", + "\u{1F1EE}\u{1F1F9}", + "\u{1F1EF}\u{1F1EA}", + "\u{1F1EF}\u{1F1F2}", + "\u{1F1EF}\u{1F1F4}", + "\u{1F1EF}\u{1F1F5}", + "\u{1F1F0}\u{1F1EA}", + "\u{1F1F0}\u{1F1EC}", + "\u{1F1F0}\u{1F1ED}", + "\u{1F1F0}\u{1F1EE}", + "\u{1F1F0}\u{1F1F2}", + "\u{1F1F0}\u{1F1F3}", + "\u{1F1F0}\u{1F1F5}", + "\u{1F1F0}\u{1F1F7}", + "\u{1F1F0}\u{1F1FC}", + "\u{1F1F0}\u{1F1FE}", + "\u{1F1F0}\u{1F1FF}", + "\u{1F1F1}\u{1F1E6}", + "\u{1F1F1}\u{1F1E7}", + "\u{1F1F1}\u{1F1E8}", + "\u{1F1F1}\u{1F1EE}", + "\u{1F1F1}\u{1F1F0}", + "\u{1F1F1}\u{1F1F7}", + "\u{1F1F1}\u{1F1F8}", + "\u{1F1F1}\u{1F1F9}", + "\u{1F1F1}\u{1F1FA}", + "\u{1F1F1}\u{1F1FB}", + "\u{1F1F1}\u{1F1FE}", + "\u{1F1F2}\u{1F1E6}", + "\u{1F1F2}\u{1F1E8}", + "\u{1F1F2}\u{1F1E9}", + "\u{1F1F2}\u{1F1EA}", + "\u{1F1F2}\u{1F1EB}", + "\u{1F1F2}\u{1F1EC}", + "\u{1F1F2}\u{1F1ED}", + "\u{1F1F2}\u{1F1F0}", + "\u{1F1F2}\u{1F1F1}", + "\u{1F1F2}\u{1F1F2}", + "\u{1F1F2}\u{1F1F3}", + "\u{1F1F2}\u{1F1F4}", + "\u{1F1F2}\u{1F1F5}", + "\u{1F1F2}\u{1F1F6}", + "\u{1F1F2}\u{1F1F7}", + "\u{1F1F2}\u{1F1F8}", + "\u{1F1F2}\u{1F1F9}", + "\u{1F1F2}\u{1F1FA}", + "\u{1F1F2}\u{1F1FB}", + "\u{1F1F2}\u{1F1FC}", + "\u{1F1F2}\u{1F1FD}", + "\u{1F1F2}\u{1F1FE}", + "\u{1F1F2}\u{1F1FF}", + "\u{1F1F3}\u{1F1E6}", + "\u{1F1F3}\u{1F1E8}", + "\u{1F1F3}\u{1F1EA}", + "\u{1F1F3}\u{1F1EB}", + "\u{1F1F3}\u{1F1EC}", + "\u{1F1F3}\u{1F1EE}", + "\u{1F1F3}\u{1F1F1}", + "\u{1F1F3}\u{1F1F4}", + "\u{1F1F3}\u{1F1F5}", + "\u{1F1F3}\u{1F1F7}", + "\u{1F1F3}\u{1F1FA}", + "\u{1F1F3}\u{1F1FF}", + "\u{1F1F4}\u{1F1F2}", + "\u{1F1F5}\u{1F1E6}", + "\u{1F1F5}\u{1F1EA}", + "\u{1F1F5}\u{1F1EB}", + "\u{1F1F5}\u{1F1EC}", + "\u{1F1F5}\u{1F1ED}", + "\u{1F1F5}\u{1F1F0}", + "\u{1F1F5}\u{1F1F1}", + "\u{1F1F5}\u{1F1F2}", + "\u{1F1F5}\u{1F1F3}", + "\u{1F1F5}\u{1F1F7}", + "\u{1F1F5}\u{1F1F8}", + "\u{1F1F5}\u{1F1F9}", + "\u{1F1F5}\u{1F1FC}", + "\u{1F1F5}\u{1F1FE}", + "\u{1F1F6}\u{1F1E6}", + "\u{1F1F7}\u{1F1EA}", + "\u{1F1F7}\u{1F1F4}", + "\u{1F1F7}\u{1F1F8}", + "\u{1F1F7}\u{1F1FA}", + "\u{1F1F7}\u{1F1FC}", + "\u{1F1F8}\u{1F1E6}", + "\u{1F1F8}\u{1F1E7}", + "\u{1F1F8}\u{1F1E8}", + "\u{1F1F8}\u{1F1E9}", + "\u{1F1F8}\u{1F1EA}", + "\u{1F1F8}\u{1F1EC}", + "\u{1F1F8}\u{1F1ED}", + "\u{1F1F8}\u{1F1EE}", + "\u{1F1F8}\u{1F1EF}", + "\u{1F1F8}\u{1F1F0}", + "\u{1F1F8}\u{1F1F1}", + "\u{1F1F8}\u{1F1F2}", + "\u{1F1F8}\u{1F1F3}", + "\u{1F1F8}\u{1F1F4}", + "\u{1F1F8}\u{1F1F7}", + "\u{1F1F8}\u{1F1F8}", + "\u{1F1F8}\u{1F1F9}", + "\u{1F1F8}\u{1F1FB}", + "\u{1F1F8}\u{1F1FD}", + "\u{1F1F8}\u{1F1FE}", + "\u{1F1F8}\u{1F1FF}", + "\u{1F1F9}\u{1F1E6}", + "\u{1F1F9}\u{1F1E8}", + "\u{1F1F9}\u{1F1E9}", + "\u{1F1F9}\u{1F1EB}", + "\u{1F1F9}\u{1F1EC}", + "\u{1F1F9}\u{1F1ED}", + "\u{1F1F9}\u{1F1EF}", + "\u{1F1F9}\u{1F1F0}", + "\u{1F1F9}\u{1F1F1}", + "\u{1F1F9}\u{1F1F2}", + "\u{1F1F9}\u{1F1F3}", + "\u{1F1F9}\u{1F1F4}", + "\u{1F1F9}\u{1F1F7}", + "\u{1F1F9}\u{1F1F9}", + "\u{1F1F9}\u{1F1FB}", + "\u{1F1F9}\u{1F1FC}", + "\u{1F1F9}\u{1F1FF}", + "\u{1F1FA}\u{1F1E6}", + "\u{1F1FA}\u{1F1EC}", + "\u{1F1FA}\u{1F1F2}", + "\u{1F1FA}\u{1F1F3}", + "\u{1F1FA}\u{1F1F8}", + "\u{1F1FA}\u{1F1FE}", + "\u{1F1FA}\u{1F1FF}", + "\u{1F1FB}\u{1F1E6}", + "\u{1F1FB}\u{1F1E8}", + "\u{1F1FB}\u{1F1EA}", + "\u{1F1FB}\u{1F1EC}", + "\u{1F1FB}\u{1F1EE}", + "\u{1F1FB}\u{1F1F3}", + "\u{1F1FB}\u{1F1FA}", + "\u{1F1FC}\u{1F1EB}", + "\u{1F1FC}\u{1F1F8}", + "\u{1F1FD}\u{1F1F0}", + "\u{1F1FE}\u{1F1EA}", + "\u{1F1FE}\u{1F1F9}", + "\u{1F1FF}\u{1F1E6}", + "\u{1F1FF}\u{1F1F2}", + "\u{1F1FF}\u{1F1FC}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}" + ], + nonMatchStrings: [ + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}", + "\u{1F9D1}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}", + "\u{1F9D1}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}", + "\u{1F9D1}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}", + "\u{1F9D1}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}", + "\u{1F9D1}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}" + ], +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-CharacterClass.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-CharacterClass.js new file mode 100644 index 000000000000..6eb48998bbd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-CharacterClass.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji` (property of strings) with `[^\p{…}]` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/[^\p{RGI_Emoji}]/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-P.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-P.js new file mode 100644 index 000000000000..ac03bf9560dd --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-P.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji` (property of strings) with `\P{…}` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\P{RGI_Emoji}/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-u.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-u.js new file mode 100644 index 000000000000..b58d3687851a --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-u.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji` (property of strings) with the `u` flag throws an early error. Properties of strings are only supported through the `v` flag. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-patterns-static-semantics-early-errors +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\p{RGI_Emoji}/u; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji.js new file mode 100644 index 000000000000..6d1144e7bd53 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji.js @@ -0,0 +1,3674 @@ +// |reftest| skip -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji` (property of strings) +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes, regexp-v-flag] +includes: [regExpUtils.js] +---*/ + +testPropertyOfStrings({ + regExp: /^\p{RGI_Emoji}+$/v, + expression: "\\p{RGI_Emoji}", + matchStrings: [ + "#\uFE0F\u20E3", + "*\uFE0F\u20E3", + "0\uFE0F\u20E3", + "1\uFE0F\u20E3", + "2\uFE0F\u20E3", + "3\uFE0F\u20E3", + "4\uFE0F\u20E3", + "5\uFE0F\u20E3", + "6\uFE0F\u20E3", + "7\uFE0F\u20E3", + "8\uFE0F\u20E3", + "9\uFE0F\u20E3", + "\xA9\uFE0F", + "\xAE\uFE0F", + "\u203C\uFE0F", + "\u2049\uFE0F", + "\u2122\uFE0F", + "\u2139\uFE0F", + "\u2194\uFE0F", + "\u2195\uFE0F", + "\u2196\uFE0F", + "\u2197\uFE0F", + "\u2198\uFE0F", + "\u2199\uFE0F", + "\u21A9\uFE0F", + "\u21AA\uFE0F", + "\u231A", + "\u231B", + "\u2328\uFE0F", + "\u23CF\uFE0F", + "\u23E9", + "\u23EA", + "\u23EB", + "\u23EC", + "\u23ED\uFE0F", + "\u23EE\uFE0F", + "\u23EF\uFE0F", + "\u23F0", + "\u23F1\uFE0F", + "\u23F2\uFE0F", + "\u23F3", + "\u23F8\uFE0F", + "\u23F9\uFE0F", + "\u23FA\uFE0F", + "\u24C2\uFE0F", + "\u25AA\uFE0F", + "\u25AB\uFE0F", + "\u25B6\uFE0F", + "\u25C0\uFE0F", + "\u25FB\uFE0F", + "\u25FC\uFE0F", + "\u25FD", + "\u25FE", + "\u2600\uFE0F", + "\u2601\uFE0F", + "\u2602\uFE0F", + "\u2603\uFE0F", + "\u2604\uFE0F", + "\u260E\uFE0F", + "\u2611\uFE0F", + "\u2614", + "\u2615", + "\u2618\uFE0F", + "\u261D\u{1F3FB}", + "\u261D\u{1F3FC}", + "\u261D\u{1F3FD}", + "\u261D\u{1F3FE}", + "\u261D\u{1F3FF}", + "\u261D\uFE0F", + "\u2620\uFE0F", + "\u2622\uFE0F", + "\u2623\uFE0F", + "\u2626\uFE0F", + "\u262A\uFE0F", + "\u262E\uFE0F", + "\u262F\uFE0F", + "\u2638\uFE0F", + "\u2639\uFE0F", + "\u263A\uFE0F", + "\u2640\uFE0F", + "\u2642\uFE0F", + "\u2648", + "\u2649", + "\u264A", + "\u264B", + "\u264C", + "\u264D", + "\u264E", + "\u264F", + "\u2650", + "\u2651", + "\u2652", + "\u2653", + "\u265F\uFE0F", + "\u2660\uFE0F", + "\u2663\uFE0F", + "\u2665\uFE0F", + "\u2666\uFE0F", + "\u2668\uFE0F", + "\u267B\uFE0F", + "\u267E\uFE0F", + "\u267F", + "\u2692\uFE0F", + "\u2693", + "\u2694\uFE0F", + "\u2695\uFE0F", + "\u2696\uFE0F", + "\u2697\uFE0F", + "\u2699\uFE0F", + "\u269B\uFE0F", + "\u269C\uFE0F", + "\u26A0\uFE0F", + "\u26A1", + "\u26A7\uFE0F", + "\u26AA", + "\u26AB", + "\u26B0\uFE0F", + "\u26B1\uFE0F", + "\u26BD", + "\u26BE", + "\u26C4", + "\u26C5", + "\u26C8\uFE0F", + "\u26CE", + "\u26CF\uFE0F", + "\u26D1\uFE0F", + "\u26D3\uFE0F", + "\u26D4", + "\u26E9\uFE0F", + "\u26EA", + "\u26F0\uFE0F", + "\u26F1\uFE0F", + "\u26F2", + "\u26F3", + "\u26F4\uFE0F", + "\u26F5", + "\u26F7\uFE0F", + "\u26F8\uFE0F", + "\u26F9\u{1F3FB}", + "\u26F9\u{1F3FB}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FB}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FC}", + "\u26F9\u{1F3FC}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FC}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FD}", + "\u26F9\u{1F3FD}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FD}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FE}", + "\u26F9\u{1F3FE}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FE}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FF}", + "\u26F9\u{1F3FF}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FF}\u200D\u2642\uFE0F", + "\u26F9\uFE0F", + "\u26F9\uFE0F\u200D\u2640\uFE0F", + "\u26F9\uFE0F\u200D\u2642\uFE0F", + "\u26FA", + "\u26FD", + "\u2702\uFE0F", + "\u2705", + "\u2708\uFE0F", + "\u2709\uFE0F", + "\u270A", + "\u270A\u{1F3FB}", + "\u270A\u{1F3FC}", + "\u270A\u{1F3FD}", + "\u270A\u{1F3FE}", + "\u270A\u{1F3FF}", + "\u270B", + "\u270B\u{1F3FB}", + "\u270B\u{1F3FC}", + "\u270B\u{1F3FD}", + "\u270B\u{1F3FE}", + "\u270B\u{1F3FF}", + "\u270C\u{1F3FB}", + "\u270C\u{1F3FC}", + "\u270C\u{1F3FD}", + "\u270C\u{1F3FE}", + "\u270C\u{1F3FF}", + "\u270C\uFE0F", + "\u270D\u{1F3FB}", + "\u270D\u{1F3FC}", + "\u270D\u{1F3FD}", + "\u270D\u{1F3FE}", + "\u270D\u{1F3FF}", + "\u270D\uFE0F", + "\u270F\uFE0F", + "\u2712\uFE0F", + "\u2714\uFE0F", + "\u2716\uFE0F", + "\u271D\uFE0F", + "\u2721\uFE0F", + "\u2728", + "\u2733\uFE0F", + "\u2734\uFE0F", + "\u2744\uFE0F", + "\u2747\uFE0F", + "\u274C", + "\u274E", + "\u2753", + "\u2754", + "\u2755", + "\u2757", + "\u2763\uFE0F", + "\u2764\uFE0F", + "\u2764\uFE0F\u200D\u{1F525}", + "\u2764\uFE0F\u200D\u{1FA79}", + "\u2795", + "\u2796", + "\u2797", + "\u27A1\uFE0F", + "\u27B0", + "\u27BF", + "\u2934\uFE0F", + "\u2935\uFE0F", + "\u2B05\uFE0F", + "\u2B06\uFE0F", + "\u2B07\uFE0F", + "\u2B1B", + "\u2B1C", + "\u2B50", + "\u2B55", + "\u3030\uFE0F", + "\u303D\uFE0F", + "\u3297\uFE0F", + "\u3299\uFE0F", + "\u{1F004}", + "\u{1F0CF}", + "\u{1F170}\uFE0F", + "\u{1F171}\uFE0F", + "\u{1F17E}\uFE0F", + "\u{1F17F}\uFE0F", + "\u{1F18E}", + "\u{1F191}", + "\u{1F192}", + "\u{1F193}", + "\u{1F194}", + "\u{1F195}", + "\u{1F196}", + "\u{1F197}", + "\u{1F198}", + "\u{1F199}", + "\u{1F19A}", + "\u{1F1E6}\u{1F1E8}", + "\u{1F1E6}\u{1F1E9}", + "\u{1F1E6}\u{1F1EA}", + "\u{1F1E6}\u{1F1EB}", + "\u{1F1E6}\u{1F1EC}", + "\u{1F1E6}\u{1F1EE}", + "\u{1F1E6}\u{1F1F1}", + "\u{1F1E6}\u{1F1F2}", + "\u{1F1E6}\u{1F1F4}", + "\u{1F1E6}\u{1F1F6}", + "\u{1F1E6}\u{1F1F7}", + "\u{1F1E6}\u{1F1F8}", + "\u{1F1E6}\u{1F1F9}", + "\u{1F1E6}\u{1F1FA}", + "\u{1F1E6}\u{1F1FC}", + "\u{1F1E6}\u{1F1FD}", + "\u{1F1E6}\u{1F1FF}", + "\u{1F1E7}\u{1F1E6}", + "\u{1F1E7}\u{1F1E7}", + "\u{1F1E7}\u{1F1E9}", + "\u{1F1E7}\u{1F1EA}", + "\u{1F1E7}\u{1F1EB}", + "\u{1F1E7}\u{1F1EC}", + "\u{1F1E7}\u{1F1ED}", + "\u{1F1E7}\u{1F1EE}", + "\u{1F1E7}\u{1F1EF}", + "\u{1F1E7}\u{1F1F1}", + "\u{1F1E7}\u{1F1F2}", + "\u{1F1E7}\u{1F1F3}", + "\u{1F1E7}\u{1F1F4}", + "\u{1F1E7}\u{1F1F6}", + "\u{1F1E7}\u{1F1F7}", + "\u{1F1E7}\u{1F1F8}", + "\u{1F1E7}\u{1F1F9}", + "\u{1F1E7}\u{1F1FB}", + "\u{1F1E7}\u{1F1FC}", + "\u{1F1E7}\u{1F1FE}", + "\u{1F1E7}\u{1F1FF}", + "\u{1F1E8}\u{1F1E6}", + "\u{1F1E8}\u{1F1E8}", + "\u{1F1E8}\u{1F1E9}", + "\u{1F1E8}\u{1F1EB}", + "\u{1F1E8}\u{1F1EC}", + "\u{1F1E8}\u{1F1ED}", + "\u{1F1E8}\u{1F1EE}", + "\u{1F1E8}\u{1F1F0}", + "\u{1F1E8}\u{1F1F1}", + "\u{1F1E8}\u{1F1F2}", + "\u{1F1E8}\u{1F1F3}", + "\u{1F1E8}\u{1F1F4}", + "\u{1F1E8}\u{1F1F5}", + "\u{1F1E8}\u{1F1F7}", + "\u{1F1E8}\u{1F1FA}", + "\u{1F1E8}\u{1F1FB}", + "\u{1F1E8}\u{1F1FC}", + "\u{1F1E8}\u{1F1FD}", + "\u{1F1E8}\u{1F1FE}", + "\u{1F1E8}\u{1F1FF}", + "\u{1F1E9}\u{1F1EA}", + "\u{1F1E9}\u{1F1EC}", + "\u{1F1E9}\u{1F1EF}", + "\u{1F1E9}\u{1F1F0}", + "\u{1F1E9}\u{1F1F2}", + "\u{1F1E9}\u{1F1F4}", + "\u{1F1E9}\u{1F1FF}", + "\u{1F1EA}\u{1F1E6}", + "\u{1F1EA}\u{1F1E8}", + "\u{1F1EA}\u{1F1EA}", + "\u{1F1EA}\u{1F1EC}", + "\u{1F1EA}\u{1F1ED}", + "\u{1F1EA}\u{1F1F7}", + "\u{1F1EA}\u{1F1F8}", + "\u{1F1EA}\u{1F1F9}", + "\u{1F1EA}\u{1F1FA}", + "\u{1F1EB}\u{1F1EE}", + "\u{1F1EB}\u{1F1EF}", + "\u{1F1EB}\u{1F1F0}", + "\u{1F1EB}\u{1F1F2}", + "\u{1F1EB}\u{1F1F4}", + "\u{1F1EB}\u{1F1F7}", + "\u{1F1EC}\u{1F1E6}", + "\u{1F1EC}\u{1F1E7}", + "\u{1F1EC}\u{1F1E9}", + "\u{1F1EC}\u{1F1EA}", + "\u{1F1EC}\u{1F1EB}", + "\u{1F1EC}\u{1F1EC}", + "\u{1F1EC}\u{1F1ED}", + "\u{1F1EC}\u{1F1EE}", + "\u{1F1EC}\u{1F1F1}", + "\u{1F1EC}\u{1F1F2}", + "\u{1F1EC}\u{1F1F3}", + "\u{1F1EC}\u{1F1F5}", + "\u{1F1EC}\u{1F1F6}", + "\u{1F1EC}\u{1F1F7}", + "\u{1F1EC}\u{1F1F8}", + "\u{1F1EC}\u{1F1F9}", + "\u{1F1EC}\u{1F1FA}", + "\u{1F1EC}\u{1F1FC}", + "\u{1F1EC}\u{1F1FE}", + "\u{1F1ED}\u{1F1F0}", + "\u{1F1ED}\u{1F1F2}", + "\u{1F1ED}\u{1F1F3}", + "\u{1F1ED}\u{1F1F7}", + "\u{1F1ED}\u{1F1F9}", + "\u{1F1ED}\u{1F1FA}", + "\u{1F1EE}\u{1F1E8}", + "\u{1F1EE}\u{1F1E9}", + "\u{1F1EE}\u{1F1EA}", + "\u{1F1EE}\u{1F1F1}", + "\u{1F1EE}\u{1F1F2}", + "\u{1F1EE}\u{1F1F3}", + "\u{1F1EE}\u{1F1F4}", + "\u{1F1EE}\u{1F1F6}", + "\u{1F1EE}\u{1F1F7}", + "\u{1F1EE}\u{1F1F8}", + "\u{1F1EE}\u{1F1F9}", + "\u{1F1EF}\u{1F1EA}", + "\u{1F1EF}\u{1F1F2}", + "\u{1F1EF}\u{1F1F4}", + "\u{1F1EF}\u{1F1F5}", + "\u{1F1F0}\u{1F1EA}", + "\u{1F1F0}\u{1F1EC}", + "\u{1F1F0}\u{1F1ED}", + "\u{1F1F0}\u{1F1EE}", + "\u{1F1F0}\u{1F1F2}", + "\u{1F1F0}\u{1F1F3}", + "\u{1F1F0}\u{1F1F5}", + "\u{1F1F0}\u{1F1F7}", + "\u{1F1F0}\u{1F1FC}", + "\u{1F1F0}\u{1F1FE}", + "\u{1F1F0}\u{1F1FF}", + "\u{1F1F1}\u{1F1E6}", + "\u{1F1F1}\u{1F1E7}", + "\u{1F1F1}\u{1F1E8}", + "\u{1F1F1}\u{1F1EE}", + "\u{1F1F1}\u{1F1F0}", + "\u{1F1F1}\u{1F1F7}", + "\u{1F1F1}\u{1F1F8}", + "\u{1F1F1}\u{1F1F9}", + "\u{1F1F1}\u{1F1FA}", + "\u{1F1F1}\u{1F1FB}", + "\u{1F1F1}\u{1F1FE}", + "\u{1F1F2}\u{1F1E6}", + "\u{1F1F2}\u{1F1E8}", + "\u{1F1F2}\u{1F1E9}", + "\u{1F1F2}\u{1F1EA}", + "\u{1F1F2}\u{1F1EB}", + "\u{1F1F2}\u{1F1EC}", + "\u{1F1F2}\u{1F1ED}", + "\u{1F1F2}\u{1F1F0}", + "\u{1F1F2}\u{1F1F1}", + "\u{1F1F2}\u{1F1F2}", + "\u{1F1F2}\u{1F1F3}", + "\u{1F1F2}\u{1F1F4}", + "\u{1F1F2}\u{1F1F5}", + "\u{1F1F2}\u{1F1F6}", + "\u{1F1F2}\u{1F1F7}", + "\u{1F1F2}\u{1F1F8}", + "\u{1F1F2}\u{1F1F9}", + "\u{1F1F2}\u{1F1FA}", + "\u{1F1F2}\u{1F1FB}", + "\u{1F1F2}\u{1F1FC}", + "\u{1F1F2}\u{1F1FD}", + "\u{1F1F2}\u{1F1FE}", + "\u{1F1F2}\u{1F1FF}", + "\u{1F1F3}\u{1F1E6}", + "\u{1F1F3}\u{1F1E8}", + "\u{1F1F3}\u{1F1EA}", + "\u{1F1F3}\u{1F1EB}", + "\u{1F1F3}\u{1F1EC}", + "\u{1F1F3}\u{1F1EE}", + "\u{1F1F3}\u{1F1F1}", + "\u{1F1F3}\u{1F1F4}", + "\u{1F1F3}\u{1F1F5}", + "\u{1F1F3}\u{1F1F7}", + "\u{1F1F3}\u{1F1FA}", + "\u{1F1F3}\u{1F1FF}", + "\u{1F1F4}\u{1F1F2}", + "\u{1F1F5}\u{1F1E6}", + "\u{1F1F5}\u{1F1EA}", + "\u{1F1F5}\u{1F1EB}", + "\u{1F1F5}\u{1F1EC}", + "\u{1F1F5}\u{1F1ED}", + "\u{1F1F5}\u{1F1F0}", + "\u{1F1F5}\u{1F1F1}", + "\u{1F1F5}\u{1F1F2}", + "\u{1F1F5}\u{1F1F3}", + "\u{1F1F5}\u{1F1F7}", + "\u{1F1F5}\u{1F1F8}", + "\u{1F1F5}\u{1F1F9}", + "\u{1F1F5}\u{1F1FC}", + "\u{1F1F5}\u{1F1FE}", + "\u{1F1F6}\u{1F1E6}", + "\u{1F1F7}\u{1F1EA}", + "\u{1F1F7}\u{1F1F4}", + "\u{1F1F7}\u{1F1F8}", + "\u{1F1F7}\u{1F1FA}", + "\u{1F1F7}\u{1F1FC}", + "\u{1F1F8}\u{1F1E6}", + "\u{1F1F8}\u{1F1E7}", + "\u{1F1F8}\u{1F1E8}", + "\u{1F1F8}\u{1F1E9}", + "\u{1F1F8}\u{1F1EA}", + "\u{1F1F8}\u{1F1EC}", + "\u{1F1F8}\u{1F1ED}", + "\u{1F1F8}\u{1F1EE}", + "\u{1F1F8}\u{1F1EF}", + "\u{1F1F8}\u{1F1F0}", + "\u{1F1F8}\u{1F1F1}", + "\u{1F1F8}\u{1F1F2}", + "\u{1F1F8}\u{1F1F3}", + "\u{1F1F8}\u{1F1F4}", + "\u{1F1F8}\u{1F1F7}", + "\u{1F1F8}\u{1F1F8}", + "\u{1F1F8}\u{1F1F9}", + "\u{1F1F8}\u{1F1FB}", + "\u{1F1F8}\u{1F1FD}", + "\u{1F1F8}\u{1F1FE}", + "\u{1F1F8}\u{1F1FF}", + "\u{1F1F9}\u{1F1E6}", + "\u{1F1F9}\u{1F1E8}", + "\u{1F1F9}\u{1F1E9}", + "\u{1F1F9}\u{1F1EB}", + "\u{1F1F9}\u{1F1EC}", + "\u{1F1F9}\u{1F1ED}", + "\u{1F1F9}\u{1F1EF}", + "\u{1F1F9}\u{1F1F0}", + "\u{1F1F9}\u{1F1F1}", + "\u{1F1F9}\u{1F1F2}", + "\u{1F1F9}\u{1F1F3}", + "\u{1F1F9}\u{1F1F4}", + "\u{1F1F9}\u{1F1F7}", + "\u{1F1F9}\u{1F1F9}", + "\u{1F1F9}\u{1F1FB}", + "\u{1F1F9}\u{1F1FC}", + "\u{1F1F9}\u{1F1FF}", + "\u{1F1FA}\u{1F1E6}", + "\u{1F1FA}\u{1F1EC}", + "\u{1F1FA}\u{1F1F2}", + "\u{1F1FA}\u{1F1F3}", + "\u{1F1FA}\u{1F1F8}", + "\u{1F1FA}\u{1F1FE}", + "\u{1F1FA}\u{1F1FF}", + "\u{1F1FB}\u{1F1E6}", + "\u{1F1FB}\u{1F1E8}", + "\u{1F1FB}\u{1F1EA}", + "\u{1F1FB}\u{1F1EC}", + "\u{1F1FB}\u{1F1EE}", + "\u{1F1FB}\u{1F1F3}", + "\u{1F1FB}\u{1F1FA}", + "\u{1F1FC}\u{1F1EB}", + "\u{1F1FC}\u{1F1F8}", + "\u{1F1FD}\u{1F1F0}", + "\u{1F1FE}\u{1F1EA}", + "\u{1F1FE}\u{1F1F9}", + "\u{1F1FF}\u{1F1E6}", + "\u{1F1FF}\u{1F1F2}", + "\u{1F1FF}\u{1F1FC}", + "\u{1F201}", + "\u{1F202}\uFE0F", + "\u{1F21A}", + "\u{1F22F}", + "\u{1F232}", + "\u{1F233}", + "\u{1F234}", + "\u{1F235}", + "\u{1F236}", + "\u{1F237}\uFE0F", + "\u{1F238}", + "\u{1F239}", + "\u{1F23A}", + "\u{1F250}", + "\u{1F251}", + "\u{1F300}", + "\u{1F301}", + "\u{1F302}", + "\u{1F303}", + "\u{1F304}", + "\u{1F305}", + "\u{1F306}", + "\u{1F307}", + "\u{1F308}", + "\u{1F309}", + "\u{1F30A}", + "\u{1F30B}", + "\u{1F30C}", + "\u{1F30D}", + "\u{1F30E}", + "\u{1F30F}", + "\u{1F310}", + "\u{1F311}", + "\u{1F312}", + "\u{1F313}", + "\u{1F314}", + "\u{1F315}", + "\u{1F316}", + "\u{1F317}", + "\u{1F318}", + "\u{1F319}", + "\u{1F31A}", + "\u{1F31B}", + "\u{1F31C}", + "\u{1F31D}", + "\u{1F31E}", + "\u{1F31F}", + "\u{1F320}", + "\u{1F321}\uFE0F", + "\u{1F324}\uFE0F", + "\u{1F325}\uFE0F", + "\u{1F326}\uFE0F", + "\u{1F327}\uFE0F", + "\u{1F328}\uFE0F", + "\u{1F329}\uFE0F", + "\u{1F32A}\uFE0F", + "\u{1F32B}\uFE0F", + "\u{1F32C}\uFE0F", + "\u{1F32D}", + "\u{1F32E}", + "\u{1F32F}", + "\u{1F330}", + "\u{1F331}", + "\u{1F332}", + "\u{1F333}", + "\u{1F334}", + "\u{1F335}", + "\u{1F336}\uFE0F", + "\u{1F337}", + "\u{1F338}", + "\u{1F339}", + "\u{1F33A}", + "\u{1F33B}", + "\u{1F33C}", + "\u{1F33D}", + "\u{1F33E}", + "\u{1F33F}", + "\u{1F340}", + "\u{1F341}", + "\u{1F342}", + "\u{1F343}", + "\u{1F344}", + "\u{1F345}", + "\u{1F346}", + "\u{1F347}", + "\u{1F348}", + "\u{1F349}", + "\u{1F34A}", + "\u{1F34B}", + "\u{1F34C}", + "\u{1F34D}", + "\u{1F34E}", + "\u{1F34F}", + "\u{1F350}", + "\u{1F351}", + "\u{1F352}", + "\u{1F353}", + "\u{1F354}", + "\u{1F355}", + "\u{1F356}", + "\u{1F357}", + "\u{1F358}", + "\u{1F359}", + "\u{1F35A}", + "\u{1F35B}", + "\u{1F35C}", + "\u{1F35D}", + "\u{1F35E}", + "\u{1F35F}", + "\u{1F360}", + "\u{1F361}", + "\u{1F362}", + "\u{1F363}", + "\u{1F364}", + "\u{1F365}", + "\u{1F366}", + "\u{1F367}", + "\u{1F368}", + "\u{1F369}", + "\u{1F36A}", + "\u{1F36B}", + "\u{1F36C}", + "\u{1F36D}", + "\u{1F36E}", + "\u{1F36F}", + "\u{1F370}", + "\u{1F371}", + "\u{1F372}", + "\u{1F373}", + "\u{1F374}", + "\u{1F375}", + "\u{1F376}", + "\u{1F377}", + "\u{1F378}", + "\u{1F379}", + "\u{1F37A}", + "\u{1F37B}", + "\u{1F37C}", + "\u{1F37D}\uFE0F", + "\u{1F37E}", + "\u{1F37F}", + "\u{1F380}", + "\u{1F381}", + "\u{1F382}", + "\u{1F383}", + "\u{1F384}", + "\u{1F385}", + "\u{1F385}\u{1F3FB}", + "\u{1F385}\u{1F3FC}", + "\u{1F385}\u{1F3FD}", + "\u{1F385}\u{1F3FE}", + "\u{1F385}\u{1F3FF}", + "\u{1F386}", + "\u{1F387}", + "\u{1F388}", + "\u{1F389}", + "\u{1F38A}", + "\u{1F38B}", + "\u{1F38C}", + "\u{1F38D}", + "\u{1F38E}", + "\u{1F38F}", + "\u{1F390}", + "\u{1F391}", + "\u{1F392}", + "\u{1F393}", + "\u{1F396}\uFE0F", + "\u{1F397}\uFE0F", + "\u{1F399}\uFE0F", + "\u{1F39A}\uFE0F", + "\u{1F39B}\uFE0F", + "\u{1F39E}\uFE0F", + "\u{1F39F}\uFE0F", + "\u{1F3A0}", + "\u{1F3A1}", + "\u{1F3A2}", + "\u{1F3A3}", + "\u{1F3A4}", + "\u{1F3A5}", + "\u{1F3A6}", + "\u{1F3A7}", + "\u{1F3A8}", + "\u{1F3A9}", + "\u{1F3AA}", + "\u{1F3AB}", + "\u{1F3AC}", + "\u{1F3AD}", + "\u{1F3AE}", + "\u{1F3AF}", + "\u{1F3B0}", + "\u{1F3B1}", + "\u{1F3B2}", + "\u{1F3B3}", + "\u{1F3B4}", + "\u{1F3B5}", + "\u{1F3B6}", + "\u{1F3B7}", + "\u{1F3B8}", + "\u{1F3B9}", + "\u{1F3BA}", + "\u{1F3BB}", + "\u{1F3BC}", + "\u{1F3BD}", + "\u{1F3BE}", + "\u{1F3BF}", + "\u{1F3C0}", + "\u{1F3C1}", + "\u{1F3C2}", + "\u{1F3C2}\u{1F3FB}", + "\u{1F3C2}\u{1F3FC}", + "\u{1F3C2}\u{1F3FD}", + "\u{1F3C2}\u{1F3FE}", + "\u{1F3C2}\u{1F3FF}", + "\u{1F3C3}", + "\u{1F3C3}\u200D\u2640\uFE0F", + "\u{1F3C3}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FB}", + "\u{1F3C3}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FC}", + "\u{1F3C3}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FD}", + "\u{1F3C3}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FE}", + "\u{1F3C3}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FF}", + "\u{1F3C3}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3C4}", + "\u{1F3C4}\u200D\u2640\uFE0F", + "\u{1F3C4}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FB}", + "\u{1F3C4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FC}", + "\u{1F3C4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FD}", + "\u{1F3C4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FE}", + "\u{1F3C4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FF}", + "\u{1F3C4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3C5}", + "\u{1F3C6}", + "\u{1F3C7}", + "\u{1F3C7}\u{1F3FB}", + "\u{1F3C7}\u{1F3FC}", + "\u{1F3C7}\u{1F3FD}", + "\u{1F3C7}\u{1F3FE}", + "\u{1F3C7}\u{1F3FF}", + "\u{1F3C8}", + "\u{1F3C9}", + "\u{1F3CA}", + "\u{1F3CA}\u200D\u2640\uFE0F", + "\u{1F3CA}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FB}", + "\u{1F3CA}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FC}", + "\u{1F3CA}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FD}", + "\u{1F3CA}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FE}", + "\u{1F3CA}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FF}", + "\u{1F3CA}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FB}", + "\u{1F3CB}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FC}", + "\u{1F3CB}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FD}", + "\u{1F3CB}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FE}", + "\u{1F3CB}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FF}", + "\u{1F3CB}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CB}\uFE0F", + "\u{1F3CB}\uFE0F\u200D\u2640\uFE0F", + "\u{1F3CB}\uFE0F\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FB}", + "\u{1F3CC}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FC}", + "\u{1F3CC}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FD}", + "\u{1F3CC}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FE}", + "\u{1F3CC}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FF}", + "\u{1F3CC}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CC}\uFE0F", + "\u{1F3CC}\uFE0F\u200D\u2640\uFE0F", + "\u{1F3CC}\uFE0F\u200D\u2642\uFE0F", + "\u{1F3CD}\uFE0F", + "\u{1F3CE}\uFE0F", + "\u{1F3CF}", + "\u{1F3D0}", + "\u{1F3D1}", + "\u{1F3D2}", + "\u{1F3D3}", + "\u{1F3D4}\uFE0F", + "\u{1F3D5}\uFE0F", + "\u{1F3D6}\uFE0F", + "\u{1F3D7}\uFE0F", + "\u{1F3D8}\uFE0F", + "\u{1F3D9}\uFE0F", + "\u{1F3DA}\uFE0F", + "\u{1F3DB}\uFE0F", + "\u{1F3DC}\uFE0F", + "\u{1F3DD}\uFE0F", + "\u{1F3DE}\uFE0F", + "\u{1F3DF}\uFE0F", + "\u{1F3E0}", + "\u{1F3E1}", + "\u{1F3E2}", + "\u{1F3E3}", + "\u{1F3E4}", + "\u{1F3E5}", + "\u{1F3E6}", + "\u{1F3E7}", + "\u{1F3E8}", + "\u{1F3E9}", + "\u{1F3EA}", + "\u{1F3EB}", + "\u{1F3EC}", + "\u{1F3ED}", + "\u{1F3EE}", + "\u{1F3EF}", + "\u{1F3F0}", + "\u{1F3F3}\uFE0F", + "\u{1F3F3}\uFE0F\u200D\u26A7\uFE0F", + "\u{1F3F3}\uFE0F\u200D\u{1F308}", + "\u{1F3F4}", + "\u{1F3F4}\u200D\u2620\uFE0F", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}", + "\u{1F3F5}\uFE0F", + "\u{1F3F7}\uFE0F", + "\u{1F3F8}", + "\u{1F3F9}", + "\u{1F3FA}", + "\u{1F3FB}", + "\u{1F3FC}", + "\u{1F3FD}", + "\u{1F3FE}", + "\u{1F3FF}", + "\u{1F400}", + "\u{1F401}", + "\u{1F402}", + "\u{1F403}", + "\u{1F404}", + "\u{1F405}", + "\u{1F406}", + "\u{1F407}", + "\u{1F408}", + "\u{1F408}\u200D\u2B1B", + "\u{1F409}", + "\u{1F40A}", + "\u{1F40B}", + "\u{1F40C}", + "\u{1F40D}", + "\u{1F40E}", + "\u{1F40F}", + "\u{1F410}", + "\u{1F411}", + "\u{1F412}", + "\u{1F413}", + "\u{1F414}", + "\u{1F415}", + "\u{1F415}\u200D\u{1F9BA}", + "\u{1F416}", + "\u{1F417}", + "\u{1F418}", + "\u{1F419}", + "\u{1F41A}", + "\u{1F41B}", + "\u{1F41C}", + "\u{1F41D}", + "\u{1F41E}", + "\u{1F41F}", + "\u{1F420}", + "\u{1F421}", + "\u{1F422}", + "\u{1F423}", + "\u{1F424}", + "\u{1F425}", + "\u{1F426}", + "\u{1F427}", + "\u{1F428}", + "\u{1F429}", + "\u{1F42A}", + "\u{1F42B}", + "\u{1F42C}", + "\u{1F42D}", + "\u{1F42E}", + "\u{1F42F}", + "\u{1F430}", + "\u{1F431}", + "\u{1F432}", + "\u{1F433}", + "\u{1F434}", + "\u{1F435}", + "\u{1F436}", + "\u{1F437}", + "\u{1F438}", + "\u{1F439}", + "\u{1F43A}", + "\u{1F43B}", + "\u{1F43B}\u200D\u2744\uFE0F", + "\u{1F43C}", + "\u{1F43D}", + "\u{1F43E}", + "\u{1F43F}\uFE0F", + "\u{1F440}", + "\u{1F441}\uFE0F", + "\u{1F441}\uFE0F\u200D\u{1F5E8}\uFE0F", + "\u{1F442}", + "\u{1F442}\u{1F3FB}", + "\u{1F442}\u{1F3FC}", + "\u{1F442}\u{1F3FD}", + "\u{1F442}\u{1F3FE}", + "\u{1F442}\u{1F3FF}", + "\u{1F443}", + "\u{1F443}\u{1F3FB}", + "\u{1F443}\u{1F3FC}", + "\u{1F443}\u{1F3FD}", + "\u{1F443}\u{1F3FE}", + "\u{1F443}\u{1F3FF}", + "\u{1F444}", + "\u{1F445}", + "\u{1F446}", + "\u{1F446}\u{1F3FB}", + "\u{1F446}\u{1F3FC}", + "\u{1F446}\u{1F3FD}", + "\u{1F446}\u{1F3FE}", + "\u{1F446}\u{1F3FF}", + "\u{1F447}", + "\u{1F447}\u{1F3FB}", + "\u{1F447}\u{1F3FC}", + "\u{1F447}\u{1F3FD}", + "\u{1F447}\u{1F3FE}", + "\u{1F447}\u{1F3FF}", + "\u{1F448}", + "\u{1F448}\u{1F3FB}", + "\u{1F448}\u{1F3FC}", + "\u{1F448}\u{1F3FD}", + "\u{1F448}\u{1F3FE}", + "\u{1F448}\u{1F3FF}", + "\u{1F449}", + "\u{1F449}\u{1F3FB}", + "\u{1F449}\u{1F3FC}", + "\u{1F449}\u{1F3FD}", + "\u{1F449}\u{1F3FE}", + "\u{1F449}\u{1F3FF}", + "\u{1F44A}", + "\u{1F44A}\u{1F3FB}", + "\u{1F44A}\u{1F3FC}", + "\u{1F44A}\u{1F3FD}", + "\u{1F44A}\u{1F3FE}", + "\u{1F44A}\u{1F3FF}", + "\u{1F44B}", + "\u{1F44B}\u{1F3FB}", + "\u{1F44B}\u{1F3FC}", + "\u{1F44B}\u{1F3FD}", + "\u{1F44B}\u{1F3FE}", + "\u{1F44B}\u{1F3FF}", + "\u{1F44C}", + "\u{1F44C}\u{1F3FB}", + "\u{1F44C}\u{1F3FC}", + "\u{1F44C}\u{1F3FD}", + "\u{1F44C}\u{1F3FE}", + "\u{1F44C}\u{1F3FF}", + "\u{1F44D}", + "\u{1F44D}\u{1F3FB}", + "\u{1F44D}\u{1F3FC}", + "\u{1F44D}\u{1F3FD}", + "\u{1F44D}\u{1F3FE}", + "\u{1F44D}\u{1F3FF}", + "\u{1F44E}", + "\u{1F44E}\u{1F3FB}", + "\u{1F44E}\u{1F3FC}", + "\u{1F44E}\u{1F3FD}", + "\u{1F44E}\u{1F3FE}", + "\u{1F44E}\u{1F3FF}", + "\u{1F44F}", + "\u{1F44F}\u{1F3FB}", + "\u{1F44F}\u{1F3FC}", + "\u{1F44F}\u{1F3FD}", + "\u{1F44F}\u{1F3FE}", + "\u{1F44F}\u{1F3FF}", + "\u{1F450}", + "\u{1F450}\u{1F3FB}", + "\u{1F450}\u{1F3FC}", + "\u{1F450}\u{1F3FD}", + "\u{1F450}\u{1F3FE}", + "\u{1F450}\u{1F3FF}", + "\u{1F451}", + "\u{1F452}", + "\u{1F453}", + "\u{1F454}", + "\u{1F455}", + "\u{1F456}", + "\u{1F457}", + "\u{1F458}", + "\u{1F459}", + "\u{1F45A}", + "\u{1F45B}", + "\u{1F45C}", + "\u{1F45D}", + "\u{1F45E}", + "\u{1F45F}", + "\u{1F460}", + "\u{1F461}", + "\u{1F462}", + "\u{1F463}", + "\u{1F464}", + "\u{1F465}", + "\u{1F466}", + "\u{1F466}\u{1F3FB}", + "\u{1F466}\u{1F3FC}", + "\u{1F466}\u{1F3FD}", + "\u{1F466}\u{1F3FE}", + "\u{1F466}\u{1F3FF}", + "\u{1F467}", + "\u{1F467}\u{1F3FB}", + "\u{1F467}\u{1F3FC}", + "\u{1F467}\u{1F3FD}", + "\u{1F467}\u{1F3FE}", + "\u{1F467}\u{1F3FF}", + "\u{1F468}", + "\u{1F468}\u200D\u2695\uFE0F", + "\u{1F468}\u200D\u2696\uFE0F", + "\u{1F468}\u200D\u2708\uFE0F", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u{1F33E}", + "\u{1F468}\u200D\u{1F373}", + "\u{1F468}\u200D\u{1F37C}", + "\u{1F468}\u200D\u{1F393}", + "\u{1F468}\u200D\u{1F3A4}", + "\u{1F468}\u200D\u{1F3A8}", + "\u{1F468}\u200D\u{1F3EB}", + "\u{1F468}\u200D\u{1F3ED}", + "\u{1F468}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F4BB}", + "\u{1F468}\u200D\u{1F4BC}", + "\u{1F468}\u200D\u{1F527}", + "\u{1F468}\u200D\u{1F52C}", + "\u{1F468}\u200D\u{1F680}", + "\u{1F468}\u200D\u{1F692}", + "\u{1F468}\u200D\u{1F9AF}", + "\u{1F468}\u200D\u{1F9B0}", + "\u{1F468}\u200D\u{1F9B1}", + "\u{1F468}\u200D\u{1F9B2}", + "\u{1F468}\u200D\u{1F9B3}", + "\u{1F468}\u200D\u{1F9BC}", + "\u{1F468}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FB}\u200D\u{1F373}", + "\u{1F468}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FB}\u200D\u{1F393}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F527}", + "\u{1F468}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FB}\u200D\u{1F680}", + "\u{1F468}\u{1F3FB}\u200D\u{1F692}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FC}\u200D\u{1F373}", + "\u{1F468}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FC}\u200D\u{1F393}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FC}\u200D\u{1F527}", + "\u{1F468}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FC}\u200D\u{1F680}", + "\u{1F468}\u{1F3FC}\u200D\u{1F692}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FD}\u200D\u{1F373}", + "\u{1F468}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FD}\u200D\u{1F393}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FD}\u200D\u{1F527}", + "\u{1F468}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FD}\u200D\u{1F680}", + "\u{1F468}\u{1F3FD}\u200D\u{1F692}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FE}\u200D\u{1F373}", + "\u{1F468}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FE}\u200D\u{1F393}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F527}", + "\u{1F468}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FE}\u200D\u{1F680}", + "\u{1F468}\u{1F3FE}\u200D\u{1F692}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FF}\u200D\u{1F373}", + "\u{1F468}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FF}\u200D\u{1F393}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F527}", + "\u{1F468}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FF}\u200D\u{1F680}", + "\u{1F468}\u{1F3FF}\u200D\u{1F692}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9BD}", + "\u{1F469}", + "\u{1F469}\u200D\u2695\uFE0F", + "\u{1F469}\u200D\u2696\uFE0F", + "\u{1F469}\u200D\u2708\uFE0F", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F468}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F469}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}", + "\u{1F469}\u200D\u{1F33E}", + "\u{1F469}\u200D\u{1F373}", + "\u{1F469}\u200D\u{1F37C}", + "\u{1F469}\u200D\u{1F393}", + "\u{1F469}\u200D\u{1F3A4}", + "\u{1F469}\u200D\u{1F3A8}", + "\u{1F469}\u200D\u{1F3EB}", + "\u{1F469}\u200D\u{1F3ED}", + "\u{1F469}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F4BB}", + "\u{1F469}\u200D\u{1F4BC}", + "\u{1F469}\u200D\u{1F527}", + "\u{1F469}\u200D\u{1F52C}", + "\u{1F469}\u200D\u{1F680}", + "\u{1F469}\u200D\u{1F692}", + "\u{1F469}\u200D\u{1F9AF}", + "\u{1F469}\u200D\u{1F9B0}", + "\u{1F469}\u200D\u{1F9B1}", + "\u{1F469}\u200D\u{1F9B2}", + "\u{1F469}\u200D\u{1F9B3}", + "\u{1F469}\u200D\u{1F9BC}", + "\u{1F469}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FB}\u200D\u{1F373}", + "\u{1F469}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FB}\u200D\u{1F393}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F527}", + "\u{1F469}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FB}\u200D\u{1F680}", + "\u{1F469}\u{1F3FB}\u200D\u{1F692}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FC}\u200D\u{1F373}", + "\u{1F469}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FC}\u200D\u{1F393}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FC}\u200D\u{1F527}", + "\u{1F469}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FC}\u200D\u{1F680}", + "\u{1F469}\u{1F3FC}\u200D\u{1F692}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FD}\u200D\u{1F373}", + "\u{1F469}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FD}\u200D\u{1F393}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F527}", + "\u{1F469}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FD}\u200D\u{1F680}", + "\u{1F469}\u{1F3FD}\u200D\u{1F692}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FE}\u200D\u{1F373}", + "\u{1F469}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FE}\u200D\u{1F393}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F527}", + "\u{1F469}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FE}\u200D\u{1F680}", + "\u{1F469}\u{1F3FE}\u200D\u{1F692}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FF}\u200D\u{1F373}", + "\u{1F469}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FF}\u200D\u{1F393}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F527}", + "\u{1F469}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FF}\u200D\u{1F680}", + "\u{1F469}\u{1F3FF}\u200D\u{1F692}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9BD}", + "\u{1F46A}", + "\u{1F46B}", + "\u{1F46B}\u{1F3FB}", + "\u{1F46B}\u{1F3FC}", + "\u{1F46B}\u{1F3FD}", + "\u{1F46B}\u{1F3FE}", + "\u{1F46B}\u{1F3FF}", + "\u{1F46C}", + "\u{1F46C}\u{1F3FB}", + "\u{1F46C}\u{1F3FC}", + "\u{1F46C}\u{1F3FD}", + "\u{1F46C}\u{1F3FE}", + "\u{1F46C}\u{1F3FF}", + "\u{1F46D}", + "\u{1F46D}\u{1F3FB}", + "\u{1F46D}\u{1F3FC}", + "\u{1F46D}\u{1F3FD}", + "\u{1F46D}\u{1F3FE}", + "\u{1F46D}\u{1F3FF}", + "\u{1F46E}", + "\u{1F46E}\u200D\u2640\uFE0F", + "\u{1F46E}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FB}", + "\u{1F46E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FC}", + "\u{1F46E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FD}", + "\u{1F46E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FE}", + "\u{1F46E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FF}", + "\u{1F46E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F46F}", + "\u{1F46F}\u200D\u2640\uFE0F", + "\u{1F46F}\u200D\u2642\uFE0F", + "\u{1F470}", + "\u{1F470}\u200D\u2640\uFE0F", + "\u{1F470}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FB}", + "\u{1F470}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FC}", + "\u{1F470}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FD}", + "\u{1F470}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FE}", + "\u{1F470}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FF}", + "\u{1F470}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F471}", + "\u{1F471}\u200D\u2640\uFE0F", + "\u{1F471}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FB}", + "\u{1F471}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FC}", + "\u{1F471}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FD}", + "\u{1F471}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FE}", + "\u{1F471}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FF}", + "\u{1F471}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F472}", + "\u{1F472}\u{1F3FB}", + "\u{1F472}\u{1F3FC}", + "\u{1F472}\u{1F3FD}", + "\u{1F472}\u{1F3FE}", + "\u{1F472}\u{1F3FF}", + "\u{1F473}", + "\u{1F473}\u200D\u2640\uFE0F", + "\u{1F473}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FB}", + "\u{1F473}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FC}", + "\u{1F473}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FD}", + "\u{1F473}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FE}", + "\u{1F473}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FF}", + "\u{1F473}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F474}", + "\u{1F474}\u{1F3FB}", + "\u{1F474}\u{1F3FC}", + "\u{1F474}\u{1F3FD}", + "\u{1F474}\u{1F3FE}", + "\u{1F474}\u{1F3FF}", + "\u{1F475}", + "\u{1F475}\u{1F3FB}", + "\u{1F475}\u{1F3FC}", + "\u{1F475}\u{1F3FD}", + "\u{1F475}\u{1F3FE}", + "\u{1F475}\u{1F3FF}", + "\u{1F476}", + "\u{1F476}\u{1F3FB}", + "\u{1F476}\u{1F3FC}", + "\u{1F476}\u{1F3FD}", + "\u{1F476}\u{1F3FE}", + "\u{1F476}\u{1F3FF}", + "\u{1F477}", + "\u{1F477}\u200D\u2640\uFE0F", + "\u{1F477}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FB}", + "\u{1F477}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FC}", + "\u{1F477}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FD}", + "\u{1F477}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FE}", + "\u{1F477}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FF}", + "\u{1F477}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F478}", + "\u{1F478}\u{1F3FB}", + "\u{1F478}\u{1F3FC}", + "\u{1F478}\u{1F3FD}", + "\u{1F478}\u{1F3FE}", + "\u{1F478}\u{1F3FF}", + "\u{1F479}", + "\u{1F47A}", + "\u{1F47B}", + "\u{1F47C}", + "\u{1F47C}\u{1F3FB}", + "\u{1F47C}\u{1F3FC}", + "\u{1F47C}\u{1F3FD}", + "\u{1F47C}\u{1F3FE}", + "\u{1F47C}\u{1F3FF}", + "\u{1F47D}", + "\u{1F47E}", + "\u{1F47F}", + "\u{1F480}", + "\u{1F481}", + "\u{1F481}\u200D\u2640\uFE0F", + "\u{1F481}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FB}", + "\u{1F481}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FC}", + "\u{1F481}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FD}", + "\u{1F481}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FE}", + "\u{1F481}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FF}", + "\u{1F481}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F482}", + "\u{1F482}\u200D\u2640\uFE0F", + "\u{1F482}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FB}", + "\u{1F482}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FC}", + "\u{1F482}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FD}", + "\u{1F482}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FE}", + "\u{1F482}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FF}", + "\u{1F482}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F483}", + "\u{1F483}\u{1F3FB}", + "\u{1F483}\u{1F3FC}", + "\u{1F483}\u{1F3FD}", + "\u{1F483}\u{1F3FE}", + "\u{1F483}\u{1F3FF}", + "\u{1F484}", + "\u{1F485}", + "\u{1F485}\u{1F3FB}", + "\u{1F485}\u{1F3FC}", + "\u{1F485}\u{1F3FD}", + "\u{1F485}\u{1F3FE}", + "\u{1F485}\u{1F3FF}", + "\u{1F486}", + "\u{1F486}\u200D\u2640\uFE0F", + "\u{1F486}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FB}", + "\u{1F486}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FC}", + "\u{1F486}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FD}", + "\u{1F486}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FE}", + "\u{1F486}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FF}", + "\u{1F486}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F487}", + "\u{1F487}\u200D\u2640\uFE0F", + "\u{1F487}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FB}", + "\u{1F487}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FC}", + "\u{1F487}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FD}", + "\u{1F487}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FE}", + "\u{1F487}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FF}", + "\u{1F487}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F488}", + "\u{1F489}", + "\u{1F48A}", + "\u{1F48B}", + "\u{1F48C}", + "\u{1F48D}", + "\u{1F48E}", + "\u{1F48F}", + "\u{1F48F}\u{1F3FB}", + "\u{1F48F}\u{1F3FC}", + "\u{1F48F}\u{1F3FD}", + "\u{1F48F}\u{1F3FE}", + "\u{1F48F}\u{1F3FF}", + "\u{1F490}", + "\u{1F491}", + "\u{1F491}\u{1F3FB}", + "\u{1F491}\u{1F3FC}", + "\u{1F491}\u{1F3FD}", + "\u{1F491}\u{1F3FE}", + "\u{1F491}\u{1F3FF}", + "\u{1F492}", + "\u{1F493}", + "\u{1F494}", + "\u{1F495}", + "\u{1F496}", + "\u{1F497}", + "\u{1F498}", + "\u{1F499}", + "\u{1F49A}", + "\u{1F49B}", + "\u{1F49C}", + "\u{1F49D}", + "\u{1F49E}", + "\u{1F49F}", + "\u{1F4A0}", + "\u{1F4A1}", + "\u{1F4A2}", + "\u{1F4A3}", + "\u{1F4A4}", + "\u{1F4A5}", + "\u{1F4A6}", + "\u{1F4A7}", + "\u{1F4A8}", + "\u{1F4A9}", + "\u{1F4AA}", + "\u{1F4AA}\u{1F3FB}", + "\u{1F4AA}\u{1F3FC}", + "\u{1F4AA}\u{1F3FD}", + "\u{1F4AA}\u{1F3FE}", + "\u{1F4AA}\u{1F3FF}", + "\u{1F4AB}", + "\u{1F4AC}", + "\u{1F4AD}", + "\u{1F4AE}", + "\u{1F4AF}", + "\u{1F4B0}", + "\u{1F4B1}", + "\u{1F4B2}", + "\u{1F4B3}", + "\u{1F4B4}", + "\u{1F4B5}", + "\u{1F4B6}", + "\u{1F4B7}", + "\u{1F4B8}", + "\u{1F4B9}", + "\u{1F4BA}", + "\u{1F4BB}", + "\u{1F4BC}", + "\u{1F4BD}", + "\u{1F4BE}", + "\u{1F4BF}", + "\u{1F4C0}", + "\u{1F4C1}", + "\u{1F4C2}", + "\u{1F4C3}", + "\u{1F4C4}", + "\u{1F4C5}", + "\u{1F4C6}", + "\u{1F4C7}", + "\u{1F4C8}", + "\u{1F4C9}", + "\u{1F4CA}", + "\u{1F4CB}", + "\u{1F4CC}", + "\u{1F4CD}", + "\u{1F4CE}", + "\u{1F4CF}", + "\u{1F4D0}", + "\u{1F4D1}", + "\u{1F4D2}", + "\u{1F4D3}", + "\u{1F4D4}", + "\u{1F4D5}", + "\u{1F4D6}", + "\u{1F4D7}", + "\u{1F4D8}", + "\u{1F4D9}", + "\u{1F4DA}", + "\u{1F4DB}", + "\u{1F4DC}", + "\u{1F4DD}", + "\u{1F4DE}", + "\u{1F4DF}", + "\u{1F4E0}", + "\u{1F4E1}", + "\u{1F4E2}", + "\u{1F4E3}", + "\u{1F4E4}", + "\u{1F4E5}", + "\u{1F4E6}", + "\u{1F4E7}", + "\u{1F4E8}", + "\u{1F4E9}", + "\u{1F4EA}", + "\u{1F4EB}", + "\u{1F4EC}", + "\u{1F4ED}", + "\u{1F4EE}", + "\u{1F4EF}", + "\u{1F4F0}", + "\u{1F4F1}", + "\u{1F4F2}", + "\u{1F4F3}", + "\u{1F4F4}", + "\u{1F4F5}", + "\u{1F4F6}", + "\u{1F4F7}", + "\u{1F4F8}", + "\u{1F4F9}", + "\u{1F4FA}", + "\u{1F4FB}", + "\u{1F4FC}", + "\u{1F4FD}\uFE0F", + "\u{1F4FF}", + "\u{1F500}", + "\u{1F501}", + "\u{1F502}", + "\u{1F503}", + "\u{1F504}", + "\u{1F505}", + "\u{1F506}", + "\u{1F507}", + "\u{1F508}", + "\u{1F509}", + "\u{1F50A}", + "\u{1F50B}", + "\u{1F50C}", + "\u{1F50D}", + "\u{1F50E}", + "\u{1F50F}", + "\u{1F510}", + "\u{1F511}", + "\u{1F512}", + "\u{1F513}", + "\u{1F514}", + "\u{1F515}", + "\u{1F516}", + "\u{1F517}", + "\u{1F518}", + "\u{1F519}", + "\u{1F51A}", + "\u{1F51B}", + "\u{1F51C}", + "\u{1F51D}", + "\u{1F51E}", + "\u{1F51F}", + "\u{1F520}", + "\u{1F521}", + "\u{1F522}", + "\u{1F523}", + "\u{1F524}", + "\u{1F525}", + "\u{1F526}", + "\u{1F527}", + "\u{1F528}", + "\u{1F529}", + "\u{1F52A}", + "\u{1F52B}", + "\u{1F52C}", + "\u{1F52D}", + "\u{1F52E}", + "\u{1F52F}", + "\u{1F530}", + "\u{1F531}", + "\u{1F532}", + "\u{1F533}", + "\u{1F534}", + "\u{1F535}", + "\u{1F536}", + "\u{1F537}", + "\u{1F538}", + "\u{1F539}", + "\u{1F53A}", + "\u{1F53B}", + "\u{1F53C}", + "\u{1F53D}", + "\u{1F549}\uFE0F", + "\u{1F54A}\uFE0F", + "\u{1F54B}", + "\u{1F54C}", + "\u{1F54D}", + "\u{1F54E}", + "\u{1F550}", + "\u{1F551}", + "\u{1F552}", + "\u{1F553}", + "\u{1F554}", + "\u{1F555}", + "\u{1F556}", + "\u{1F557}", + "\u{1F558}", + "\u{1F559}", + "\u{1F55A}", + "\u{1F55B}", + "\u{1F55C}", + "\u{1F55D}", + "\u{1F55E}", + "\u{1F55F}", + "\u{1F560}", + "\u{1F561}", + "\u{1F562}", + "\u{1F563}", + "\u{1F564}", + "\u{1F565}", + "\u{1F566}", + "\u{1F567}", + "\u{1F56F}\uFE0F", + "\u{1F570}\uFE0F", + "\u{1F573}\uFE0F", + "\u{1F574}\u{1F3FB}", + "\u{1F574}\u{1F3FC}", + "\u{1F574}\u{1F3FD}", + "\u{1F574}\u{1F3FE}", + "\u{1F574}\u{1F3FF}", + "\u{1F574}\uFE0F", + "\u{1F575}\u{1F3FB}", + "\u{1F575}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FC}", + "\u{1F575}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FD}", + "\u{1F575}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FE}", + "\u{1F575}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FF}", + "\u{1F575}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F575}\uFE0F", + "\u{1F575}\uFE0F\u200D\u2640\uFE0F", + "\u{1F575}\uFE0F\u200D\u2642\uFE0F", + "\u{1F576}\uFE0F", + "\u{1F577}\uFE0F", + "\u{1F578}\uFE0F", + "\u{1F579}\uFE0F", + "\u{1F57A}", + "\u{1F57A}\u{1F3FB}", + "\u{1F57A}\u{1F3FC}", + "\u{1F57A}\u{1F3FD}", + "\u{1F57A}\u{1F3FE}", + "\u{1F57A}\u{1F3FF}", + "\u{1F587}\uFE0F", + "\u{1F58A}\uFE0F", + "\u{1F58B}\uFE0F", + "\u{1F58C}\uFE0F", + "\u{1F58D}\uFE0F", + "\u{1F590}\u{1F3FB}", + "\u{1F590}\u{1F3FC}", + "\u{1F590}\u{1F3FD}", + "\u{1F590}\u{1F3FE}", + "\u{1F590}\u{1F3FF}", + "\u{1F590}\uFE0F", + "\u{1F595}", + "\u{1F595}\u{1F3FB}", + "\u{1F595}\u{1F3FC}", + "\u{1F595}\u{1F3FD}", + "\u{1F595}\u{1F3FE}", + "\u{1F595}\u{1F3FF}", + "\u{1F596}", + "\u{1F596}\u{1F3FB}", + "\u{1F596}\u{1F3FC}", + "\u{1F596}\u{1F3FD}", + "\u{1F596}\u{1F3FE}", + "\u{1F596}\u{1F3FF}", + "\u{1F5A4}", + "\u{1F5A5}\uFE0F", + "\u{1F5A8}\uFE0F", + "\u{1F5B1}\uFE0F", + "\u{1F5B2}\uFE0F", + "\u{1F5BC}\uFE0F", + "\u{1F5C2}\uFE0F", + "\u{1F5C3}\uFE0F", + "\u{1F5C4}\uFE0F", + "\u{1F5D1}\uFE0F", + "\u{1F5D2}\uFE0F", + "\u{1F5D3}\uFE0F", + "\u{1F5DC}\uFE0F", + "\u{1F5DD}\uFE0F", + "\u{1F5DE}\uFE0F", + "\u{1F5E1}\uFE0F", + "\u{1F5E3}\uFE0F", + "\u{1F5E8}\uFE0F", + "\u{1F5EF}\uFE0F", + "\u{1F5F3}\uFE0F", + "\u{1F5FA}\uFE0F", + "\u{1F5FB}", + "\u{1F5FC}", + "\u{1F5FD}", + "\u{1F5FE}", + "\u{1F5FF}", + "\u{1F600}", + "\u{1F601}", + "\u{1F602}", + "\u{1F603}", + "\u{1F604}", + "\u{1F605}", + "\u{1F606}", + "\u{1F607}", + "\u{1F608}", + "\u{1F609}", + "\u{1F60A}", + "\u{1F60B}", + "\u{1F60C}", + "\u{1F60D}", + "\u{1F60E}", + "\u{1F60F}", + "\u{1F610}", + "\u{1F611}", + "\u{1F612}", + "\u{1F613}", + "\u{1F614}", + "\u{1F615}", + "\u{1F616}", + "\u{1F617}", + "\u{1F618}", + "\u{1F619}", + "\u{1F61A}", + "\u{1F61B}", + "\u{1F61C}", + "\u{1F61D}", + "\u{1F61E}", + "\u{1F61F}", + "\u{1F620}", + "\u{1F621}", + "\u{1F622}", + "\u{1F623}", + "\u{1F624}", + "\u{1F625}", + "\u{1F626}", + "\u{1F627}", + "\u{1F628}", + "\u{1F629}", + "\u{1F62A}", + "\u{1F62B}", + "\u{1F62C}", + "\u{1F62D}", + "\u{1F62E}", + "\u{1F62E}\u200D\u{1F4A8}", + "\u{1F62F}", + "\u{1F630}", + "\u{1F631}", + "\u{1F632}", + "\u{1F633}", + "\u{1F634}", + "\u{1F635}", + "\u{1F635}\u200D\u{1F4AB}", + "\u{1F636}", + "\u{1F636}\u200D\u{1F32B}\uFE0F", + "\u{1F637}", + "\u{1F638}", + "\u{1F639}", + "\u{1F63A}", + "\u{1F63B}", + "\u{1F63C}", + "\u{1F63D}", + "\u{1F63E}", + "\u{1F63F}", + "\u{1F640}", + "\u{1F641}", + "\u{1F642}", + "\u{1F643}", + "\u{1F644}", + "\u{1F645}", + "\u{1F645}\u200D\u2640\uFE0F", + "\u{1F645}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FB}", + "\u{1F645}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FC}", + "\u{1F645}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FD}", + "\u{1F645}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FE}", + "\u{1F645}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FF}", + "\u{1F645}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F646}", + "\u{1F646}\u200D\u2640\uFE0F", + "\u{1F646}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FB}", + "\u{1F646}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FC}", + "\u{1F646}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FD}", + "\u{1F646}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FE}", + "\u{1F646}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FF}", + "\u{1F646}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F647}", + "\u{1F647}\u200D\u2640\uFE0F", + "\u{1F647}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FB}", + "\u{1F647}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FC}", + "\u{1F647}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FD}", + "\u{1F647}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FE}", + "\u{1F647}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FF}", + "\u{1F647}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F648}", + "\u{1F649}", + "\u{1F64A}", + "\u{1F64B}", + "\u{1F64B}\u200D\u2640\uFE0F", + "\u{1F64B}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FB}", + "\u{1F64B}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FC}", + "\u{1F64B}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FD}", + "\u{1F64B}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FE}", + "\u{1F64B}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FF}", + "\u{1F64B}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64C}", + "\u{1F64C}\u{1F3FB}", + "\u{1F64C}\u{1F3FC}", + "\u{1F64C}\u{1F3FD}", + "\u{1F64C}\u{1F3FE}", + "\u{1F64C}\u{1F3FF}", + "\u{1F64D}", + "\u{1F64D}\u200D\u2640\uFE0F", + "\u{1F64D}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FB}", + "\u{1F64D}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FC}", + "\u{1F64D}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FD}", + "\u{1F64D}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FE}", + "\u{1F64D}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FF}", + "\u{1F64D}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64E}", + "\u{1F64E}\u200D\u2640\uFE0F", + "\u{1F64E}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FB}", + "\u{1F64E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FC}", + "\u{1F64E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FD}", + "\u{1F64E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FE}", + "\u{1F64E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FF}", + "\u{1F64E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64F}", + "\u{1F64F}\u{1F3FB}", + "\u{1F64F}\u{1F3FC}", + "\u{1F64F}\u{1F3FD}", + "\u{1F64F}\u{1F3FE}", + "\u{1F64F}\u{1F3FF}", + "\u{1F680}", + "\u{1F681}", + "\u{1F682}", + "\u{1F683}", + "\u{1F684}", + "\u{1F685}", + "\u{1F686}", + "\u{1F687}", + "\u{1F688}", + "\u{1F689}", + "\u{1F68A}", + "\u{1F68B}", + "\u{1F68C}", + "\u{1F68D}", + "\u{1F68E}", + "\u{1F68F}", + "\u{1F690}", + "\u{1F691}", + "\u{1F692}", + "\u{1F693}", + "\u{1F694}", + "\u{1F695}", + "\u{1F696}", + "\u{1F697}", + "\u{1F698}", + "\u{1F699}", + "\u{1F69A}", + "\u{1F69B}", + "\u{1F69C}", + "\u{1F69D}", + "\u{1F69E}", + "\u{1F69F}", + "\u{1F6A0}", + "\u{1F6A1}", + "\u{1F6A2}", + "\u{1F6A3}", + "\u{1F6A3}\u200D\u2640\uFE0F", + "\u{1F6A3}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FB}", + "\u{1F6A3}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FC}", + "\u{1F6A3}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FD}", + "\u{1F6A3}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FE}", + "\u{1F6A3}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FF}", + "\u{1F6A3}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6A4}", + "\u{1F6A5}", + "\u{1F6A6}", + "\u{1F6A7}", + "\u{1F6A8}", + "\u{1F6A9}", + "\u{1F6AA}", + "\u{1F6AB}", + "\u{1F6AC}", + "\u{1F6AD}", + "\u{1F6AE}", + "\u{1F6AF}", + "\u{1F6B0}", + "\u{1F6B1}", + "\u{1F6B2}", + "\u{1F6B3}", + "\u{1F6B4}", + "\u{1F6B4}\u200D\u2640\uFE0F", + "\u{1F6B4}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FB}", + "\u{1F6B4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FC}", + "\u{1F6B4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FD}", + "\u{1F6B4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FE}", + "\u{1F6B4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FF}", + "\u{1F6B4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B5}", + "\u{1F6B5}\u200D\u2640\uFE0F", + "\u{1F6B5}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FB}", + "\u{1F6B5}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FC}", + "\u{1F6B5}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FD}", + "\u{1F6B5}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FE}", + "\u{1F6B5}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FF}", + "\u{1F6B5}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B6}", + "\u{1F6B6}\u200D\u2640\uFE0F", + "\u{1F6B6}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FB}", + "\u{1F6B6}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FC}", + "\u{1F6B6}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FD}", + "\u{1F6B6}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FE}", + "\u{1F6B6}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FF}", + "\u{1F6B6}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B7}", + "\u{1F6B8}", + "\u{1F6B9}", + "\u{1F6BA}", + "\u{1F6BB}", + "\u{1F6BC}", + "\u{1F6BD}", + "\u{1F6BE}", + "\u{1F6BF}", + "\u{1F6C0}", + "\u{1F6C0}\u{1F3FB}", + "\u{1F6C0}\u{1F3FC}", + "\u{1F6C0}\u{1F3FD}", + "\u{1F6C0}\u{1F3FE}", + "\u{1F6C0}\u{1F3FF}", + "\u{1F6C1}", + "\u{1F6C2}", + "\u{1F6C3}", + "\u{1F6C4}", + "\u{1F6C5}", + "\u{1F6CB}\uFE0F", + "\u{1F6CC}", + "\u{1F6CC}\u{1F3FB}", + "\u{1F6CC}\u{1F3FC}", + "\u{1F6CC}\u{1F3FD}", + "\u{1F6CC}\u{1F3FE}", + "\u{1F6CC}\u{1F3FF}", + "\u{1F6CD}\uFE0F", + "\u{1F6CE}\uFE0F", + "\u{1F6CF}\uFE0F", + "\u{1F6D0}", + "\u{1F6D1}", + "\u{1F6D2}", + "\u{1F6D5}", + "\u{1F6D6}", + "\u{1F6D7}", + "\u{1F6DD}", + "\u{1F6DE}", + "\u{1F6DF}", + "\u{1F6E0}\uFE0F", + "\u{1F6E1}\uFE0F", + "\u{1F6E2}\uFE0F", + "\u{1F6E3}\uFE0F", + "\u{1F6E4}\uFE0F", + "\u{1F6E5}\uFE0F", + "\u{1F6E9}\uFE0F", + "\u{1F6EB}", + "\u{1F6EC}", + "\u{1F6F0}\uFE0F", + "\u{1F6F3}\uFE0F", + "\u{1F6F4}", + "\u{1F6F5}", + "\u{1F6F6}", + "\u{1F6F7}", + "\u{1F6F8}", + "\u{1F6F9}", + "\u{1F6FA}", + "\u{1F6FB}", + "\u{1F6FC}", + "\u{1F7E0}", + "\u{1F7E1}", + "\u{1F7E2}", + "\u{1F7E3}", + "\u{1F7E4}", + "\u{1F7E5}", + "\u{1F7E6}", + "\u{1F7E7}", + "\u{1F7E8}", + "\u{1F7E9}", + "\u{1F7EA}", + "\u{1F7EB}", + "\u{1F7F0}", + "\u{1F90C}", + "\u{1F90C}\u{1F3FB}", + "\u{1F90C}\u{1F3FC}", + "\u{1F90C}\u{1F3FD}", + "\u{1F90C}\u{1F3FE}", + "\u{1F90C}\u{1F3FF}", + "\u{1F90D}", + "\u{1F90E}", + "\u{1F90F}", + "\u{1F90F}\u{1F3FB}", + "\u{1F90F}\u{1F3FC}", + "\u{1F90F}\u{1F3FD}", + "\u{1F90F}\u{1F3FE}", + "\u{1F90F}\u{1F3FF}", + "\u{1F910}", + "\u{1F911}", + "\u{1F912}", + "\u{1F913}", + "\u{1F914}", + "\u{1F915}", + "\u{1F916}", + "\u{1F917}", + "\u{1F918}", + "\u{1F918}\u{1F3FB}", + "\u{1F918}\u{1F3FC}", + "\u{1F918}\u{1F3FD}", + "\u{1F918}\u{1F3FE}", + "\u{1F918}\u{1F3FF}", + "\u{1F919}", + "\u{1F919}\u{1F3FB}", + "\u{1F919}\u{1F3FC}", + "\u{1F919}\u{1F3FD}", + "\u{1F919}\u{1F3FE}", + "\u{1F919}\u{1F3FF}", + "\u{1F91A}", + "\u{1F91A}\u{1F3FB}", + "\u{1F91A}\u{1F3FC}", + "\u{1F91A}\u{1F3FD}", + "\u{1F91A}\u{1F3FE}", + "\u{1F91A}\u{1F3FF}", + "\u{1F91B}", + "\u{1F91B}\u{1F3FB}", + "\u{1F91B}\u{1F3FC}", + "\u{1F91B}\u{1F3FD}", + "\u{1F91B}\u{1F3FE}", + "\u{1F91B}\u{1F3FF}", + "\u{1F91C}", + "\u{1F91C}\u{1F3FB}", + "\u{1F91C}\u{1F3FC}", + "\u{1F91C}\u{1F3FD}", + "\u{1F91C}\u{1F3FE}", + "\u{1F91C}\u{1F3FF}", + "\u{1F91D}", + "\u{1F91D}\u{1F3FB}", + "\u{1F91D}\u{1F3FC}", + "\u{1F91D}\u{1F3FD}", + "\u{1F91D}\u{1F3FE}", + "\u{1F91D}\u{1F3FF}", + "\u{1F91E}", + "\u{1F91E}\u{1F3FB}", + "\u{1F91E}\u{1F3FC}", + "\u{1F91E}\u{1F3FD}", + "\u{1F91E}\u{1F3FE}", + "\u{1F91E}\u{1F3FF}", + "\u{1F91F}", + "\u{1F91F}\u{1F3FB}", + "\u{1F91F}\u{1F3FC}", + "\u{1F91F}\u{1F3FD}", + "\u{1F91F}\u{1F3FE}", + "\u{1F91F}\u{1F3FF}", + "\u{1F920}", + "\u{1F921}", + "\u{1F922}", + "\u{1F923}", + "\u{1F924}", + "\u{1F925}", + "\u{1F926}", + "\u{1F926}\u200D\u2640\uFE0F", + "\u{1F926}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FB}", + "\u{1F926}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FC}", + "\u{1F926}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FD}", + "\u{1F926}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FE}", + "\u{1F926}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FF}", + "\u{1F926}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F927}", + "\u{1F928}", + "\u{1F929}", + "\u{1F92A}", + "\u{1F92B}", + "\u{1F92C}", + "\u{1F92D}", + "\u{1F92E}", + "\u{1F92F}", + "\u{1F930}", + "\u{1F930}\u{1F3FB}", + "\u{1F930}\u{1F3FC}", + "\u{1F930}\u{1F3FD}", + "\u{1F930}\u{1F3FE}", + "\u{1F930}\u{1F3FF}", + "\u{1F931}", + "\u{1F931}\u{1F3FB}", + "\u{1F931}\u{1F3FC}", + "\u{1F931}\u{1F3FD}", + "\u{1F931}\u{1F3FE}", + "\u{1F931}\u{1F3FF}", + "\u{1F932}", + "\u{1F932}\u{1F3FB}", + "\u{1F932}\u{1F3FC}", + "\u{1F932}\u{1F3FD}", + "\u{1F932}\u{1F3FE}", + "\u{1F932}\u{1F3FF}", + "\u{1F933}", + "\u{1F933}\u{1F3FB}", + "\u{1F933}\u{1F3FC}", + "\u{1F933}\u{1F3FD}", + "\u{1F933}\u{1F3FE}", + "\u{1F933}\u{1F3FF}", + "\u{1F934}", + "\u{1F934}\u{1F3FB}", + "\u{1F934}\u{1F3FC}", + "\u{1F934}\u{1F3FD}", + "\u{1F934}\u{1F3FE}", + "\u{1F934}\u{1F3FF}", + "\u{1F935}", + "\u{1F935}\u200D\u2640\uFE0F", + "\u{1F935}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FB}", + "\u{1F935}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FC}", + "\u{1F935}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FD}", + "\u{1F935}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FE}", + "\u{1F935}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FF}", + "\u{1F935}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F936}", + "\u{1F936}\u{1F3FB}", + "\u{1F936}\u{1F3FC}", + "\u{1F936}\u{1F3FD}", + "\u{1F936}\u{1F3FE}", + "\u{1F936}\u{1F3FF}", + "\u{1F937}", + "\u{1F937}\u200D\u2640\uFE0F", + "\u{1F937}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FB}", + "\u{1F937}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FC}", + "\u{1F937}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FD}", + "\u{1F937}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FE}", + "\u{1F937}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FF}", + "\u{1F937}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F938}", + "\u{1F938}\u200D\u2640\uFE0F", + "\u{1F938}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FB}", + "\u{1F938}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FC}", + "\u{1F938}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FD}", + "\u{1F938}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FE}", + "\u{1F938}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FF}", + "\u{1F938}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F939}", + "\u{1F939}\u200D\u2640\uFE0F", + "\u{1F939}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FB}", + "\u{1F939}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FC}", + "\u{1F939}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FD}", + "\u{1F939}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FE}", + "\u{1F939}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FF}", + "\u{1F939}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F93A}", + "\u{1F93C}", + "\u{1F93C}\u200D\u2640\uFE0F", + "\u{1F93C}\u200D\u2642\uFE0F", + "\u{1F93D}", + "\u{1F93D}\u200D\u2640\uFE0F", + "\u{1F93D}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FB}", + "\u{1F93D}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FC}", + "\u{1F93D}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FD}", + "\u{1F93D}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FE}", + "\u{1F93D}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FF}", + "\u{1F93D}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F93E}", + "\u{1F93E}\u200D\u2640\uFE0F", + "\u{1F93E}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FB}", + "\u{1F93E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FC}", + "\u{1F93E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FD}", + "\u{1F93E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FE}", + "\u{1F93E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FF}", + "\u{1F93E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F93F}", + "\u{1F940}", + "\u{1F941}", + "\u{1F942}", + "\u{1F943}", + "\u{1F944}", + "\u{1F945}", + "\u{1F947}", + "\u{1F948}", + "\u{1F949}", + "\u{1F94A}", + "\u{1F94B}", + "\u{1F94C}", + "\u{1F94D}", + "\u{1F94E}", + "\u{1F94F}", + "\u{1F950}", + "\u{1F951}", + "\u{1F952}", + "\u{1F953}", + "\u{1F954}", + "\u{1F955}", + "\u{1F956}", + "\u{1F957}", + "\u{1F958}", + "\u{1F959}", + "\u{1F95A}", + "\u{1F95B}", + "\u{1F95C}", + "\u{1F95D}", + "\u{1F95E}", + "\u{1F95F}", + "\u{1F960}", + "\u{1F961}", + "\u{1F962}", + "\u{1F963}", + "\u{1F964}", + "\u{1F965}", + "\u{1F966}", + "\u{1F967}", + "\u{1F968}", + "\u{1F969}", + "\u{1F96A}", + "\u{1F96B}", + "\u{1F96C}", + "\u{1F96D}", + "\u{1F96E}", + "\u{1F96F}", + "\u{1F970}", + "\u{1F971}", + "\u{1F972}", + "\u{1F973}", + "\u{1F974}", + "\u{1F975}", + "\u{1F976}", + "\u{1F977}", + "\u{1F977}\u{1F3FB}", + "\u{1F977}\u{1F3FC}", + "\u{1F977}\u{1F3FD}", + "\u{1F977}\u{1F3FE}", + "\u{1F977}\u{1F3FF}", + "\u{1F978}", + "\u{1F979}", + "\u{1F97A}", + "\u{1F97B}", + "\u{1F97C}", + "\u{1F97D}", + "\u{1F97E}", + "\u{1F97F}", + "\u{1F980}", + "\u{1F981}", + "\u{1F982}", + "\u{1F983}", + "\u{1F984}", + "\u{1F985}", + "\u{1F986}", + "\u{1F987}", + "\u{1F988}", + "\u{1F989}", + "\u{1F98A}", + "\u{1F98B}", + "\u{1F98C}", + "\u{1F98D}", + "\u{1F98E}", + "\u{1F98F}", + "\u{1F990}", + "\u{1F991}", + "\u{1F992}", + "\u{1F993}", + "\u{1F994}", + "\u{1F995}", + "\u{1F996}", + "\u{1F997}", + "\u{1F998}", + "\u{1F999}", + "\u{1F99A}", + "\u{1F99B}", + "\u{1F99C}", + "\u{1F99D}", + "\u{1F99E}", + "\u{1F99F}", + "\u{1F9A0}", + "\u{1F9A1}", + "\u{1F9A2}", + "\u{1F9A3}", + "\u{1F9A4}", + "\u{1F9A5}", + "\u{1F9A6}", + "\u{1F9A7}", + "\u{1F9A8}", + "\u{1F9A9}", + "\u{1F9AA}", + "\u{1F9AB}", + "\u{1F9AC}", + "\u{1F9AD}", + "\u{1F9AE}", + "\u{1F9AF}", + "\u{1F9B0}", + "\u{1F9B1}", + "\u{1F9B2}", + "\u{1F9B3}", + "\u{1F9B4}", + "\u{1F9B5}", + "\u{1F9B5}\u{1F3FB}", + "\u{1F9B5}\u{1F3FC}", + "\u{1F9B5}\u{1F3FD}", + "\u{1F9B5}\u{1F3FE}", + "\u{1F9B5}\u{1F3FF}", + "\u{1F9B6}", + "\u{1F9B6}\u{1F3FB}", + "\u{1F9B6}\u{1F3FC}", + "\u{1F9B6}\u{1F3FD}", + "\u{1F9B6}\u{1F3FE}", + "\u{1F9B6}\u{1F3FF}", + "\u{1F9B7}", + "\u{1F9B8}", + "\u{1F9B8}\u200D\u2640\uFE0F", + "\u{1F9B8}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FB}", + "\u{1F9B8}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FC}", + "\u{1F9B8}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FD}", + "\u{1F9B8}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FE}", + "\u{1F9B8}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FF}", + "\u{1F9B8}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9B9}", + "\u{1F9B9}\u200D\u2640\uFE0F", + "\u{1F9B9}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FB}", + "\u{1F9B9}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FC}", + "\u{1F9B9}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FD}", + "\u{1F9B9}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FE}", + "\u{1F9B9}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FF}", + "\u{1F9B9}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9BA}", + "\u{1F9BB}", + "\u{1F9BB}\u{1F3FB}", + "\u{1F9BB}\u{1F3FC}", + "\u{1F9BB}\u{1F3FD}", + "\u{1F9BB}\u{1F3FE}", + "\u{1F9BB}\u{1F3FF}", + "\u{1F9BC}", + "\u{1F9BD}", + "\u{1F9BE}", + "\u{1F9BF}", + "\u{1F9C0}", + "\u{1F9C1}", + "\u{1F9C2}", + "\u{1F9C3}", + "\u{1F9C4}", + "\u{1F9C5}", + "\u{1F9C6}", + "\u{1F9C7}", + "\u{1F9C8}", + "\u{1F9C9}", + "\u{1F9CA}", + "\u{1F9CB}", + "\u{1F9CC}", + "\u{1F9CD}", + "\u{1F9CD}\u200D\u2640\uFE0F", + "\u{1F9CD}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FB}", + "\u{1F9CD}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FC}", + "\u{1F9CD}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FD}", + "\u{1F9CD}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FE}", + "\u{1F9CD}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FF}", + "\u{1F9CD}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9CE}", + "\u{1F9CE}\u200D\u2640\uFE0F", + "\u{1F9CE}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FB}", + "\u{1F9CE}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FC}", + "\u{1F9CE}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FD}", + "\u{1F9CE}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FE}", + "\u{1F9CE}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FF}", + "\u{1F9CE}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9CF}", + "\u{1F9CF}\u200D\u2640\uFE0F", + "\u{1F9CF}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FB}", + "\u{1F9CF}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FC}", + "\u{1F9CF}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FD}", + "\u{1F9CF}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FE}", + "\u{1F9CF}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FF}", + "\u{1F9CF}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D0}", + "\u{1F9D1}", + "\u{1F9D1}\u200D\u2695\uFE0F", + "\u{1F9D1}\u200D\u2696\uFE0F", + "\u{1F9D1}\u200D\u2708\uFE0F", + "\u{1F9D1}\u200D\u{1F33E}", + "\u{1F9D1}\u200D\u{1F373}", + "\u{1F9D1}\u200D\u{1F37C}", + "\u{1F9D1}\u200D\u{1F384}", + "\u{1F9D1}\u200D\u{1F393}", + "\u{1F9D1}\u200D\u{1F3A4}", + "\u{1F9D1}\u200D\u{1F3A8}", + "\u{1F9D1}\u200D\u{1F3EB}", + "\u{1F9D1}\u200D\u{1F3ED}", + "\u{1F9D1}\u200D\u{1F4BB}", + "\u{1F9D1}\u200D\u{1F4BC}", + "\u{1F9D1}\u200D\u{1F527}", + "\u{1F9D1}\u200D\u{1F52C}", + "\u{1F9D1}\u200D\u{1F680}", + "\u{1F9D1}\u200D\u{1F692}", + "\u{1F9D1}\u200D\u{1F91D}\u200D\u{1F9D1}", + "\u{1F9D1}\u200D\u{1F9AF}", + "\u{1F9D1}\u200D\u{1F9B0}", + "\u{1F9D1}\u200D\u{1F9B1}", + "\u{1F9D1}\u200D\u{1F9B2}", + "\u{1F9D1}\u200D\u{1F9B3}", + "\u{1F9D1}\u200D\u{1F9BC}", + "\u{1F9D1}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BD}", + "\u{1F9D2}", + "\u{1F9D2}\u{1F3FB}", + "\u{1F9D2}\u{1F3FC}", + "\u{1F9D2}\u{1F3FD}", + "\u{1F9D2}\u{1F3FE}", + "\u{1F9D2}\u{1F3FF}", + "\u{1F9D3}", + "\u{1F9D3}\u{1F3FB}", + "\u{1F9D3}\u{1F3FC}", + "\u{1F9D3}\u{1F3FD}", + "\u{1F9D3}\u{1F3FE}", + "\u{1F9D3}\u{1F3FF}", + "\u{1F9D4}", + "\u{1F9D4}\u200D\u2640\uFE0F", + "\u{1F9D4}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FB}", + "\u{1F9D4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FC}", + "\u{1F9D4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FD}", + "\u{1F9D4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FE}", + "\u{1F9D4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FF}", + "\u{1F9D4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D5}", + "\u{1F9D5}\u{1F3FB}", + "\u{1F9D5}\u{1F3FC}", + "\u{1F9D5}\u{1F3FD}", + "\u{1F9D5}\u{1F3FE}", + "\u{1F9D5}\u{1F3FF}", + "\u{1F9D6}", + "\u{1F9D6}\u200D\u2640\uFE0F", + "\u{1F9D6}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FB}", + "\u{1F9D6}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FC}", + "\u{1F9D6}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FD}", + "\u{1F9D6}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FE}", + "\u{1F9D6}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FF}", + "\u{1F9D6}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D7}", + "\u{1F9D7}\u200D\u2640\uFE0F", + "\u{1F9D7}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FB}", + "\u{1F9D7}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FC}", + "\u{1F9D7}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FD}", + "\u{1F9D7}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FE}", + "\u{1F9D7}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FF}", + "\u{1F9D7}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D8}", + "\u{1F9D8}\u200D\u2640\uFE0F", + "\u{1F9D8}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FB}", + "\u{1F9D8}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FC}", + "\u{1F9D8}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FD}", + "\u{1F9D8}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FE}", + "\u{1F9D8}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FF}", + "\u{1F9D8}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D9}", + "\u{1F9D9}\u200D\u2640\uFE0F", + "\u{1F9D9}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FB}", + "\u{1F9D9}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FC}", + "\u{1F9D9}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FD}", + "\u{1F9D9}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FE}", + "\u{1F9D9}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FF}", + "\u{1F9D9}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DA}", + "\u{1F9DA}\u200D\u2640\uFE0F", + "\u{1F9DA}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FB}", + "\u{1F9DA}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FC}", + "\u{1F9DA}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FD}", + "\u{1F9DA}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FE}", + "\u{1F9DA}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FF}", + "\u{1F9DA}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DB}", + "\u{1F9DB}\u200D\u2640\uFE0F", + "\u{1F9DB}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FB}", + "\u{1F9DB}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FC}", + "\u{1F9DB}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FD}", + "\u{1F9DB}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FE}", + "\u{1F9DB}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FF}", + "\u{1F9DB}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DC}", + "\u{1F9DC}\u200D\u2640\uFE0F", + "\u{1F9DC}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FB}", + "\u{1F9DC}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FC}", + "\u{1F9DC}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FD}", + "\u{1F9DC}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FE}", + "\u{1F9DC}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FF}", + "\u{1F9DC}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DD}", + "\u{1F9DD}\u200D\u2640\uFE0F", + "\u{1F9DD}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FB}", + "\u{1F9DD}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FC}", + "\u{1F9DD}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FD}", + "\u{1F9DD}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FE}", + "\u{1F9DD}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FF}", + "\u{1F9DD}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DE}", + "\u{1F9DE}\u200D\u2640\uFE0F", + "\u{1F9DE}\u200D\u2642\uFE0F", + "\u{1F9DF}", + "\u{1F9DF}\u200D\u2640\uFE0F", + "\u{1F9DF}\u200D\u2642\uFE0F", + "\u{1F9E0}", + "\u{1F9E1}", + "\u{1F9E2}", + "\u{1F9E3}", + "\u{1F9E4}", + "\u{1F9E5}", + "\u{1F9E6}", + "\u{1F9E7}", + "\u{1F9E8}", + "\u{1F9E9}", + "\u{1F9EA}", + "\u{1F9EB}", + "\u{1F9EC}", + "\u{1F9ED}", + "\u{1F9EE}", + "\u{1F9EF}", + "\u{1F9F0}", + "\u{1F9F1}", + "\u{1F9F2}", + "\u{1F9F3}", + "\u{1F9F4}", + "\u{1F9F5}", + "\u{1F9F6}", + "\u{1F9F7}", + "\u{1F9F8}", + "\u{1F9F9}", + "\u{1F9FA}", + "\u{1F9FB}", + "\u{1F9FC}", + "\u{1F9FD}", + "\u{1F9FE}", + "\u{1F9FF}", + "\u{1FA70}", + "\u{1FA71}", + "\u{1FA72}", + "\u{1FA73}", + "\u{1FA74}", + "\u{1FA78}", + "\u{1FA79}", + "\u{1FA7A}", + "\u{1FA7B}", + "\u{1FA7C}", + "\u{1FA80}", + "\u{1FA81}", + "\u{1FA82}", + "\u{1FA83}", + "\u{1FA84}", + "\u{1FA85}", + "\u{1FA86}", + "\u{1FA90}", + "\u{1FA91}", + "\u{1FA92}", + "\u{1FA93}", + "\u{1FA94}", + "\u{1FA95}", + "\u{1FA96}", + "\u{1FA97}", + "\u{1FA98}", + "\u{1FA99}", + "\u{1FA9A}", + "\u{1FA9B}", + "\u{1FA9C}", + "\u{1FA9D}", + "\u{1FA9E}", + "\u{1FA9F}", + "\u{1FAA0}", + "\u{1FAA1}", + "\u{1FAA2}", + "\u{1FAA3}", + "\u{1FAA4}", + "\u{1FAA5}", + "\u{1FAA6}", + "\u{1FAA7}", + "\u{1FAA8}", + "\u{1FAA9}", + "\u{1FAAA}", + "\u{1FAAB}", + "\u{1FAAC}", + "\u{1FAB0}", + "\u{1FAB1}", + "\u{1FAB2}", + "\u{1FAB3}", + "\u{1FAB4}", + "\u{1FAB5}", + "\u{1FAB6}", + "\u{1FAB7}", + "\u{1FAB8}", + "\u{1FAB9}", + "\u{1FABA}", + "\u{1FAC0}", + "\u{1FAC1}", + "\u{1FAC2}", + "\u{1FAC3}", + "\u{1FAC3}\u{1F3FB}", + "\u{1FAC3}\u{1F3FC}", + "\u{1FAC3}\u{1F3FD}", + "\u{1FAC3}\u{1F3FE}", + "\u{1FAC3}\u{1F3FF}", + "\u{1FAC4}", + "\u{1FAC4}\u{1F3FB}", + "\u{1FAC4}\u{1F3FC}", + "\u{1FAC4}\u{1F3FD}", + "\u{1FAC4}\u{1F3FE}", + "\u{1FAC4}\u{1F3FF}", + "\u{1FAC5}", + "\u{1FAC5}\u{1F3FB}", + "\u{1FAC5}\u{1F3FC}", + "\u{1FAC5}\u{1F3FD}", + "\u{1FAC5}\u{1F3FE}", + "\u{1FAC5}\u{1F3FF}", + "\u{1FAD0}", + "\u{1FAD1}", + "\u{1FAD2}", + "\u{1FAD3}", + "\u{1FAD4}", + "\u{1FAD5}", + "\u{1FAD6}", + "\u{1FAD7}", + "\u{1FAD8}", + "\u{1FAD9}", + "\u{1FAE0}", + "\u{1FAE1}", + "\u{1FAE2}", + "\u{1FAE3}", + "\u{1FAE4}", + "\u{1FAE5}", + "\u{1FAE6}", + "\u{1FAE7}", + "\u{1FAF0}", + "\u{1FAF0}\u{1F3FB}", + "\u{1FAF0}\u{1F3FC}", + "\u{1FAF0}\u{1F3FD}", + "\u{1FAF0}\u{1F3FE}", + "\u{1FAF0}\u{1F3FF}", + "\u{1FAF1}", + "\u{1FAF1}\u{1F3FB}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FC}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FD}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FE}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FF}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF2}", + "\u{1FAF2}\u{1F3FB}", + "\u{1FAF2}\u{1F3FC}", + "\u{1FAF2}\u{1F3FD}", + "\u{1FAF2}\u{1F3FE}", + "\u{1FAF2}\u{1F3FF}", + "\u{1FAF3}", + "\u{1FAF3}\u{1F3FB}", + "\u{1FAF3}\u{1F3FC}", + "\u{1FAF3}\u{1F3FD}", + "\u{1FAF3}\u{1F3FE}", + "\u{1FAF3}\u{1F3FF}", + "\u{1FAF4}", + "\u{1FAF4}\u{1F3FB}", + "\u{1FAF4}\u{1F3FC}", + "\u{1FAF4}\u{1F3FD}", + "\u{1FAF4}\u{1F3FE}", + "\u{1FAF4}\u{1F3FF}", + "\u{1FAF5}", + "\u{1FAF5}\u{1F3FB}", + "\u{1FAF5}\u{1F3FC}", + "\u{1FAF5}\u{1F3FD}", + "\u{1FAF5}\u{1F3FE}", + "\u{1FAF5}\u{1F3FF}", + "\u{1FAF6}", + "\u{1FAF6}\u{1F3FB}", + "\u{1FAF6}\u{1F3FC}", + "\u{1FAF6}\u{1F3FD}", + "\u{1FAF6}\u{1F3FE}", + "\u{1FAF6}\u{1F3FF}" + ], + nonMatchStrings: [ + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}" + ], +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-CharacterClass.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-CharacterClass.js new file mode 100644 index 000000000000..7f84e40bd9d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-CharacterClass.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji_Flag_Sequence` (property of strings) with `[^\p{…}]` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/[^\p{RGI_Emoji_Flag_Sequence}]/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-P.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-P.js new file mode 100644 index 000000000000..b10e83e01d93 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-P.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji_Flag_Sequence` (property of strings) with `\P{…}` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\P{RGI_Emoji_Flag_Sequence}/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-u.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-u.js new file mode 100644 index 000000000000..f9695425e7c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-u.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji_Flag_Sequence` (property of strings) with the `u` flag throws an early error. Properties of strings are only supported through the `v` flag. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-patterns-static-semantics-early-errors +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\p{RGI_Emoji_Flag_Sequence}/u; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence.js new file mode 100644 index 000000000000..16c303a04d9b --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence.js @@ -0,0 +1,294 @@ +// |reftest| skip -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji_Flag_Sequence` (property of strings) +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes, regexp-v-flag] +includes: [regExpUtils.js] +---*/ + +testPropertyOfStrings({ + regExp: /^\p{RGI_Emoji_Flag_Sequence}+$/v, + expression: "\\p{RGI_Emoji_Flag_Sequence}", + matchStrings: [ + "\u{1F1E6}\u{1F1E8}", + "\u{1F1E6}\u{1F1E9}", + "\u{1F1E6}\u{1F1EA}", + "\u{1F1E6}\u{1F1EB}", + "\u{1F1E6}\u{1F1EC}", + "\u{1F1E6}\u{1F1EE}", + "\u{1F1E6}\u{1F1F1}", + "\u{1F1E6}\u{1F1F2}", + "\u{1F1E6}\u{1F1F4}", + "\u{1F1E6}\u{1F1F6}", + "\u{1F1E6}\u{1F1F7}", + "\u{1F1E6}\u{1F1F8}", + "\u{1F1E6}\u{1F1F9}", + "\u{1F1E6}\u{1F1FA}", + "\u{1F1E6}\u{1F1FC}", + "\u{1F1E6}\u{1F1FD}", + "\u{1F1E6}\u{1F1FF}", + "\u{1F1E7}\u{1F1E6}", + "\u{1F1E7}\u{1F1E7}", + "\u{1F1E7}\u{1F1E9}", + "\u{1F1E7}\u{1F1EA}", + "\u{1F1E7}\u{1F1EB}", + "\u{1F1E7}\u{1F1EC}", + "\u{1F1E7}\u{1F1ED}", + "\u{1F1E7}\u{1F1EE}", + "\u{1F1E7}\u{1F1EF}", + "\u{1F1E7}\u{1F1F1}", + "\u{1F1E7}\u{1F1F2}", + "\u{1F1E7}\u{1F1F3}", + "\u{1F1E7}\u{1F1F4}", + "\u{1F1E7}\u{1F1F6}", + "\u{1F1E7}\u{1F1F7}", + "\u{1F1E7}\u{1F1F8}", + "\u{1F1E7}\u{1F1F9}", + "\u{1F1E7}\u{1F1FB}", + "\u{1F1E7}\u{1F1FC}", + "\u{1F1E7}\u{1F1FE}", + "\u{1F1E7}\u{1F1FF}", + "\u{1F1E8}\u{1F1E6}", + "\u{1F1E8}\u{1F1E8}", + "\u{1F1E8}\u{1F1E9}", + "\u{1F1E8}\u{1F1EB}", + "\u{1F1E8}\u{1F1EC}", + "\u{1F1E8}\u{1F1ED}", + "\u{1F1E8}\u{1F1EE}", + "\u{1F1E8}\u{1F1F0}", + "\u{1F1E8}\u{1F1F1}", + "\u{1F1E8}\u{1F1F2}", + "\u{1F1E8}\u{1F1F3}", + "\u{1F1E8}\u{1F1F4}", + "\u{1F1E8}\u{1F1F5}", + "\u{1F1E8}\u{1F1F7}", + "\u{1F1E8}\u{1F1FA}", + "\u{1F1E8}\u{1F1FB}", + "\u{1F1E8}\u{1F1FC}", + "\u{1F1E8}\u{1F1FD}", + "\u{1F1E8}\u{1F1FE}", + "\u{1F1E8}\u{1F1FF}", + "\u{1F1E9}\u{1F1EA}", + "\u{1F1E9}\u{1F1EC}", + "\u{1F1E9}\u{1F1EF}", + "\u{1F1E9}\u{1F1F0}", + "\u{1F1E9}\u{1F1F2}", + "\u{1F1E9}\u{1F1F4}", + "\u{1F1E9}\u{1F1FF}", + "\u{1F1EA}\u{1F1E6}", + "\u{1F1EA}\u{1F1E8}", + "\u{1F1EA}\u{1F1EA}", + "\u{1F1EA}\u{1F1EC}", + "\u{1F1EA}\u{1F1ED}", + "\u{1F1EA}\u{1F1F7}", + "\u{1F1EA}\u{1F1F8}", + "\u{1F1EA}\u{1F1F9}", + "\u{1F1EA}\u{1F1FA}", + "\u{1F1EB}\u{1F1EE}", + "\u{1F1EB}\u{1F1EF}", + "\u{1F1EB}\u{1F1F0}", + "\u{1F1EB}\u{1F1F2}", + "\u{1F1EB}\u{1F1F4}", + "\u{1F1EB}\u{1F1F7}", + "\u{1F1EC}\u{1F1E6}", + "\u{1F1EC}\u{1F1E7}", + "\u{1F1EC}\u{1F1E9}", + "\u{1F1EC}\u{1F1EA}", + "\u{1F1EC}\u{1F1EB}", + "\u{1F1EC}\u{1F1EC}", + "\u{1F1EC}\u{1F1ED}", + "\u{1F1EC}\u{1F1EE}", + "\u{1F1EC}\u{1F1F1}", + "\u{1F1EC}\u{1F1F2}", + "\u{1F1EC}\u{1F1F3}", + "\u{1F1EC}\u{1F1F5}", + "\u{1F1EC}\u{1F1F6}", + "\u{1F1EC}\u{1F1F7}", + "\u{1F1EC}\u{1F1F8}", + "\u{1F1EC}\u{1F1F9}", + "\u{1F1EC}\u{1F1FA}", + "\u{1F1EC}\u{1F1FC}", + "\u{1F1EC}\u{1F1FE}", + "\u{1F1ED}\u{1F1F0}", + "\u{1F1ED}\u{1F1F2}", + "\u{1F1ED}\u{1F1F3}", + "\u{1F1ED}\u{1F1F7}", + "\u{1F1ED}\u{1F1F9}", + "\u{1F1ED}\u{1F1FA}", + "\u{1F1EE}\u{1F1E8}", + "\u{1F1EE}\u{1F1E9}", + "\u{1F1EE}\u{1F1EA}", + "\u{1F1EE}\u{1F1F1}", + "\u{1F1EE}\u{1F1F2}", + "\u{1F1EE}\u{1F1F3}", + "\u{1F1EE}\u{1F1F4}", + "\u{1F1EE}\u{1F1F6}", + "\u{1F1EE}\u{1F1F7}", + "\u{1F1EE}\u{1F1F8}", + "\u{1F1EE}\u{1F1F9}", + "\u{1F1EF}\u{1F1EA}", + "\u{1F1EF}\u{1F1F2}", + "\u{1F1EF}\u{1F1F4}", + "\u{1F1EF}\u{1F1F5}", + "\u{1F1F0}\u{1F1EA}", + "\u{1F1F0}\u{1F1EC}", + "\u{1F1F0}\u{1F1ED}", + "\u{1F1F0}\u{1F1EE}", + "\u{1F1F0}\u{1F1F2}", + "\u{1F1F0}\u{1F1F3}", + "\u{1F1F0}\u{1F1F5}", + "\u{1F1F0}\u{1F1F7}", + "\u{1F1F0}\u{1F1FC}", + "\u{1F1F0}\u{1F1FE}", + "\u{1F1F0}\u{1F1FF}", + "\u{1F1F1}\u{1F1E6}", + "\u{1F1F1}\u{1F1E7}", + "\u{1F1F1}\u{1F1E8}", + "\u{1F1F1}\u{1F1EE}", + "\u{1F1F1}\u{1F1F0}", + "\u{1F1F1}\u{1F1F7}", + "\u{1F1F1}\u{1F1F8}", + "\u{1F1F1}\u{1F1F9}", + "\u{1F1F1}\u{1F1FA}", + "\u{1F1F1}\u{1F1FB}", + "\u{1F1F1}\u{1F1FE}", + "\u{1F1F2}\u{1F1E6}", + "\u{1F1F2}\u{1F1E8}", + "\u{1F1F2}\u{1F1E9}", + "\u{1F1F2}\u{1F1EA}", + "\u{1F1F2}\u{1F1EB}", + "\u{1F1F2}\u{1F1EC}", + "\u{1F1F2}\u{1F1ED}", + "\u{1F1F2}\u{1F1F0}", + "\u{1F1F2}\u{1F1F1}", + "\u{1F1F2}\u{1F1F2}", + "\u{1F1F2}\u{1F1F3}", + "\u{1F1F2}\u{1F1F4}", + "\u{1F1F2}\u{1F1F5}", + "\u{1F1F2}\u{1F1F6}", + "\u{1F1F2}\u{1F1F7}", + "\u{1F1F2}\u{1F1F8}", + "\u{1F1F2}\u{1F1F9}", + "\u{1F1F2}\u{1F1FA}", + "\u{1F1F2}\u{1F1FB}", + "\u{1F1F2}\u{1F1FC}", + "\u{1F1F2}\u{1F1FD}", + "\u{1F1F2}\u{1F1FE}", + "\u{1F1F2}\u{1F1FF}", + "\u{1F1F3}\u{1F1E6}", + "\u{1F1F3}\u{1F1E8}", + "\u{1F1F3}\u{1F1EA}", + "\u{1F1F3}\u{1F1EB}", + "\u{1F1F3}\u{1F1EC}", + "\u{1F1F3}\u{1F1EE}", + "\u{1F1F3}\u{1F1F1}", + "\u{1F1F3}\u{1F1F4}", + "\u{1F1F3}\u{1F1F5}", + "\u{1F1F3}\u{1F1F7}", + "\u{1F1F3}\u{1F1FA}", + "\u{1F1F3}\u{1F1FF}", + "\u{1F1F4}\u{1F1F2}", + "\u{1F1F5}\u{1F1E6}", + "\u{1F1F5}\u{1F1EA}", + "\u{1F1F5}\u{1F1EB}", + "\u{1F1F5}\u{1F1EC}", + "\u{1F1F5}\u{1F1ED}", + "\u{1F1F5}\u{1F1F0}", + "\u{1F1F5}\u{1F1F1}", + "\u{1F1F5}\u{1F1F2}", + "\u{1F1F5}\u{1F1F3}", + "\u{1F1F5}\u{1F1F7}", + "\u{1F1F5}\u{1F1F8}", + "\u{1F1F5}\u{1F1F9}", + "\u{1F1F5}\u{1F1FC}", + "\u{1F1F5}\u{1F1FE}", + "\u{1F1F6}\u{1F1E6}", + "\u{1F1F7}\u{1F1EA}", + "\u{1F1F7}\u{1F1F4}", + "\u{1F1F7}\u{1F1F8}", + "\u{1F1F7}\u{1F1FA}", + "\u{1F1F7}\u{1F1FC}", + "\u{1F1F8}\u{1F1E6}", + "\u{1F1F8}\u{1F1E7}", + "\u{1F1F8}\u{1F1E8}", + "\u{1F1F8}\u{1F1E9}", + "\u{1F1F8}\u{1F1EA}", + "\u{1F1F8}\u{1F1EC}", + "\u{1F1F8}\u{1F1ED}", + "\u{1F1F8}\u{1F1EE}", + "\u{1F1F8}\u{1F1EF}", + "\u{1F1F8}\u{1F1F0}", + "\u{1F1F8}\u{1F1F1}", + "\u{1F1F8}\u{1F1F2}", + "\u{1F1F8}\u{1F1F3}", + "\u{1F1F8}\u{1F1F4}", + "\u{1F1F8}\u{1F1F7}", + "\u{1F1F8}\u{1F1F8}", + "\u{1F1F8}\u{1F1F9}", + "\u{1F1F8}\u{1F1FB}", + "\u{1F1F8}\u{1F1FD}", + "\u{1F1F8}\u{1F1FE}", + "\u{1F1F8}\u{1F1FF}", + "\u{1F1F9}\u{1F1E6}", + "\u{1F1F9}\u{1F1E8}", + "\u{1F1F9}\u{1F1E9}", + "\u{1F1F9}\u{1F1EB}", + "\u{1F1F9}\u{1F1EC}", + "\u{1F1F9}\u{1F1ED}", + "\u{1F1F9}\u{1F1EF}", + "\u{1F1F9}\u{1F1F0}", + "\u{1F1F9}\u{1F1F1}", + "\u{1F1F9}\u{1F1F2}", + "\u{1F1F9}\u{1F1F3}", + "\u{1F1F9}\u{1F1F4}", + "\u{1F1F9}\u{1F1F7}", + "\u{1F1F9}\u{1F1F9}", + "\u{1F1F9}\u{1F1FB}", + "\u{1F1F9}\u{1F1FC}", + "\u{1F1F9}\u{1F1FF}", + "\u{1F1FA}\u{1F1E6}", + "\u{1F1FA}\u{1F1EC}", + "\u{1F1FA}\u{1F1F2}", + "\u{1F1FA}\u{1F1F3}", + "\u{1F1FA}\u{1F1F8}", + "\u{1F1FA}\u{1F1FE}", + "\u{1F1FA}\u{1F1FF}", + "\u{1F1FB}\u{1F1E6}", + "\u{1F1FB}\u{1F1E8}", + "\u{1F1FB}\u{1F1EA}", + "\u{1F1FB}\u{1F1EC}", + "\u{1F1FB}\u{1F1EE}", + "\u{1F1FB}\u{1F1F3}", + "\u{1F1FB}\u{1F1FA}", + "\u{1F1FC}\u{1F1EB}", + "\u{1F1FC}\u{1F1F8}", + "\u{1F1FD}\u{1F1F0}", + "\u{1F1FE}\u{1F1EA}", + "\u{1F1FE}\u{1F1F9}", + "\u{1F1FF}\u{1F1E6}", + "\u{1F1FF}\u{1F1F2}", + "\u{1F1FF}\u{1F1FC}" + ], + nonMatchStrings: [ + "\u{1F1E8}", + "\u{1F1E6}", + "\u{1F1E9}", + "\u{1F1E6}", + "\u{1F1EA}", + "\u{1F1E6}", + "\u{1F1EB}", + "\u{1F1E6}", + "\u{1F1EC}", + "\u{1F1E6}" + ], +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-CharacterClass.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-CharacterClass.js new file mode 100644 index 000000000000..cc2420d598f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-CharacterClass.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji_Modifier_Sequence` (property of strings) with `[^\p{…}]` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/[^\p{RGI_Emoji_Modifier_Sequence}]/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-P.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-P.js new file mode 100644 index 000000000000..ecc00fa31331 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-P.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji_Modifier_Sequence` (property of strings) with `\P{…}` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\P{RGI_Emoji_Modifier_Sequence}/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-u.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-u.js new file mode 100644 index 000000000000..8dff5b9180a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-u.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji_Modifier_Sequence` (property of strings) with the `u` flag throws an early error. Properties of strings are only supported through the `v` flag. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-patterns-static-semantics-early-errors +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\p{RGI_Emoji_Modifier_Sequence}/u; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence.js new file mode 100644 index 000000000000..5d5773bedf5f --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence.js @@ -0,0 +1,681 @@ +// |reftest| skip -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji_Modifier_Sequence` (property of strings) +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes, regexp-v-flag] +includes: [regExpUtils.js] +---*/ + +testPropertyOfStrings({ + regExp: /^\p{RGI_Emoji_Modifier_Sequence}+$/v, + expression: "\\p{RGI_Emoji_Modifier_Sequence}", + matchStrings: [ + "\u261D\u{1F3FB}", + "\u261D\u{1F3FC}", + "\u261D\u{1F3FD}", + "\u261D\u{1F3FE}", + "\u261D\u{1F3FF}", + "\u26F9\u{1F3FB}", + "\u26F9\u{1F3FC}", + "\u26F9\u{1F3FD}", + "\u26F9\u{1F3FE}", + "\u26F9\u{1F3FF}", + "\u270A\u{1F3FB}", + "\u270A\u{1F3FC}", + "\u270A\u{1F3FD}", + "\u270A\u{1F3FE}", + "\u270A\u{1F3FF}", + "\u270B\u{1F3FB}", + "\u270B\u{1F3FC}", + "\u270B\u{1F3FD}", + "\u270B\u{1F3FE}", + "\u270B\u{1F3FF}", + "\u270C\u{1F3FB}", + "\u270C\u{1F3FC}", + "\u270C\u{1F3FD}", + "\u270C\u{1F3FE}", + "\u270C\u{1F3FF}", + "\u270D\u{1F3FB}", + "\u270D\u{1F3FC}", + "\u270D\u{1F3FD}", + "\u270D\u{1F3FE}", + "\u270D\u{1F3FF}", + "\u{1F385}\u{1F3FB}", + "\u{1F385}\u{1F3FC}", + "\u{1F385}\u{1F3FD}", + "\u{1F385}\u{1F3FE}", + "\u{1F385}\u{1F3FF}", + "\u{1F3C2}\u{1F3FB}", + "\u{1F3C2}\u{1F3FC}", + "\u{1F3C2}\u{1F3FD}", + "\u{1F3C2}\u{1F3FE}", + "\u{1F3C2}\u{1F3FF}", + "\u{1F3C3}\u{1F3FB}", + "\u{1F3C3}\u{1F3FC}", + "\u{1F3C3}\u{1F3FD}", + "\u{1F3C3}\u{1F3FE}", + "\u{1F3C3}\u{1F3FF}", + "\u{1F3C4}\u{1F3FB}", + "\u{1F3C4}\u{1F3FC}", + "\u{1F3C4}\u{1F3FD}", + "\u{1F3C4}\u{1F3FE}", + "\u{1F3C4}\u{1F3FF}", + "\u{1F3C7}\u{1F3FB}", + "\u{1F3C7}\u{1F3FC}", + "\u{1F3C7}\u{1F3FD}", + "\u{1F3C7}\u{1F3FE}", + "\u{1F3C7}\u{1F3FF}", + "\u{1F3CA}\u{1F3FB}", + "\u{1F3CA}\u{1F3FC}", + "\u{1F3CA}\u{1F3FD}", + "\u{1F3CA}\u{1F3FE}", + "\u{1F3CA}\u{1F3FF}", + "\u{1F3CB}\u{1F3FB}", + "\u{1F3CB}\u{1F3FC}", + "\u{1F3CB}\u{1F3FD}", + "\u{1F3CB}\u{1F3FE}", + "\u{1F3CB}\u{1F3FF}", + "\u{1F3CC}\u{1F3FB}", + "\u{1F3CC}\u{1F3FC}", + "\u{1F3CC}\u{1F3FD}", + "\u{1F3CC}\u{1F3FE}", + "\u{1F3CC}\u{1F3FF}", + "\u{1F442}\u{1F3FB}", + "\u{1F442}\u{1F3FC}", + "\u{1F442}\u{1F3FD}", + "\u{1F442}\u{1F3FE}", + "\u{1F442}\u{1F3FF}", + "\u{1F443}\u{1F3FB}", + "\u{1F443}\u{1F3FC}", + "\u{1F443}\u{1F3FD}", + "\u{1F443}\u{1F3FE}", + "\u{1F443}\u{1F3FF}", + "\u{1F446}\u{1F3FB}", + "\u{1F446}\u{1F3FC}", + "\u{1F446}\u{1F3FD}", + "\u{1F446}\u{1F3FE}", + "\u{1F446}\u{1F3FF}", + "\u{1F447}\u{1F3FB}", + "\u{1F447}\u{1F3FC}", + "\u{1F447}\u{1F3FD}", + "\u{1F447}\u{1F3FE}", + "\u{1F447}\u{1F3FF}", + "\u{1F448}\u{1F3FB}", + "\u{1F448}\u{1F3FC}", + "\u{1F448}\u{1F3FD}", + "\u{1F448}\u{1F3FE}", + "\u{1F448}\u{1F3FF}", + "\u{1F449}\u{1F3FB}", + "\u{1F449}\u{1F3FC}", + "\u{1F449}\u{1F3FD}", + "\u{1F449}\u{1F3FE}", + "\u{1F449}\u{1F3FF}", + "\u{1F44A}\u{1F3FB}", + "\u{1F44A}\u{1F3FC}", + "\u{1F44A}\u{1F3FD}", + "\u{1F44A}\u{1F3FE}", + "\u{1F44A}\u{1F3FF}", + "\u{1F44B}\u{1F3FB}", + "\u{1F44B}\u{1F3FC}", + "\u{1F44B}\u{1F3FD}", + "\u{1F44B}\u{1F3FE}", + "\u{1F44B}\u{1F3FF}", + "\u{1F44C}\u{1F3FB}", + "\u{1F44C}\u{1F3FC}", + "\u{1F44C}\u{1F3FD}", + "\u{1F44C}\u{1F3FE}", + "\u{1F44C}\u{1F3FF}", + "\u{1F44D}\u{1F3FB}", + "\u{1F44D}\u{1F3FC}", + "\u{1F44D}\u{1F3FD}", + "\u{1F44D}\u{1F3FE}", + "\u{1F44D}\u{1F3FF}", + "\u{1F44E}\u{1F3FB}", + "\u{1F44E}\u{1F3FC}", + "\u{1F44E}\u{1F3FD}", + "\u{1F44E}\u{1F3FE}", + "\u{1F44E}\u{1F3FF}", + "\u{1F44F}\u{1F3FB}", + "\u{1F44F}\u{1F3FC}", + "\u{1F44F}\u{1F3FD}", + "\u{1F44F}\u{1F3FE}", + "\u{1F44F}\u{1F3FF}", + "\u{1F450}\u{1F3FB}", + "\u{1F450}\u{1F3FC}", + "\u{1F450}\u{1F3FD}", + "\u{1F450}\u{1F3FE}", + "\u{1F450}\u{1F3FF}", + "\u{1F466}\u{1F3FB}", + "\u{1F466}\u{1F3FC}", + "\u{1F466}\u{1F3FD}", + "\u{1F466}\u{1F3FE}", + "\u{1F466}\u{1F3FF}", + "\u{1F467}\u{1F3FB}", + "\u{1F467}\u{1F3FC}", + "\u{1F467}\u{1F3FD}", + "\u{1F467}\u{1F3FE}", + "\u{1F467}\u{1F3FF}", + "\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}", + "\u{1F46B}\u{1F3FB}", + "\u{1F46B}\u{1F3FC}", + "\u{1F46B}\u{1F3FD}", + "\u{1F46B}\u{1F3FE}", + "\u{1F46B}\u{1F3FF}", + "\u{1F46C}\u{1F3FB}", + "\u{1F46C}\u{1F3FC}", + "\u{1F46C}\u{1F3FD}", + "\u{1F46C}\u{1F3FE}", + "\u{1F46C}\u{1F3FF}", + "\u{1F46D}\u{1F3FB}", + "\u{1F46D}\u{1F3FC}", + "\u{1F46D}\u{1F3FD}", + "\u{1F46D}\u{1F3FE}", + "\u{1F46D}\u{1F3FF}", + "\u{1F46E}\u{1F3FB}", + "\u{1F46E}\u{1F3FC}", + "\u{1F46E}\u{1F3FD}", + "\u{1F46E}\u{1F3FE}", + "\u{1F46E}\u{1F3FF}", + "\u{1F470}\u{1F3FB}", + "\u{1F470}\u{1F3FC}", + "\u{1F470}\u{1F3FD}", + "\u{1F470}\u{1F3FE}", + "\u{1F470}\u{1F3FF}", + "\u{1F471}\u{1F3FB}", + "\u{1F471}\u{1F3FC}", + "\u{1F471}\u{1F3FD}", + "\u{1F471}\u{1F3FE}", + "\u{1F471}\u{1F3FF}", + "\u{1F472}\u{1F3FB}", + "\u{1F472}\u{1F3FC}", + "\u{1F472}\u{1F3FD}", + "\u{1F472}\u{1F3FE}", + "\u{1F472}\u{1F3FF}", + "\u{1F473}\u{1F3FB}", + "\u{1F473}\u{1F3FC}", + "\u{1F473}\u{1F3FD}", + "\u{1F473}\u{1F3FE}", + "\u{1F473}\u{1F3FF}", + "\u{1F474}\u{1F3FB}", + "\u{1F474}\u{1F3FC}", + "\u{1F474}\u{1F3FD}", + "\u{1F474}\u{1F3FE}", + "\u{1F474}\u{1F3FF}", + "\u{1F475}\u{1F3FB}", + "\u{1F475}\u{1F3FC}", + "\u{1F475}\u{1F3FD}", + "\u{1F475}\u{1F3FE}", + "\u{1F475}\u{1F3FF}", + "\u{1F476}\u{1F3FB}", + "\u{1F476}\u{1F3FC}", + "\u{1F476}\u{1F3FD}", + "\u{1F476}\u{1F3FE}", + "\u{1F476}\u{1F3FF}", + "\u{1F477}\u{1F3FB}", + "\u{1F477}\u{1F3FC}", + "\u{1F477}\u{1F3FD}", + "\u{1F477}\u{1F3FE}", + "\u{1F477}\u{1F3FF}", + "\u{1F478}\u{1F3FB}", + "\u{1F478}\u{1F3FC}", + "\u{1F478}\u{1F3FD}", + "\u{1F478}\u{1F3FE}", + "\u{1F478}\u{1F3FF}", + "\u{1F47C}\u{1F3FB}", + "\u{1F47C}\u{1F3FC}", + "\u{1F47C}\u{1F3FD}", + "\u{1F47C}\u{1F3FE}", + "\u{1F47C}\u{1F3FF}", + "\u{1F481}\u{1F3FB}", + "\u{1F481}\u{1F3FC}", + "\u{1F481}\u{1F3FD}", + "\u{1F481}\u{1F3FE}", + "\u{1F481}\u{1F3FF}", + "\u{1F482}\u{1F3FB}", + "\u{1F482}\u{1F3FC}", + "\u{1F482}\u{1F3FD}", + "\u{1F482}\u{1F3FE}", + "\u{1F482}\u{1F3FF}", + "\u{1F483}\u{1F3FB}", + "\u{1F483}\u{1F3FC}", + "\u{1F483}\u{1F3FD}", + "\u{1F483}\u{1F3FE}", + "\u{1F483}\u{1F3FF}", + "\u{1F485}\u{1F3FB}", + "\u{1F485}\u{1F3FC}", + "\u{1F485}\u{1F3FD}", + "\u{1F485}\u{1F3FE}", + "\u{1F485}\u{1F3FF}", + "\u{1F486}\u{1F3FB}", + "\u{1F486}\u{1F3FC}", + "\u{1F486}\u{1F3FD}", + "\u{1F486}\u{1F3FE}", + "\u{1F486}\u{1F3FF}", + "\u{1F487}\u{1F3FB}", + "\u{1F487}\u{1F3FC}", + "\u{1F487}\u{1F3FD}", + "\u{1F487}\u{1F3FE}", + "\u{1F487}\u{1F3FF}", + "\u{1F48F}\u{1F3FB}", + "\u{1F48F}\u{1F3FC}", + "\u{1F48F}\u{1F3FD}", + "\u{1F48F}\u{1F3FE}", + "\u{1F48F}\u{1F3FF}", + "\u{1F491}\u{1F3FB}", + "\u{1F491}\u{1F3FC}", + "\u{1F491}\u{1F3FD}", + "\u{1F491}\u{1F3FE}", + "\u{1F491}\u{1F3FF}", + "\u{1F4AA}\u{1F3FB}", + "\u{1F4AA}\u{1F3FC}", + "\u{1F4AA}\u{1F3FD}", + "\u{1F4AA}\u{1F3FE}", + "\u{1F4AA}\u{1F3FF}", + "\u{1F574}\u{1F3FB}", + "\u{1F574}\u{1F3FC}", + "\u{1F574}\u{1F3FD}", + "\u{1F574}\u{1F3FE}", + "\u{1F574}\u{1F3FF}", + "\u{1F575}\u{1F3FB}", + "\u{1F575}\u{1F3FC}", + "\u{1F575}\u{1F3FD}", + "\u{1F575}\u{1F3FE}", + "\u{1F575}\u{1F3FF}", + "\u{1F57A}\u{1F3FB}", + "\u{1F57A}\u{1F3FC}", + "\u{1F57A}\u{1F3FD}", + "\u{1F57A}\u{1F3FE}", + "\u{1F57A}\u{1F3FF}", + "\u{1F590}\u{1F3FB}", + "\u{1F590}\u{1F3FC}", + "\u{1F590}\u{1F3FD}", + "\u{1F590}\u{1F3FE}", + "\u{1F590}\u{1F3FF}", + "\u{1F595}\u{1F3FB}", + "\u{1F595}\u{1F3FC}", + "\u{1F595}\u{1F3FD}", + "\u{1F595}\u{1F3FE}", + "\u{1F595}\u{1F3FF}", + "\u{1F596}\u{1F3FB}", + "\u{1F596}\u{1F3FC}", + "\u{1F596}\u{1F3FD}", + "\u{1F596}\u{1F3FE}", + "\u{1F596}\u{1F3FF}", + "\u{1F645}\u{1F3FB}", + "\u{1F645}\u{1F3FC}", + "\u{1F645}\u{1F3FD}", + "\u{1F645}\u{1F3FE}", + "\u{1F645}\u{1F3FF}", + "\u{1F646}\u{1F3FB}", + "\u{1F646}\u{1F3FC}", + "\u{1F646}\u{1F3FD}", + "\u{1F646}\u{1F3FE}", + "\u{1F646}\u{1F3FF}", + "\u{1F647}\u{1F3FB}", + "\u{1F647}\u{1F3FC}", + "\u{1F647}\u{1F3FD}", + "\u{1F647}\u{1F3FE}", + "\u{1F647}\u{1F3FF}", + "\u{1F64B}\u{1F3FB}", + "\u{1F64B}\u{1F3FC}", + "\u{1F64B}\u{1F3FD}", + "\u{1F64B}\u{1F3FE}", + "\u{1F64B}\u{1F3FF}", + "\u{1F64C}\u{1F3FB}", + "\u{1F64C}\u{1F3FC}", + "\u{1F64C}\u{1F3FD}", + "\u{1F64C}\u{1F3FE}", + "\u{1F64C}\u{1F3FF}", + "\u{1F64D}\u{1F3FB}", + "\u{1F64D}\u{1F3FC}", + "\u{1F64D}\u{1F3FD}", + "\u{1F64D}\u{1F3FE}", + "\u{1F64D}\u{1F3FF}", + "\u{1F64E}\u{1F3FB}", + "\u{1F64E}\u{1F3FC}", + "\u{1F64E}\u{1F3FD}", + "\u{1F64E}\u{1F3FE}", + "\u{1F64E}\u{1F3FF}", + "\u{1F64F}\u{1F3FB}", + "\u{1F64F}\u{1F3FC}", + "\u{1F64F}\u{1F3FD}", + "\u{1F64F}\u{1F3FE}", + "\u{1F64F}\u{1F3FF}", + "\u{1F6A3}\u{1F3FB}", + "\u{1F6A3}\u{1F3FC}", + "\u{1F6A3}\u{1F3FD}", + "\u{1F6A3}\u{1F3FE}", + "\u{1F6A3}\u{1F3FF}", + "\u{1F6B4}\u{1F3FB}", + "\u{1F6B4}\u{1F3FC}", + "\u{1F6B4}\u{1F3FD}", + "\u{1F6B4}\u{1F3FE}", + "\u{1F6B4}\u{1F3FF}", + "\u{1F6B5}\u{1F3FB}", + "\u{1F6B5}\u{1F3FC}", + "\u{1F6B5}\u{1F3FD}", + "\u{1F6B5}\u{1F3FE}", + "\u{1F6B5}\u{1F3FF}", + "\u{1F6B6}\u{1F3FB}", + "\u{1F6B6}\u{1F3FC}", + "\u{1F6B6}\u{1F3FD}", + "\u{1F6B6}\u{1F3FE}", + "\u{1F6B6}\u{1F3FF}", + "\u{1F6C0}\u{1F3FB}", + "\u{1F6C0}\u{1F3FC}", + "\u{1F6C0}\u{1F3FD}", + "\u{1F6C0}\u{1F3FE}", + "\u{1F6C0}\u{1F3FF}", + "\u{1F6CC}\u{1F3FB}", + "\u{1F6CC}\u{1F3FC}", + "\u{1F6CC}\u{1F3FD}", + "\u{1F6CC}\u{1F3FE}", + "\u{1F6CC}\u{1F3FF}", + "\u{1F90C}\u{1F3FB}", + "\u{1F90C}\u{1F3FC}", + "\u{1F90C}\u{1F3FD}", + "\u{1F90C}\u{1F3FE}", + "\u{1F90C}\u{1F3FF}", + "\u{1F90F}\u{1F3FB}", + "\u{1F90F}\u{1F3FC}", + "\u{1F90F}\u{1F3FD}", + "\u{1F90F}\u{1F3FE}", + "\u{1F90F}\u{1F3FF}", + "\u{1F918}\u{1F3FB}", + "\u{1F918}\u{1F3FC}", + "\u{1F918}\u{1F3FD}", + "\u{1F918}\u{1F3FE}", + "\u{1F918}\u{1F3FF}", + "\u{1F919}\u{1F3FB}", + "\u{1F919}\u{1F3FC}", + "\u{1F919}\u{1F3FD}", + "\u{1F919}\u{1F3FE}", + "\u{1F919}\u{1F3FF}", + "\u{1F91A}\u{1F3FB}", + "\u{1F91A}\u{1F3FC}", + "\u{1F91A}\u{1F3FD}", + "\u{1F91A}\u{1F3FE}", + "\u{1F91A}\u{1F3FF}", + "\u{1F91B}\u{1F3FB}", + "\u{1F91B}\u{1F3FC}", + "\u{1F91B}\u{1F3FD}", + "\u{1F91B}\u{1F3FE}", + "\u{1F91B}\u{1F3FF}", + "\u{1F91C}\u{1F3FB}", + "\u{1F91C}\u{1F3FC}", + "\u{1F91C}\u{1F3FD}", + "\u{1F91C}\u{1F3FE}", + "\u{1F91C}\u{1F3FF}", + "\u{1F91D}\u{1F3FB}", + "\u{1F91D}\u{1F3FC}", + "\u{1F91D}\u{1F3FD}", + "\u{1F91D}\u{1F3FE}", + "\u{1F91D}\u{1F3FF}", + "\u{1F91E}\u{1F3FB}", + "\u{1F91E}\u{1F3FC}", + "\u{1F91E}\u{1F3FD}", + "\u{1F91E}\u{1F3FE}", + "\u{1F91E}\u{1F3FF}", + "\u{1F91F}\u{1F3FB}", + "\u{1F91F}\u{1F3FC}", + "\u{1F91F}\u{1F3FD}", + "\u{1F91F}\u{1F3FE}", + "\u{1F91F}\u{1F3FF}", + "\u{1F926}\u{1F3FB}", + "\u{1F926}\u{1F3FC}", + "\u{1F926}\u{1F3FD}", + "\u{1F926}\u{1F3FE}", + "\u{1F926}\u{1F3FF}", + "\u{1F930}\u{1F3FB}", + "\u{1F930}\u{1F3FC}", + "\u{1F930}\u{1F3FD}", + "\u{1F930}\u{1F3FE}", + "\u{1F930}\u{1F3FF}", + "\u{1F931}\u{1F3FB}", + "\u{1F931}\u{1F3FC}", + "\u{1F931}\u{1F3FD}", + "\u{1F931}\u{1F3FE}", + "\u{1F931}\u{1F3FF}", + "\u{1F932}\u{1F3FB}", + "\u{1F932}\u{1F3FC}", + "\u{1F932}\u{1F3FD}", + "\u{1F932}\u{1F3FE}", + "\u{1F932}\u{1F3FF}", + "\u{1F933}\u{1F3FB}", + "\u{1F933}\u{1F3FC}", + "\u{1F933}\u{1F3FD}", + "\u{1F933}\u{1F3FE}", + "\u{1F933}\u{1F3FF}", + "\u{1F934}\u{1F3FB}", + "\u{1F934}\u{1F3FC}", + "\u{1F934}\u{1F3FD}", + "\u{1F934}\u{1F3FE}", + "\u{1F934}\u{1F3FF}", + "\u{1F935}\u{1F3FB}", + "\u{1F935}\u{1F3FC}", + "\u{1F935}\u{1F3FD}", + "\u{1F935}\u{1F3FE}", + "\u{1F935}\u{1F3FF}", + "\u{1F936}\u{1F3FB}", + "\u{1F936}\u{1F3FC}", + "\u{1F936}\u{1F3FD}", + "\u{1F936}\u{1F3FE}", + "\u{1F936}\u{1F3FF}", + "\u{1F937}\u{1F3FB}", + "\u{1F937}\u{1F3FC}", + "\u{1F937}\u{1F3FD}", + "\u{1F937}\u{1F3FE}", + "\u{1F937}\u{1F3FF}", + "\u{1F938}\u{1F3FB}", + "\u{1F938}\u{1F3FC}", + "\u{1F938}\u{1F3FD}", + "\u{1F938}\u{1F3FE}", + "\u{1F938}\u{1F3FF}", + "\u{1F939}\u{1F3FB}", + "\u{1F939}\u{1F3FC}", + "\u{1F939}\u{1F3FD}", + "\u{1F939}\u{1F3FE}", + "\u{1F939}\u{1F3FF}", + "\u{1F93D}\u{1F3FB}", + "\u{1F93D}\u{1F3FC}", + "\u{1F93D}\u{1F3FD}", + "\u{1F93D}\u{1F3FE}", + "\u{1F93D}\u{1F3FF}", + "\u{1F93E}\u{1F3FB}", + "\u{1F93E}\u{1F3FC}", + "\u{1F93E}\u{1F3FD}", + "\u{1F93E}\u{1F3FE}", + "\u{1F93E}\u{1F3FF}", + "\u{1F977}\u{1F3FB}", + "\u{1F977}\u{1F3FC}", + "\u{1F977}\u{1F3FD}", + "\u{1F977}\u{1F3FE}", + "\u{1F977}\u{1F3FF}", + "\u{1F9B5}\u{1F3FB}", + "\u{1F9B5}\u{1F3FC}", + "\u{1F9B5}\u{1F3FD}", + "\u{1F9B5}\u{1F3FE}", + "\u{1F9B5}\u{1F3FF}", + "\u{1F9B6}\u{1F3FB}", + "\u{1F9B6}\u{1F3FC}", + "\u{1F9B6}\u{1F3FD}", + "\u{1F9B6}\u{1F3FE}", + "\u{1F9B6}\u{1F3FF}", + "\u{1F9B8}\u{1F3FB}", + "\u{1F9B8}\u{1F3FC}", + "\u{1F9B8}\u{1F3FD}", + "\u{1F9B8}\u{1F3FE}", + "\u{1F9B8}\u{1F3FF}", + "\u{1F9B9}\u{1F3FB}", + "\u{1F9B9}\u{1F3FC}", + "\u{1F9B9}\u{1F3FD}", + "\u{1F9B9}\u{1F3FE}", + "\u{1F9B9}\u{1F3FF}", + "\u{1F9BB}\u{1F3FB}", + "\u{1F9BB}\u{1F3FC}", + "\u{1F9BB}\u{1F3FD}", + "\u{1F9BB}\u{1F3FE}", + "\u{1F9BB}\u{1F3FF}", + "\u{1F9CD}\u{1F3FB}", + "\u{1F9CD}\u{1F3FC}", + "\u{1F9CD}\u{1F3FD}", + "\u{1F9CD}\u{1F3FE}", + "\u{1F9CD}\u{1F3FF}", + "\u{1F9CE}\u{1F3FB}", + "\u{1F9CE}\u{1F3FC}", + "\u{1F9CE}\u{1F3FD}", + "\u{1F9CE}\u{1F3FE}", + "\u{1F9CE}\u{1F3FF}", + "\u{1F9CF}\u{1F3FB}", + "\u{1F9CF}\u{1F3FC}", + "\u{1F9CF}\u{1F3FD}", + "\u{1F9CF}\u{1F3FE}", + "\u{1F9CF}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}", + "\u{1F9D2}\u{1F3FB}", + "\u{1F9D2}\u{1F3FC}", + "\u{1F9D2}\u{1F3FD}", + "\u{1F9D2}\u{1F3FE}", + "\u{1F9D2}\u{1F3FF}", + "\u{1F9D3}\u{1F3FB}", + "\u{1F9D3}\u{1F3FC}", + "\u{1F9D3}\u{1F3FD}", + "\u{1F9D3}\u{1F3FE}", + "\u{1F9D3}\u{1F3FF}", + "\u{1F9D4}\u{1F3FB}", + "\u{1F9D4}\u{1F3FC}", + "\u{1F9D4}\u{1F3FD}", + "\u{1F9D4}\u{1F3FE}", + "\u{1F9D4}\u{1F3FF}", + "\u{1F9D5}\u{1F3FB}", + "\u{1F9D5}\u{1F3FC}", + "\u{1F9D5}\u{1F3FD}", + "\u{1F9D5}\u{1F3FE}", + "\u{1F9D5}\u{1F3FF}", + "\u{1F9D6}\u{1F3FB}", + "\u{1F9D6}\u{1F3FC}", + "\u{1F9D6}\u{1F3FD}", + "\u{1F9D6}\u{1F3FE}", + "\u{1F9D6}\u{1F3FF}", + "\u{1F9D7}\u{1F3FB}", + "\u{1F9D7}\u{1F3FC}", + "\u{1F9D7}\u{1F3FD}", + "\u{1F9D7}\u{1F3FE}", + "\u{1F9D7}\u{1F3FF}", + "\u{1F9D8}\u{1F3FB}", + "\u{1F9D8}\u{1F3FC}", + "\u{1F9D8}\u{1F3FD}", + "\u{1F9D8}\u{1F3FE}", + "\u{1F9D8}\u{1F3FF}", + "\u{1F9D9}\u{1F3FB}", + "\u{1F9D9}\u{1F3FC}", + "\u{1F9D9}\u{1F3FD}", + "\u{1F9D9}\u{1F3FE}", + "\u{1F9D9}\u{1F3FF}", + "\u{1F9DA}\u{1F3FB}", + "\u{1F9DA}\u{1F3FC}", + "\u{1F9DA}\u{1F3FD}", + "\u{1F9DA}\u{1F3FE}", + "\u{1F9DA}\u{1F3FF}", + "\u{1F9DB}\u{1F3FB}", + "\u{1F9DB}\u{1F3FC}", + "\u{1F9DB}\u{1F3FD}", + "\u{1F9DB}\u{1F3FE}", + "\u{1F9DB}\u{1F3FF}", + "\u{1F9DC}\u{1F3FB}", + "\u{1F9DC}\u{1F3FC}", + "\u{1F9DC}\u{1F3FD}", + "\u{1F9DC}\u{1F3FE}", + "\u{1F9DC}\u{1F3FF}", + "\u{1F9DD}\u{1F3FB}", + "\u{1F9DD}\u{1F3FC}", + "\u{1F9DD}\u{1F3FD}", + "\u{1F9DD}\u{1F3FE}", + "\u{1F9DD}\u{1F3FF}", + "\u{1FAC3}\u{1F3FB}", + "\u{1FAC3}\u{1F3FC}", + "\u{1FAC3}\u{1F3FD}", + "\u{1FAC3}\u{1F3FE}", + "\u{1FAC3}\u{1F3FF}", + "\u{1FAC4}\u{1F3FB}", + "\u{1FAC4}\u{1F3FC}", + "\u{1FAC4}\u{1F3FD}", + "\u{1FAC4}\u{1F3FE}", + "\u{1FAC4}\u{1F3FF}", + "\u{1FAC5}\u{1F3FB}", + "\u{1FAC5}\u{1F3FC}", + "\u{1FAC5}\u{1F3FD}", + "\u{1FAC5}\u{1F3FE}", + "\u{1FAC5}\u{1F3FF}", + "\u{1FAF0}\u{1F3FB}", + "\u{1FAF0}\u{1F3FC}", + "\u{1FAF0}\u{1F3FD}", + "\u{1FAF0}\u{1F3FE}", + "\u{1FAF0}\u{1F3FF}", + "\u{1FAF1}\u{1F3FB}", + "\u{1FAF1}\u{1F3FC}", + "\u{1FAF1}\u{1F3FD}", + "\u{1FAF1}\u{1F3FE}", + "\u{1FAF1}\u{1F3FF}", + "\u{1FAF2}\u{1F3FB}", + "\u{1FAF2}\u{1F3FC}", + "\u{1FAF2}\u{1F3FD}", + "\u{1FAF2}\u{1F3FE}", + "\u{1FAF2}\u{1F3FF}", + "\u{1FAF3}\u{1F3FB}", + "\u{1FAF3}\u{1F3FC}", + "\u{1FAF3}\u{1F3FD}", + "\u{1FAF3}\u{1F3FE}", + "\u{1FAF3}\u{1F3FF}", + "\u{1FAF4}\u{1F3FB}", + "\u{1FAF4}\u{1F3FC}", + "\u{1FAF4}\u{1F3FD}", + "\u{1FAF4}\u{1F3FE}", + "\u{1FAF4}\u{1F3FF}", + "\u{1FAF5}\u{1F3FB}", + "\u{1FAF5}\u{1F3FC}", + "\u{1FAF5}\u{1F3FD}", + "\u{1FAF5}\u{1F3FE}", + "\u{1FAF5}\u{1F3FF}", + "\u{1FAF6}\u{1F3FB}", + "\u{1FAF6}\u{1F3FC}", + "\u{1FAF6}\u{1F3FD}", + "\u{1FAF6}\u{1F3FE}", + "\u{1FAF6}\u{1F3FF}" + ], + nonMatchStrings: [ + "\u{1F3FB}", + "\u261D", + "\u{1F3FC}", + "\u261D", + "\u{1F3FD}", + "\u261D", + "\u{1F3FE}", + "\u261D", + "\u{1F3FF}", + "\u261D" + ], +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-CharacterClass.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-CharacterClass.js new file mode 100644 index 000000000000..1c3aa45c8786 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-CharacterClass.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji_Tag_Sequence` (property of strings) with `[^\p{…}]` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/[^\p{RGI_Emoji_Tag_Sequence}]/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-P.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-P.js new file mode 100644 index 000000000000..639a44514af0 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-P.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji_Tag_Sequence` (property of strings) with `\P{…}` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\P{RGI_Emoji_Tag_Sequence}/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-u.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-u.js new file mode 100644 index 000000000000..2b082963c209 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-u.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji_Tag_Sequence` (property of strings) with the `u` flag throws an early error. Properties of strings are only supported through the `v` flag. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-patterns-static-semantics-early-errors +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\p{RGI_Emoji_Tag_Sequence}/u; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence.js new file mode 100644 index 000000000000..4fe2fbfefa06 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence.js @@ -0,0 +1,38 @@ +// |reftest| skip -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji_Tag_Sequence` (property of strings) +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes, regexp-v-flag] +includes: [regExpUtils.js] +---*/ + +testPropertyOfStrings({ + regExp: /^\p{RGI_Emoji_Tag_Sequence}+$/v, + expression: "\\p{RGI_Emoji_Tag_Sequence}", + matchStrings: [ + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}" + ], + nonMatchStrings: [ + "\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}", + "\u{1F3F4}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}", + "\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}", + "\u{1F3F4}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}", + "\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}", + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}", + "\u{1F3F4}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}" + ], +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-CharacterClass.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-CharacterClass.js new file mode 100644 index 000000000000..773205355a24 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-CharacterClass.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji_ZWJ_Sequence` (property of strings) with `[^\p{…}]` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/[^\p{RGI_Emoji_ZWJ_Sequence}]/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-P.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-P.js new file mode 100644 index 000000000000..d5b804859baa --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-P.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Negating Unicode property escapes for `RGI_Emoji_ZWJ_Sequence` (property of strings) with `\P{…}` throws an early error. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-isvalidregularexpressionliteral +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\P{RGI_Emoji_ZWJ_Sequence}/v; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-u.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-u.js new file mode 100644 index 000000000000..385e15f30a6d --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-u.js @@ -0,0 +1,21 @@ +// |reftest| skip error:SyntaxError -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji_ZWJ_Sequence` (property of strings) with the `u` flag throws an early error. Properties of strings are only supported through the `v` flag. +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-patterns-static-semantics-early-errors +features: [regexp-unicode-property-escapes, regexp-v-flag] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +/\p{RGI_Emoji_ZWJ_Sequence}/u; diff --git a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence.js new file mode 100644 index 000000000000..e2fc28113908 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence.js @@ -0,0 +1,1390 @@ +// |reftest| skip -- regexp-v-flag is not supported +// Copyright 2021 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +description: > + Unicode property escapes for `RGI_Emoji_ZWJ_Sequence` (property of strings) +info: | + Generated by https://github.com/mathiasbynens/unicode-property-escapes-tests + Unicode v14.0.0 +esid: sec-static-semantics-unicodematchproperty-p +features: [regexp-unicode-property-escapes, regexp-v-flag] +includes: [regExpUtils.js] +---*/ + +testPropertyOfStrings({ + regExp: /^\p{RGI_Emoji_ZWJ_Sequence}+$/v, + expression: "\\p{RGI_Emoji_ZWJ_Sequence}", + matchStrings: [ + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F468}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F469}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}", + "\u{1F469}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}", + "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F468}\u{1F3FE}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FD}", + "\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F469}\u{1F3FE}", + "\u{1F9D1}\u200D\u{1F91D}\u200D\u{1F9D1}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F384}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FC}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1FAF1}\u{1F3FD}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FE}\u200D\u{1FAF2}\u{1F3FF}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FB}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FC}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FD}", + "\u{1FAF1}\u{1F3FF}\u200D\u{1FAF2}\u{1F3FE}", + "\u{1F468}\u200D\u2695\uFE0F", + "\u{1F468}\u200D\u2696\uFE0F", + "\u{1F468}\u200D\u2708\uFE0F", + "\u{1F468}\u200D\u{1F33E}", + "\u{1F468}\u200D\u{1F373}", + "\u{1F468}\u200D\u{1F37C}", + "\u{1F468}\u200D\u{1F393}", + "\u{1F468}\u200D\u{1F3A4}", + "\u{1F468}\u200D\u{1F3A8}", + "\u{1F468}\u200D\u{1F3EB}", + "\u{1F468}\u200D\u{1F3ED}", + "\u{1F468}\u200D\u{1F4BB}", + "\u{1F468}\u200D\u{1F4BC}", + "\u{1F468}\u200D\u{1F527}", + "\u{1F468}\u200D\u{1F52C}", + "\u{1F468}\u200D\u{1F680}", + "\u{1F468}\u200D\u{1F692}", + "\u{1F468}\u200D\u{1F9AF}", + "\u{1F468}\u200D\u{1F9BC}", + "\u{1F468}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FB}\u200D\u{1F373}", + "\u{1F468}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FB}\u200D\u{1F393}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F527}", + "\u{1F468}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FB}\u200D\u{1F680}", + "\u{1F468}\u{1F3FB}\u200D\u{1F692}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FC}\u200D\u{1F373}", + "\u{1F468}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FC}\u200D\u{1F393}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FC}\u200D\u{1F527}", + "\u{1F468}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FC}\u200D\u{1F680}", + "\u{1F468}\u{1F3FC}\u200D\u{1F692}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FD}\u200D\u{1F373}", + "\u{1F468}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FD}\u200D\u{1F393}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FD}\u200D\u{1F527}", + "\u{1F468}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FD}\u200D\u{1F680}", + "\u{1F468}\u{1F3FD}\u200D\u{1F692}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FE}\u200D\u{1F373}", + "\u{1F468}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FE}\u200D\u{1F393}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F527}", + "\u{1F468}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FE}\u200D\u{1F680}", + "\u{1F468}\u{1F3FE}\u200D\u{1F692}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F468}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F468}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F468}\u{1F3FF}\u200D\u{1F373}", + "\u{1F468}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F468}\u{1F3FF}\u200D\u{1F393}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F468}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F468}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F527}", + "\u{1F468}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F468}\u{1F3FF}\u200D\u{1F680}", + "\u{1F468}\u{1F3FF}\u200D\u{1F692}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9BD}", + "\u{1F469}\u200D\u2695\uFE0F", + "\u{1F469}\u200D\u2696\uFE0F", + "\u{1F469}\u200D\u2708\uFE0F", + "\u{1F469}\u200D\u{1F33E}", + "\u{1F469}\u200D\u{1F373}", + "\u{1F469}\u200D\u{1F37C}", + "\u{1F469}\u200D\u{1F393}", + "\u{1F469}\u200D\u{1F3A4}", + "\u{1F469}\u200D\u{1F3A8}", + "\u{1F469}\u200D\u{1F3EB}", + "\u{1F469}\u200D\u{1F3ED}", + "\u{1F469}\u200D\u{1F4BB}", + "\u{1F469}\u200D\u{1F4BC}", + "\u{1F469}\u200D\u{1F527}", + "\u{1F469}\u200D\u{1F52C}", + "\u{1F469}\u200D\u{1F680}", + "\u{1F469}\u200D\u{1F692}", + "\u{1F469}\u200D\u{1F9AF}", + "\u{1F469}\u200D\u{1F9BC}", + "\u{1F469}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FB}\u200D\u{1F373}", + "\u{1F469}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FB}\u200D\u{1F393}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F527}", + "\u{1F469}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FB}\u200D\u{1F680}", + "\u{1F469}\u{1F3FB}\u200D\u{1F692}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FC}\u200D\u{1F373}", + "\u{1F469}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FC}\u200D\u{1F393}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FC}\u200D\u{1F527}", + "\u{1F469}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FC}\u200D\u{1F680}", + "\u{1F469}\u{1F3FC}\u200D\u{1F692}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FD}\u200D\u{1F373}", + "\u{1F469}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FD}\u200D\u{1F393}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F527}", + "\u{1F469}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FD}\u200D\u{1F680}", + "\u{1F469}\u{1F3FD}\u200D\u{1F692}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FE}\u200D\u{1F373}", + "\u{1F469}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FE}\u200D\u{1F393}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F527}", + "\u{1F469}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FE}\u200D\u{1F680}", + "\u{1F469}\u{1F3FE}\u200D\u{1F692}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F469}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F469}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F469}\u{1F3FF}\u200D\u{1F373}", + "\u{1F469}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F469}\u{1F3FF}\u200D\u{1F393}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F469}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F469}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F527}", + "\u{1F469}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F469}\u{1F3FF}\u200D\u{1F680}", + "\u{1F469}\u{1F3FF}\u200D\u{1F692}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9BD}", + "\u{1F9D1}\u200D\u2695\uFE0F", + "\u{1F9D1}\u200D\u2696\uFE0F", + "\u{1F9D1}\u200D\u2708\uFE0F", + "\u{1F9D1}\u200D\u{1F33E}", + "\u{1F9D1}\u200D\u{1F373}", + "\u{1F9D1}\u200D\u{1F37C}", + "\u{1F9D1}\u200D\u{1F393}", + "\u{1F9D1}\u200D\u{1F3A4}", + "\u{1F9D1}\u200D\u{1F3A8}", + "\u{1F9D1}\u200D\u{1F3EB}", + "\u{1F9D1}\u200D\u{1F3ED}", + "\u{1F9D1}\u200D\u{1F4BB}", + "\u{1F9D1}\u200D\u{1F4BC}", + "\u{1F9D1}\u200D\u{1F527}", + "\u{1F9D1}\u200D\u{1F52C}", + "\u{1F9D1}\u200D\u{1F680}", + "\u{1F9D1}\u200D\u{1F692}", + "\u{1F9D1}\u200D\u{1F9AF}", + "\u{1F9D1}\u200D\u{1F9BC}", + "\u{1F9D1}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FB}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FC}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FD}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FE}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BD}", + "\u{1F9D1}\u{1F3FF}\u200D\u2695\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u2696\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u2708\uFE0F", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F33E}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F373}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F37C}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F393}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3A4}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3A8}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3EB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F3ED}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F4BB}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F4BC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F527}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F52C}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F680}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F692}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9AF}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BC}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BD}", + "\u26F9\u{1F3FB}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FB}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FC}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FC}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FD}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FD}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FE}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FE}\u200D\u2642\uFE0F", + "\u26F9\u{1F3FF}\u200D\u2640\uFE0F", + "\u26F9\u{1F3FF}\u200D\u2642\uFE0F", + "\u26F9\uFE0F\u200D\u2640\uFE0F", + "\u26F9\uFE0F\u200D\u2642\uFE0F", + "\u{1F3C3}\u200D\u2640\uFE0F", + "\u{1F3C3}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3C3}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3C3}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3C4}\u200D\u2640\uFE0F", + "\u{1F3C4}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3C4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3C4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CA}\u200D\u2640\uFE0F", + "\u{1F3CA}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CA}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CA}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CB}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CB}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CB}\uFE0F\u200D\u2640\uFE0F", + "\u{1F3CB}\uFE0F\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F3CC}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F3CC}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F3CC}\uFE0F\u200D\u2640\uFE0F", + "\u{1F3CC}\uFE0F\u200D\u2642\uFE0F", + "\u{1F46E}\u200D\u2640\uFE0F", + "\u{1F46E}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F46E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F46E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F46F}\u200D\u2640\uFE0F", + "\u{1F46F}\u200D\u2642\uFE0F", + "\u{1F470}\u200D\u2640\uFE0F", + "\u{1F470}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F470}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F470}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F471}\u200D\u2640\uFE0F", + "\u{1F471}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F471}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F471}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F473}\u200D\u2640\uFE0F", + "\u{1F473}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F473}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F473}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F477}\u200D\u2640\uFE0F", + "\u{1F477}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F477}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F477}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F481}\u200D\u2640\uFE0F", + "\u{1F481}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F481}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F481}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F482}\u200D\u2640\uFE0F", + "\u{1F482}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F482}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F482}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F486}\u200D\u2640\uFE0F", + "\u{1F486}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F486}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F486}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F487}\u200D\u2640\uFE0F", + "\u{1F487}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F487}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F487}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F575}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F575}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F575}\uFE0F\u200D\u2640\uFE0F", + "\u{1F575}\uFE0F\u200D\u2642\uFE0F", + "\u{1F645}\u200D\u2640\uFE0F", + "\u{1F645}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F645}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F645}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F646}\u200D\u2640\uFE0F", + "\u{1F646}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F646}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F646}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F647}\u200D\u2640\uFE0F", + "\u{1F647}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F647}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F647}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64B}\u200D\u2640\uFE0F", + "\u{1F64B}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64B}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64B}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64D}\u200D\u2640\uFE0F", + "\u{1F64D}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64D}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64D}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F64E}\u200D\u2640\uFE0F", + "\u{1F64E}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F64E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F64E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6A3}\u200D\u2640\uFE0F", + "\u{1F6A3}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6A3}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6A3}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B4}\u200D\u2640\uFE0F", + "\u{1F6B4}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B5}\u200D\u2640\uFE0F", + "\u{1F6B5}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B5}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B5}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F6B6}\u200D\u2640\uFE0F", + "\u{1F6B6}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F6B6}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F6B6}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F926}\u200D\u2640\uFE0F", + "\u{1F926}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F926}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F926}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F935}\u200D\u2640\uFE0F", + "\u{1F935}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F935}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F935}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F937}\u200D\u2640\uFE0F", + "\u{1F937}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F937}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F937}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F938}\u200D\u2640\uFE0F", + "\u{1F938}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F938}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F938}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F939}\u200D\u2640\uFE0F", + "\u{1F939}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F939}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F939}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F93C}\u200D\u2640\uFE0F", + "\u{1F93C}\u200D\u2642\uFE0F", + "\u{1F93D}\u200D\u2640\uFE0F", + "\u{1F93D}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F93D}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F93D}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F93E}\u200D\u2640\uFE0F", + "\u{1F93E}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F93E}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F93E}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9B8}\u200D\u2640\uFE0F", + "\u{1F9B8}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9B8}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9B8}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9B9}\u200D\u2640\uFE0F", + "\u{1F9B9}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9B9}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9B9}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9CD}\u200D\u2640\uFE0F", + "\u{1F9CD}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CD}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CD}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9CE}\u200D\u2640\uFE0F", + "\u{1F9CE}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CE}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CE}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9CF}\u200D\u2640\uFE0F", + "\u{1F9CF}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9CF}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9CF}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D4}\u200D\u2640\uFE0F", + "\u{1F9D4}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D4}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D4}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D6}\u200D\u2640\uFE0F", + "\u{1F9D6}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D6}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D6}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D7}\u200D\u2640\uFE0F", + "\u{1F9D7}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D7}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D7}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D8}\u200D\u2640\uFE0F", + "\u{1F9D8}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D8}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D8}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9D9}\u200D\u2640\uFE0F", + "\u{1F9D9}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9D9}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9D9}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DA}\u200D\u2640\uFE0F", + "\u{1F9DA}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DA}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DA}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DB}\u200D\u2640\uFE0F", + "\u{1F9DB}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DB}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DB}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DC}\u200D\u2640\uFE0F", + "\u{1F9DC}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DC}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DC}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DD}\u200D\u2640\uFE0F", + "\u{1F9DD}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FB}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FB}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FC}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FC}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FD}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FD}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FE}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FE}\u200D\u2642\uFE0F", + "\u{1F9DD}\u{1F3FF}\u200D\u2640\uFE0F", + "\u{1F9DD}\u{1F3FF}\u200D\u2642\uFE0F", + "\u{1F9DE}\u200D\u2640\uFE0F", + "\u{1F9DE}\u200D\u2642\uFE0F", + "\u{1F9DF}\u200D\u2640\uFE0F", + "\u{1F9DF}\u200D\u2642\uFE0F", + "\u{1F468}\u200D\u{1F9B0}", + "\u{1F468}\u200D\u{1F9B1}", + "\u{1F468}\u200D\u{1F9B2}", + "\u{1F468}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F468}\u{1F3FF}\u200D\u{1F9B3}", + "\u{1F469}\u200D\u{1F9B0}", + "\u{1F469}\u200D\u{1F9B1}", + "\u{1F469}\u200D\u{1F9B2}", + "\u{1F469}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F469}\u{1F3FF}\u200D\u{1F9B3}", + "\u{1F9D1}\u200D\u{1F9B0}", + "\u{1F9D1}\u200D\u{1F9B1}", + "\u{1F9D1}\u200D\u{1F9B2}", + "\u{1F9D1}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B3}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B0}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B1}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B2}", + "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B3}", + "\u2764\uFE0F\u200D\u{1F525}", + "\u2764\uFE0F\u200D\u{1FA79}", + "\u{1F3F3}\uFE0F\u200D\u26A7\uFE0F", + "\u{1F3F3}\uFE0F\u200D\u{1F308}", + "\u{1F3F4}\u200D\u2620\uFE0F", + "\u{1F408}\u200D\u2B1B", + "\u{1F415}\u200D\u{1F9BA}", + "\u{1F43B}\u200D\u2744\uFE0F", + "\u{1F441}\uFE0F\u200D\u{1F5E8}\uFE0F", + "\u{1F62E}\u200D\u{1F4A8}", + "\u{1F635}\u200D\u{1F4AB}", + "\u{1F636}\u200D\u{1F32B}\uFE0F", + "\u{1F9D1}\u200D\u{1F384}" + ], + nonMatchStrings: [ + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}", + "\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}", + "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}", + "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}" + ], +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/browser.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/browser.js rename to js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/browser.js diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/shell.js b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/shell.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/shell.js rename to js/src/tests/test262/built-ins/RegExp/property-escapes/generated/strings/shell.js diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A1.js b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A1.js index 8effb4f219cd..04d04f32100c 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A1.js @@ -6,10 +6,6 @@ info: The RegExp has property prototype es5id: 15.10.5.1_A1 description: Checking RegExp.prototype property ---*/ - -//CHECK#1 -if (RegExp.hasOwnProperty('prototype') !== true) { - throw new Test262Error('#1: RegExp.hasOwnProperty(\'prototype\') === true'); -} +assert.sameValue(RegExp.hasOwnProperty('prototype'), true, 'RegExp.hasOwnProperty(\'prototype\') must return true'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A2.js b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A2.js index 78fd823b036c..3ae4b9d1bded 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A2.js @@ -6,25 +6,23 @@ info: The RegExp.prototype property has the attribute DontEnum es5id: 15.10.5.1_A2 description: Checking if enumerating the RegExp.prototype property fails ---*/ +assert.sameValue(RegExp.hasOwnProperty('prototype'), true, 'RegExp.hasOwnProperty(\'prototype\') must return true'); -//CHECK#0 -if (RegExp.hasOwnProperty('prototype') !== true) { - throw new Test262Error('#0: RegExp.hasOwnProperty(\'prototype\') === true'); -} +assert.sameValue( + RegExp.propertyIsEnumerable('prototype'), + false, + 'RegExp.propertyIsEnumerable(\'prototype\') must return false' +); - //CHECK#1 -if (RegExp.propertyIsEnumerable('prototype') !== false) { - throw new Test262Error('#1: RegExp.propertyIsEnumerable(\'prototype\') === false'); -} - - //CHECK#2 var count=0; for (var p in RegExp){ - if (p==="prototype") count++; + if (p==="prototype") { + count++; + } } -if (count !== 0) { - throw new Test262Error('#2: count=0; for (p in RegExp){ if (p==="prototype") count++; } count === 0. Actual: ' + (count)); -} +assert.sameValue(count, 0, 'The value of count is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A3.js b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A3.js index b81b65992ca6..d88e80882e7e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A3.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A3.js @@ -7,27 +7,24 @@ es5id: 15.10.5.1_A3 description: Checking if deleting the RegExp.prototype property fails includes: [propertyHelper.js] ---*/ - -//CHECK#0 -if (RegExp.hasOwnProperty('prototype') !== true) { - throw new Test262Error('#0: RegExp.hasOwnProperty(\'prototype\') === true'); -} +assert.sameValue(RegExp.hasOwnProperty('prototype'), true); verifyNotConfigurable(RegExp, "prototype"); -//CHECK#1 try { - if (delete RegExp.prototype !== false) { - throw new Test262Error('#1: delete RegExp.prototype === false'); - } + assert.sameValue(delete RegExp.prototype, false); } catch (e) { - if (e instanceof Test262Error) throw e; + if (e instanceof Test262Error) { + throw e; + } assert(e instanceof TypeError); } -//CHECK#2 if (RegExp.hasOwnProperty('prototype') !== true) { - throw new Test262Error('#2: delete RegExp.prototype; RegExp.hasOwnProperty(\'prototype\') === true'); + throw new Test262Error('#2: delete RegExp.prototype; RegExp.hasOwnProperty(\'prototype\') === true'); } +// TODO: Convert to verifyProperty() format. +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A4.js b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A4.js index c05e4e5833ed..f55d12ffb5e5 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A4.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.5.1_A4.js @@ -7,19 +7,14 @@ es5id: 15.10.5.1_A4 description: Checking if varying the RegExp.prototype property fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (RegExp.hasOwnProperty('prototype') !== true) { - throw new Test262Error('#1: RegExp.hasOwnProperty(\'prototype\') === true'); -} +assert.sameValue(RegExp.hasOwnProperty('prototype'), true, 'RegExp.hasOwnProperty(\'prototype\') must return true'); var __obj = RegExp.prototype; verifyNotWritable(RegExp, "prototype", null, function(){return "shifted";}); -//CHECK#2 -if (RegExp.prototype !== __obj) { - throw new Test262Error('#2: __obj = RegExp.prototype; RegExp.prototype = function(){return "shifted";}; RegExp.prototype === __obj. Actual: ' + (RegExp.prototype)); -} +assert.sameValue(RegExp.prototype, __obj, 'The value of RegExp.prototype is expected to equal the value of __obj'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6.1_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6.1_A1_T1.js index 09431c5e440b..00da30eab955 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6.1_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6.1_A1_T1.js @@ -8,10 +8,10 @@ info: | es5id: 15.10.6.1_A1_T1 description: Compare RegExp.prototype.constructor with RegExp ---*/ - -//CHECK#1 -if (RegExp.prototype.constructor !== RegExp) { - throw new Test262Error('#1: RegExp.prototype.constructor === RegExp. Actual: ' + (RegExp.prototype.constructor)); -} +assert.sameValue( + RegExp.prototype.constructor, + RegExp, + 'The value of RegExp.prototype.constructor is expected to equal the value of RegExp' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6.1_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6.1_A1_T2.js index 79294068401c..01dada3d9e12 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6.1_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6.1_A1_T2.js @@ -15,14 +15,16 @@ var __FACTORY = RegExp.prototype.constructor; var __instance = new __FACTORY; -//CHECK#1 -if ((__instance instanceof RegExp) !== true) { - throw new Test262Error('#1: __FACTORY = RegExp.prototype.constructor; __instance = new __FACTORY; (__instance instanceof RegExp) === true'); -} +assert.sameValue( + __instance instanceof RegExp, + true, + 'The result of evaluating (__instance instanceof RegExp) is expected to be true' +); -//CHECK#2 -if (__instance.constructor !== RegExp) { - throw new Test262Error('#2: __FACTORY = RegExp.prototype.constructor; __instance = new __FACTORY; __instance.constructor === RegExp. Actual: ' + (__instance.constructor)); -} +assert.sameValue( + __instance.constructor, + RegExp, + 'The value of __instance.constructor is expected to equal the value of RegExp' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6_A1_T1.js index 15da0f2977a5..c7c472c99715 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6_A1_T1.js @@ -8,10 +8,10 @@ info: | es5id: 15.10.6_A1_T1 description: Checking Object.prototype.isPrototypeOf(RegExp.prototype) ---*/ - -//CHECK#1 -if (Object.prototype.isPrototypeOf(RegExp.prototype) !== true) { - throw new Test262Error('#1: Object.prototype.isPrototypeOf(RegExp.prototype) === true'); -} +assert.sameValue( + Object.prototype.isPrototypeOf(RegExp.prototype), + true, + 'Object.prototype.isPrototypeOf(RegExp.prototype) must return true' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6_A1_T2.js index ab0b8eb5c3ae..9de66ca24601 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/S15.10.6_A1_T2.js @@ -13,9 +13,6 @@ description: > Object.prototype.indicator = 1; -//CHECK#1 -if (RegExp.prototype.indicator !== 1) { - throw new Test262Error('#1: Object.prototype.indicator = 1; RegExp.prototype.indicator === 1. Actual: ' + (RegExp.prototype.indicator)); -} +assert.sameValue(RegExp.prototype.indicator, 1, 'The value of RegExp.prototype.indicator is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/Symbol.matchAll/shell.js b/js/src/tests/test262/built-ins/RegExp/prototype/Symbol.matchAll/shell.js index acac42890065..1ad30bb1df39 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/Symbol.matchAll/shell.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/Symbol.matchAll/shell.js @@ -42,7 +42,7 @@ assert.compareIterator = function(iter, validators, message) { /*--- description: | Collection of functions used to assert the correctness of RegExp objects. -defines: [buildString, testPropertyEscapes, matchValidator] +defines: [buildString, testPropertyEscapes, testPropertyOfStrings, matchValidator] ---*/ function buildString(args) { @@ -70,23 +70,65 @@ function buildString(args) { return result; } -function testPropertyEscapes(regex, string, expression) { - if (!regex.test(string)) { +function printCodePoint(codePoint) { + const hex = codePoint + .toString(16) + .toUpperCase() + .padStart(6, "0"); + return `U+${hex}`; +} + +function printStringCodePoints(string) { + const buf = []; + for (const symbol of string) { + const formatted = printCodePoint(symbol.codePointAt(0)); + buf.push(formatted); + } + return buf.join(' '); +} + +function testPropertyEscapes(regExp, string, expression) { + if (!regExp.test(string)) { for (const symbol of string) { - const hex = symbol - .codePointAt(0) - .toString(16) - .toUpperCase() - .padStart(6, "0"); + printCodePoint(symbol.codePointAt(0)); assert( - regex.test(symbol), + regExp.test(symbol), `\`${ expression }\` should match U+${ hex } (\`${ symbol }\`)` ); } } } -// Returns a function that will validate RegExp match result +function testPropertyOfStrings(args) { + // Use member expressions rather than destructuring `args` for improved + // compatibility with engines that only implement assignment patterns + // partially or not at all. + const regExp = args.regExp; + const expression = args.expression; + const matchStrings = args.matchStrings; + const nonMatchStrings = args.nonMatchStrings; + const allStrings = matchStrings.join(''); + if (!regExp.test(allStrings)) { + for (const string of matchStrings) { + assert( + regExp.test(string), + `\`${ expression }\` should match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } + + const allNonMatchStrings = nonMatchStrings.join(''); + if (regExp.test(allNonMatchStrings)) { + for (const string of nonMatchStrings) { + assert( + !regExp.test(string), + `\`${ expression }\` should not match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } +} + +// Returns a function that validates a RegExp match result. // // Example: // diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A10.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A10.js index ade262832dda..30f70bedace2 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A10.js @@ -7,19 +7,22 @@ es5id: 15.10.6.2_A10 description: Checking if varying the RegExp.prototype.exec.length property fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (RegExp.prototype.exec.hasOwnProperty('length') !== true) { - throw new Test262Error('#1: RegExp.prototype.exec.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + RegExp.prototype.exec.hasOwnProperty('length'), + true, + 'RegExp.prototype.exec.hasOwnProperty(\'length\') must return true' +); var __obj = RegExp.prototype.exec.length; verifyNotWritable(RegExp.prototype.exec, "length", null, function(){return "shifted";}); -//CHECK#2 -if (RegExp.prototype.exec.length !== __obj) { - throw new Test262Error('#2: __obj = RegExp.prototype.exec.length; RegExp.prototype.exec.length = function(){return "shifted";}; RegExp.prototype.exec.length === __obj. Actual: ' + (RegExp.prototype.exec.length)); -} +assert.sameValue( + RegExp.prototype.exec.length, + __obj, + 'The value of RegExp.prototype.exec.length is expected to equal the value of __obj' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A11.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A11.js index df136276dabd..2cd62c397fe9 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A11.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A11.js @@ -6,15 +6,12 @@ info: The length property of the exec method is 1 es5id: 15.10.6.2_A11 description: Checking RegExp.prototype.exec.length ---*/ +assert.sameValue( + RegExp.prototype.exec.hasOwnProperty("length"), + true, + 'RegExp.prototype.exec.hasOwnProperty("length") must return true' +); -//CHECK#1 -if (RegExp.prototype.exec.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: RegExp.prototype.exec.hasOwnProperty(\'length\') === true'); -} - -//CHECK#2 -if (RegExp.prototype.exec.length !== 1) { - throw new Test262Error('#2: RegExp.prototype.exec.length === 1. Actual: ' + (RegExp.prototype.exec.length)); -} +assert.sameValue(RegExp.prototype.exec.length, 1, 'The value of RegExp.prototype.exec.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A12.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A12.js index 328c71cc2e25..86c5b5794590 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A12.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A12.js @@ -9,11 +9,7 @@ description: Checking RegExp.prototype.exec (/foo/).test('xfoox'); var match = new RegExp('(.|\r|\n)*','').exec()[0]; -if (match === 'xfoox') { - throw new Test262Error('#1: regExp.exec() leaks match globally'); -} -if (match !== 'undefined') { - throw new Test262Error('#2: regExp.exec() must coerce absent first arg to "undefined"'); -} +assert.notSameValue(match, 'xfoox', 'The value of match is not "xfoox"'); +assert.sameValue(match, 'undefined', 'The value of match is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T1.js index 47da61758ac4..afbac70c616e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T1.js @@ -15,31 +15,36 @@ var __expected = ["1"]; __expected.index=0; __expected.input="123"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /1|12/.exec("123"); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /1|12/.exec("123"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /1|12/.exec("123"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /1|12/.exec("123"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /1|12/.exec("123"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T10.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T10.js index d21f8e7f5888..8da723954490 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T10.js @@ -15,31 +15,36 @@ var __expected = ["1"]; __expected.index=0; __expected.input="1.01"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /1|12/.exec(1.01); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /1|12/.exec(1.01); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /1|12/.exec(1.01); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /1|12/.exec(1.01); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /1|12/.exec(1.01); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T11.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T11.js index b67eef47f3cf..826e9f1f0b8c 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T11.js @@ -15,31 +15,36 @@ var __expected = ["12"]; __expected.index=3; __expected.input="1.012"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /2|12/.exec(new Number(1.012)); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /2|12/.exec(new Number(1.012)); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /2|12/.exec(new Number(1.012)); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /2|12/.exec(new Number(1.012)); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /2|12/.exec(new Number(1.012)); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T12.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T12.js index 9e8446d2ce63..25924e5aa6ef 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T12.js @@ -17,31 +17,36 @@ var __expected = [".14"]; __expected.index=1; __expected.input=String(Math.PI); -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /\\.14/.exec({toString:function(){return Math.PI}}); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /\\.14/.exec({toString:function(){return Math.PI}}); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /\\.14/.exec({toString:function(){return Math.PI}}); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /\\.14/.exec({toString:function(){return Math.PI}}); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /\\.14/.exec({toString:function(){return Math.PI}}); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T13.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T13.js index 5f71297328ca..c727f0db2b70 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T13.js @@ -15,31 +15,36 @@ var __expected = ["tr"]; __expected.index=0; __expected.input="true"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /t[a-b|q-s]/.exec(true); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /t[a-b|q-s]/.exec(true); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /t[a-b|q-s]/.exec(true); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /t[a-b|q-s]/.exec(true); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /t[a-b|q-s]/.exec(true); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T14.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T14.js index 4d27ce29c0a0..4b447fc4512f 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T14.js @@ -15,31 +15,36 @@ var __expected = ["se"]; __expected.index=3; __expected.input="false"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /AL|se/.exec(new Boolean); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /AL|se/.exec(new Boolean); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /AL|se/.exec(new Boolean); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /AL|se/.exec(new Boolean); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /AL|se/.exec(new Boolean); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T15.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T15.js index d4e47eeb8fbb..37eb4c668914 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T15.js @@ -15,31 +15,36 @@ var __expected = ["ls"]; __expected.index=2; __expected.input="false"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /LS/i.exec({toString:function(){return false}}); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /LS/i.exec({toString:function(){return false}}); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /LS/i.exec({toString:function(){return false}}); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /LS/i.exec({toString:function(){return false}}); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /LS/i.exec({toString:function(){return false}}); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T16.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T16.js index 5f7024925dde..45318b1bf6b1 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T16.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T16.js @@ -10,8 +10,6 @@ description: RegExp is /undefined/ and call exec() without arguments ---*/ var __re = /undefined/.exec()[0]; -if (__re !== "undefined") { - throw new Test262Error('#1: /undefined/.exec()[0] === "undefined". Actual: ' + (__re)); -} +assert.sameValue(__re, "undefined", 'The value of __re is expected to be "undefined"'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T17.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T17.js index dec0acf5df70..ed4f5280de62 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T17.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T17.js @@ -15,31 +15,36 @@ var __expected = ["ll"]; __expected.index=2; __expected.input="null"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /ll|l/.exec(null); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /ll|l/.exec(null); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /ll|l/.exec(null); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /ll|l/.exec(null); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /ll|l/.exec(null); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T18.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T18.js index 1943f03723c2..4682802f69f6 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T18.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T18.js @@ -15,31 +15,36 @@ var __expected = ["nd"]; __expected.index=1; __expected.input="undefined"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /nd|ne/.exec(undefined); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /nd|ne/.exec(undefined); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /nd|ne/.exec(undefined); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /nd|ne/.exec(undefined); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /nd|ne/.exec(undefined); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T19.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T19.js index eb80082277fc..1a904a79dfa3 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T19.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T19.js @@ -15,31 +15,36 @@ var __expected = ["e"]; __expected.index=3; __expected.input="undefined"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /e{1}/.exec(void 0); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /e{1}/.exec(void 0); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /e{1}/.exec(void 0); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /e{1}/.exec(void 0); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /e{1}/.exec(void 0); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T2.js index f6cb91af8070..1260136aa123 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T2.js @@ -16,31 +16,36 @@ var __expected = ["123", "1", "1", undefined, "23", undefined, "23"]; __expected.index=0; __expected.input="123"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __re = /((1)|(12))((3)|(23))/; __executed = __re.exec(new String("123"));} (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /((1)|(12))((3)|(23))/; __executed = __re.exec(new String("123"));} __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /((1)|(12))((3)|(23))/; __executed = __re.exec(new String("123"));} __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /((1)|(12))((3)|(23))/; __executed = __re.exec(new String("123"));} __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /((1)|(12))((3)|(23))/; __executed = __re.exec(new String("123"));} __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T20.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T20.js index 425c264c3413..338e7ef05f69 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T20.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T20.js @@ -15,31 +15,36 @@ var __expected = ["ed"]; __expected.index=7; __expected.input="undefined"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /[a-f]d/.exec(x); var x; (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[a-f]d/.exec(x); var x; __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[a-f]d/.exec(x); var x; __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[a-f]d/.exec(x); var x; __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[a-f]d/.exec(x); var x; __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } var x; diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T21.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T21.js index 12aceec43a43..f35ae8d538d1 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T21.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T21.js @@ -15,31 +15,36 @@ var __expected = ["un"]; __expected.index=0; __expected.input="undefined"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /[a-z]n/.exec(function(){}()); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /[a-z]n/.exec(function(){}()); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /[a-z]n/.exec(function(){}()); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /[a-z]n/.exec(function(){}()); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /[a-z]n/.exec(function(){}()); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T3.js index 0b83bab6721e..c6e0d2f77598 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T3.js @@ -15,31 +15,36 @@ var __expected = ["abcde"]; __expected.index=0; __expected.input="abcdefghi"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /a[a-z]{2,4}/.exec(new Object("abcdefghi")); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a[a-z]{2,4}/.exec(new Object("abcdefghi")); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a[a-z]{2,4}/.exec(new Object("abcdefghi")); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a[a-z]{2,4}/.exec(new Object("abcdefghi")); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a[a-z]{2,4}/.exec(new Object("abcdefghi")); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T4.js index 5654fc4f0018..fc4bdb79c72b 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T4.js @@ -17,31 +17,36 @@ var __expected = ["abc"]; __expected.index=0; __expected.input="abcdefghi"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /a[a-z]{2,4}?/.exec({toString:function(){return "abcdefghi"}}); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /a[a-z]{2,4}?/.exec({toString:function(){return "abcdefghi"}}); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /a[a-z]{2,4}?/.exec({toString:function(){return "abcdefghi"}}); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /a[a-z]{2,4}?/.exec({toString:function(){return "abcdefghi"}}); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /a[a-z]{2,4}?/.exec({toString:function(){return "abcdefghi"}}); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T5.js index fedd83e33fd8..228127b9cd91 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T5.js @@ -18,31 +18,36 @@ var __expected = ["aaba", "ba"]; __expected.index=0; __expected.input="aabaac"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /(aa|aabaac|ba|b|c)*/.exec({toString:function(){return {};}, valueOf:function(){return "aabaac";}}); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(aa|aabaac|ba|b|c)*/.exec({toString:function(){return {};}, valueOf:function(){return "aabaac";}}); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(aa|aabaac|ba|b|c)*/.exec({toString:function(){return {};}, valueOf:function(){return "aabaac";}}); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(aa|aabaac|ba|b|c)*/.exec({toString:function(){return {};}, valueOf:function(){return "aabaac";}}); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(aa|aabaac|ba|b|c)*/.exec({toString:function(){return {};}, valueOf:function(){return "aabaac";}}); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js index a01d86d7d7e6..a06db4b6ebcd 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js @@ -17,31 +17,36 @@ var __expected = ["zaacbbbcac", "z", "ac", "a", undefined, "c"]; __expected.index=0; __expected.input="zaacbbbcac"; -//CHECK#0 -if ((__executed instanceof Array) !== true) { - throw new Test262Error('#0: __executed = /(z)((a+)?(b+)?(c))*/.exec((function(){return "zaacbbbcac"})()); (__executed instanceof Array) === true'); -} +assert.sameValue( + __executed instanceof Array, + true, + 'The result of evaluating (__executed instanceof Array) is expected to be true' +); -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __executed = /(z)((a+)?(b+)?(c))*/.exec((function(){return "zaacbbbcac"})()); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __executed = /(z)((a+)?(b+)?(c))*/.exec((function(){return "zaacbbbcac"})()); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __executed = /(z)((a+)?(b+)?(c))*/.exec((function(){return "zaacbbbcac"})()); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __executed = /(z)((a+)?(b+)?(c))*/.exec((function(){return "zaacbbbcac"})()); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T7.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T7.js index bd0003de57d6..8d51e48ea16c 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T7.js @@ -11,13 +11,12 @@ description: > /[a-z]/ ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: /[a-z]/.exec({toString:function(){throw "intostr"}}) throw "intostr". Actual: ' + (/[a-z]/.exec({toString:function(){throw "intostr"}}))); + throw new Test262Error('#1.1: /[a-z]/.exec({toString:function(){throw "intostr"}}) throw "intostr". Actual: ' + (/[a-z]/.exec({toString:function(){throw "intostr"}}))); } catch (e) { - if (e !== "intostr") { - throw new Test262Error('#1.2: /[a-z]/.exec({toString:function(){throw "intostr"}}) throw "intostr". Actual: ' + (e)); - } + assert.sameValue(e, "intostr", 'The value of e is expected to be "intostr"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T8.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T8.js index a959aacc61bf..c842675bb816 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T8.js @@ -11,13 +11,12 @@ description: > and RegExp is /[a-z]/ ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[a-z]/.exec({toString:void 0, valueOf:function(){throw "invalof"}}) throw "invalof". Actual: ' + (/[a-z]/.exec({toString:void 0, valueOf:function(){throw "invalof"}}))); } catch (e) { - if (e !== "invalof") { - throw new Test262Error('#1.2: /[a-z]/.exec({toString:void 0, valueOf:function(){throw "invalof"}}) throw "invalof". Actual: ' + (e)); - } + assert.sameValue(e, "invalof", 'The value of e is expected to be "invalof"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T9.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T9.js index a6eab8f7f65a..42bda957e5e7 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T9.js @@ -11,12 +11,9 @@ description: String is undefined variable and RegExp is /1|12/ var __string; -//CHECK#1 var __re = /1|12/; -if (__re.exec(__string) !== null) { - throw new Test262Error('#1: var __string; /1|12/.exec(__string) === null; function __string(){}. Actual: ' + (__re)); -} +assert.sameValue(__re.exec(__string), null, '__re.exec() must return null'); -function __string(){}; +function __string(){} reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T1.js index bcc3bc686edd..160fe731cd14 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T1.js @@ -13,13 +13,16 @@ var __instance = new Object; __instance.exec = RegExp.prototype.exec; -//CHECK#1 try { - throw new Test262Error('#1.1: __instance = new Object; __instance.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); + throw new Test262Error('#1.1: __instance = new Object; __instance.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = new Object; __instance.exec = RegExp.prototype.exec. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T10.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T10.js index b3061247e77e..377601dd09f6 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T10.js @@ -11,13 +11,16 @@ description: The tested object is undefined var exec = RegExp.prototype.exec; -//CHECK#1 try { - throw new Test262Error('#1.1: exec = RegExp.prototype.exec; exec("message to investigate"). Actual: ' + (exec("message to investigate"))); + throw new Test262Error('#1.1: exec = RegExp.prototype.exec; exec("message to investigate"). Actual: ' + (exec("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: exec = RegExp.prototype.exec; exec("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T2.js index 7ee44fd196f9..b00031334e8e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T2.js @@ -13,14 +13,17 @@ var __instance = Math; __instance.exec = RegExp.prototype.exec; -//CHECK#1 try { __instance.exec("message to investigate"); - throw new Test262Error('#1.1: __instance = Math; __instance.exec = RegExp.prototype.exec; __instance.exec("message to investigate")'); + throw new Test262Error('#1.1: __instance = Math; __instance.exec = RegExp.prototype.exec; __instance.exec("message to investigate")'); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = Math; __instance.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T3.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T3.js index 911fcee8903d..36cedabf51c8 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T3.js @@ -11,16 +11,19 @@ description: The tested object is function object __instance.exec = RegExp.prototype.exec; -//CHECK#1 try { __instance.exec("message to investigate"); - throw new Test262Error('#1.1: __instance.exec = RegExp.prototype.exec; __instance.exec("message to investigate"); function __instance(){}'); + throw new Test262Error('#1.1: __instance.exec = RegExp.prototype.exec; __instance.exec("message to investigate"); function __instance(){}'); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance.exec = RegExp.prototype.exec; __instance.exec("message to investigate"); function __instance(){}. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } function __instance(){}; +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T4.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T4.js index 91f5e1b39086..5cf0ba8d349f 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T4.js @@ -13,13 +13,16 @@ var __instance = new String("[a-b]"); __instance.exec = RegExp.prototype.exec; -//CHECK#1 try { - throw new Test262Error('#1.1: __instance = new String("[a-b]"); __instance.exec = RegExp.prototype.exec; exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); + throw new Test262Error('#1.1: __instance = new String("[a-b]"); __instance.exec = RegExp.prototype.exec; exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = new String("[a-b]"); __instance.exec = RegExp.prototype.exec; exec("message to investigate"). Actual: ' + (e)); - } - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); + } + +// TODO: Convert to assert.throws() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T5.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T5.js index eb9712a6751d..4128d2a5c04e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T5.js @@ -13,13 +13,16 @@ var __instance = new Boolean(false); __instance.exec = RegExp.prototype.exec; -//CHECK#1 try { throw new Test262Error('#1.1: __instance = new Boolean(false); __instance.exec = RegExp.prototype.exec; exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); } catch (e) { - if ((e instanceof TypeError !== true)) { - throw new Test262Error('#1.2: __instance = new Boolean(false); __instance.exec = RegExp.prototype.exec; exec("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T6.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T6.js index b2dd4f4bd1d1..ebbb2a8a2aef 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T6.js @@ -13,13 +13,16 @@ var __instance = new Number(1.0); __instance.exec = RegExp.prototype.exec; -//CHECK#1 try { - throw new Test262Error('#1.1: __instance = new Number(1.0); __instance.exec = RegExp.prototype.exec; __instance["exec"]("message to investigate"). Actual: ' + (__instance["exec"]("message to investigate"))); + throw new Test262Error('#1.1: __instance = new Number(1.0); __instance.exec = RegExp.prototype.exec; __instance["exec"]("message to investigate"). Actual: ' + (__instance["exec"]("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = new Number(1.0); __instance.exec = RegExp.prototype.exec; __instance["exec"]("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T7.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T7.js index a2baf4005488..be09f460f821 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T7.js @@ -13,13 +13,16 @@ var __instance = false; Object.prototype.exec = RegExp.prototype.exec; -//CHECK#1 try { - throw new Test262Error('#1.1: __instance = false; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); + throw new Test262Error('#1.1: __instance = false; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = false; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T8.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T8.js index ff6299c6bd78..4118289d6f3c 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T8.js @@ -13,13 +13,16 @@ var __instance = "."; Object.prototype.exec = RegExp.prototype.exec; -//CHECK#1 try { - throw new Test262Error('#1.1: __instance = "."; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); + throw new Test262Error('#1.1: __instance = "."; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = "."; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T9.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T9.js index ab2b7ef6b636..83f8f5945a33 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A2_T9.js @@ -13,13 +13,16 @@ var __instance = 1.0; Object.prototype.exec = RegExp.prototype.exec; -//CHECK#1 try { - throw new Test262Error('#1.1: __instance = 1.0; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); + throw new Test262Error('#1.1: __instance = 1.0; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (__instance.exec("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = 1.0; Object.prototype.exec = RegExp.prototype.exec; __instance.exec("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T1.js index 8d195223dbaf..52d3ccc26dcd 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T1.js @@ -25,16 +25,18 @@ do{ } }while(true); -//CHECK#1 -if (__expected.length !== __matched.length) { - throw new Test262Error('#1: __executed = /(?:ab|cd)\\d?/g.exec("ab cd2 ab34 cd"); __matched.length === ' + (__expected.length) + '.Actual: ' + (__matched.length)); -} +assert.sameValue( + __expected.length, + __matched.length, + 'The value of __expected.length is expected to equal the value of __matched.length' +); -//CHECK#2 for(var index=0; index<__expected.length; index++) { - if (__expected[index] !== __matched[index]) { - throw new Test262Error('#2: __executed = /(?:ab|cd)\\d?/g.exec("ab cd2 ab34 cd"); __matched[' + index + '] === ' + __expected[index] + '. Actual: ' + __matched[index]); - } + assert.sameValue( + __expected[index], + __matched[index], + 'The value of __expected[index] is expected to equal the value of __matched[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T2.js index 142eb6dc10f6..2c9c8b51715f 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T2.js @@ -134,23 +134,20 @@ var __the__raven = " Once upon a midnight dreary, while I pondered weak and wear "And my soul from out that shadow that lies floating on the floor" + "Shall be lifted - nevermore!" -var NEVERMORE=11; - +var NEVERMORE=11; + var __re = /[Nn]evermore/g; var __matched=0; do{ var __executed = __re.exec(__the__raven); if (__executed !== null) { - __matched++; + __matched++; } else { - break; + break; } }while(1); -//CHECK#1 -if (__matched !== NEVERMORE) { - throw new Test262Error('#1: __re = /[Nn]evermore/g; __executed = __re.exec(__the__raven)'+__matched); -} +assert.sameValue(__matched, NEVERMORE, 'The value of __matched is expected to equal the value of NEVERMORE'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T3.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T3.js index 78f8a6c2a51c..dec512cc87ca 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T3.js @@ -134,23 +134,24 @@ var __the__raven = " Once upon a midnight dreary, while I pondered weak and wear "And my soul from out that shadow that lies floating on the floor" + "Shall be lifted - nevermore!" -var NEVERMORE_AND_EVERMORE=12; - +var NEVERMORE_AND_EVERMORE=12; + var __re = /[Nn]?evermore/g; var __matched=0; do{ var __executed = __re.exec(__the__raven); if (__executed !== null) { - __matched++; + __matched++; } else { - break; + break; } }while(1); -//CHECK#1 -if (__matched !== NEVERMORE_AND_EVERMORE) { - throw new Test262Error('#1: __re = /[Nn]?evermore/g; __executed = __re.exec(__the__raven)'+__matched); -} +assert.sameValue( + __matched, + NEVERMORE_AND_EVERMORE, + 'The value of __matched is expected to equal the value of NEVERMORE_AND_EVERMORE' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T4.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T4.js index 38a81f287aa4..dd54ccca23bb 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T4.js @@ -136,23 +136,24 @@ var __the__raven = " Once upon a midnight dreary, while I pondered weak and wear "And my soul from out that shadow that lies floating on the floor" + "Shall be lifted - nevermore!" -var ALL_THE_HOPELESS_MORE=18; - +var ALL_THE_HOPELESS_MORE=18; + var __re = /([Nn]?ever|([Nn]othing\s{1,}))more/g; var __matched=0; do{ var __executed = __re.exec(__the__raven); if (__executed !== null) { - __matched++; + __matched++; } else { - break; + break; } }while(1); -//CHECK#1 -if (__matched !== ALL_THE_HOPELESS_MORE) { - throw new Test262Error('#1: __re = /([Nn]?ever|([Nn]othing\\s{1,}))more/g; __executed = __re.exec(__the__raven)'+__matched); -} +assert.sameValue( + __matched, + ALL_THE_HOPELESS_MORE, + 'The value of __matched is expected to equal the value of ALL_THE_HOPELESS_MORE' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T5.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T5.js index 4036b062ff88..a457312611d7 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T5.js @@ -19,22 +19,24 @@ var __expected = ["123","456","789"]; do{ var __executed = __re.exec("123 456 789"); if (__executed !== null) { - __matched.push(__executed[0]); + __matched.push(__executed[0]); } else { - break; + break; } }while(true); -//CHECK#1 -if (__expected.length !== __matched.length) { - throw new Test262Error('#1: __executed = /\\d+/g.exec("123 456 789"); __matched.length === ' + (__expected.length) + '.Actual: ' + (__matched.length)); -} +assert.sameValue( + __expected.length, + __matched.length, + 'The value of __expected.length is expected to equal the value of __matched.length' +); -//CHECK#2 for(var index=0; index<__expected.length; index++) { - if (__expected[index] !== __matched[index]) { - throw new Test262Error('#2: __executed = /\\d+/g.exec("123 456 789"); __matched[' + index + '] === ' + __expected[index] + '. Actual: ' + __matched[index]); - } + assert.sameValue( + __expected[index], + __matched[index], + 'The value of __expected[index] is expected to equal the value of __matched[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T6.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T6.js index c8195fff2dbf..4c4c1491a693 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T6.js @@ -19,22 +19,24 @@ var __expected = ["123","456","789"]; do{ var __executed = __re.exec("123 456 789"); if (__executed !== null) { - __matched.push(__executed[0]); + __matched.push(__executed[0]); } else { - break; + break; } }while(true); -//CHECK#1 -if (__expected.length !== __matched.length) { - throw new Test262Error('#1: __executed = /(\\d+)/g.exec("123 456 789"); __matched.length === ' + (__expected.length) + '.Actual: ' + (__matched.length)); -} +assert.sameValue( + __expected.length, + __matched.length, + 'The value of __expected.length is expected to equal the value of __matched.length' +); -//CHECK#2 for(var index=0; index<__expected.length; index++) { - if (__expected[index] !== __matched[index]) { - throw new Test262Error('#2: __executed = /(\\d+)/g.exec("123 456 789"); __matched[' + index + '] === ' + __expected[index] + '. Actual: ' + __matched[index]); - } + assert.sameValue( + __expected[index], + __matched[index], + 'The value of __expected[index] is expected to equal the value of __matched[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T7.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T7.js index 6ea8a74ba1c5..75232f1ea334 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A3_T7.js @@ -19,22 +19,24 @@ var __expected = ["123","123","123","123","123","123","123","123","123","123"]; do{ var __executed = __re.exec("123 456 789"); if (__executed !== null) { - __matched.push(__executed[0]); + __matched.push(__executed[0]); } else { - break; + break; } }while(__matched.length<10); -//CHECK#1 -if (__expected.length !== __matched.length) { - throw new Test262Error('#1: __executed = /\\d+/.exec("123 456 789"); __matched.length === ' + (__expected.length) + '.Actual: ' + (__matched.length)); -} +assert.sameValue( + __expected.length, + __matched.length, + 'The value of __expected.length is expected to equal the value of __matched.length' +); -//CHECK#2 for(var index=0; index<__expected.length; index++) { - if (__expected[index] !== __matched[index]) { - throw new Test262Error('#2: __executed = /\\d+/.exec("123 456 789"); __matched[' + index + '] === ' + __expected[index] + '. Actual: ' + __matched[index]); - } + assert.sameValue( + __expected[index], + __matched[index], + 'The value of __expected[index] is expected to equal the value of __matched[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T1.js index bfe0b403670a..22fa38839843 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T1.js @@ -17,26 +17,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = 12; @@ -47,26 +51,30 @@ __expected = ["ab4"]; __expected.index = 17; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = 12; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = 12; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = 12; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = 12; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T10.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T10.js index ab7dd9ca450e..5c3cbd0ff490 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T10.js @@ -19,26 +19,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } var __obj = {valueOf:function(){return 12;}}; @@ -51,26 +55,30 @@ __expected = ["ab4"]; __expected.index = 17; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __obj = {valueOf:function(){return 12;}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __obj = {valueOf:function(){return 12;}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __obj = {valueOf:function(){return 12;}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __obj = {valueOf:function(){return 12;}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T11.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T11.js index 07ca3aa7af33..6d8559da5672 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T11.js @@ -19,39 +19,42 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } var __obj = {valueOf:function(){throw "intoint";}}; __re.lastIndex = __obj; -//CHECK#5 try { throw new Test262Error('#5.1: __obj = {valueOf:function(){throw "intoint";}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42") throw "intoint". Actual: ' + (__re.exec("aacd2233ab12nm444ab42"))); } catch (e) { - if (e !== "intoint") { - throw new Test262Error('#5.2: __obj = {valueOf:function(){throw "intoint";}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42") throw "intoint". Actual: ' + (e)); - } + assert.sameValue(e, "intoint", 'The value of e is expected to be "intoint"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T12.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T12.js index e839dbc8df1a..f9e6a6df3810 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T12.js @@ -20,26 +20,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } var __obj = {toString:function(){return 12;},valueOf:function(){return {};}}; @@ -52,26 +56,30 @@ __expected = ["ab4"]; __expected.index = 17; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __obj = {toString:function(){return 12;},valueOf:function(){return {};}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __obj = {toString:function(){return 12;},valueOf:function(){return {};}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __obj = {toString:function(){return 12;},valueOf:function(){return {};}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __obj = {toString:function(){return 12;},valueOf:function(){return {};}}; __re.lastIndex = __obj; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T2.js index f7f053413eaf..cc3d4a67eeb7 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T2.js @@ -19,26 +19,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = undefined; @@ -49,26 +53,30 @@ __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = undefined; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = undefined; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = undefined; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = undefined; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T3.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T3.js index b7a4e02b1b01..eec144fd7285 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T3.js @@ -17,26 +17,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = void 0; @@ -47,26 +51,30 @@ __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = void 0; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = void 0; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = void 0; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = void 0; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T4.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T4.js index 45dbf539949b..b87cb4b9f0c6 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T4.js @@ -17,26 +17,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = null; @@ -47,26 +51,30 @@ __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = null; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = null; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = null; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = null; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T5.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T5.js index ae1fca0c7818..00e8e21fc3a3 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T5.js @@ -19,26 +19,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = x; @@ -49,26 +53,30 @@ __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = x; __executed = __re.exec("aacd2233ab12nm444ab42"); var x; __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = x; __executed = __re.exec("aacd2233ab12nm444ab42"); var x; __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = x; __executed = __re.exec("aacd2233ab12nm444ab42"); var x; __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = x; __executed = __re.exec("aacd2233ab12nm444ab42"); var x; __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } var x; diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T6.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T6.js index 30c4c74ff93c..ccd2eff07c37 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T6.js @@ -17,26 +17,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = false; @@ -47,26 +51,30 @@ __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = false; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = false; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = false; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = false; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T7.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T7.js index c9adc412a8ec..5d90fa04351a 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T7.js @@ -19,26 +19,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = Math.NaN; @@ -49,26 +53,30 @@ __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = Math.NaN; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = Math.NaN; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = Math.NaN; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; re.lastIndex = Math.NaN; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T8.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T8.js index cd5ef0775efe..77c7f9c4d4e2 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T8.js @@ -17,26 +17,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = "12"; @@ -47,26 +51,30 @@ __expected = ["ab4"]; __expected.index = 17; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = "12"; __executed = __re.exec("aacd2233ab12nm444ab42");__executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = "12"; __executed = __re.exec("aacd2233ab12nm444ab42");__executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = "12"; __executed = __re.exec("aacd2233ab12nm444ab42");__executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = "12"; __executed = __re.exec("aacd2233ab12nm444ab42");__executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T9.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T9.js index ff0021801b0c..dc4902a6bbdb 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A4_T9.js @@ -19,26 +19,30 @@ var __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __re.lastIndex = "eleven"; @@ -49,26 +53,30 @@ __expected = ["cd2"]; __expected.index = 2; __expected.input = "aacd2233ab12nm444ab42"; -//CHECK#5 -if (__executed.length !== __expected.length) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = "eleven"; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#6 -if (__executed.index !== __expected.index) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = "eleven"; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#7 -if (__executed.input !== __expected.input) { - throw new Test262Error('#7: __re = /(?:ab|cd)\\d?/g; __re.lastIndex = "eleven"; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#8 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#8: __re = /(?:ab|cd)\\d?/g;__re.lastIndex = "eleven"; __executed = __re.exec("aacd2233ab12nm444ab42"); __executed = __re.exec("aacd2233ab12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T1.js index 2cabc6550b37..c290de421b23 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T1.js @@ -19,38 +19,35 @@ var __expected = ["ab4"]; __expected.index = 21; __expected.input = "aac1dz2233a1bz12nm444ab42"; -//CHECK#1 -if (__executed.length !== __expected.length) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aac1dz2233a1bz12nm444ab42"); __executed.length === ' + __expected.length + '. Actual: ' + __executed.length); -} +assert.sameValue( + __executed.length, + __expected.length, + 'The value of __executed.length is expected to equal the value of __expected.length' +); -//CHECK#2 -if (__executed.index !== __expected.index) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aac1dz2233a1bz12nm444ab42"); __executed.index === ' + __expected.index + '. Actual: ' + __executed.index); -} +assert.sameValue( + __executed.index, + __expected.index, + 'The value of __executed.index is expected to equal the value of __expected.index' +); -//CHECK#3 -if (__executed.input !== __expected.input) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aac1dz2233a1bz12nm444ab42"); __executed.input === ' + __expected.input + '. Actual: ' + __executed.input); -} +assert.sameValue( + __executed.input, + __expected.input, + 'The value of __executed.input is expected to equal the value of __expected.input' +); -//CHECK#4 for(var index=0; index<__expected.length; index++) { - if (__executed[index] !== __expected[index]) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aac1dz2233a1bz12nm444ab42"); __executed[' + index + '] === ' + __expected[index] + '. Actual: ' + __executed[index]); - } + assert.sameValue( + __executed[index], + __expected[index], + 'The value of __executed[index] is expected to equal the value of __expected[index]' + ); } __executed = __re.exec("aacd22"); -//CHECK#5 -if (__executed) { - throw new Test262Error('#5: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd22"); __executed === true'); -} - -//CHECK#6 -if (__re.lastIndex !== 0) { - throw new Test262Error('#6: __re = /(?:ab|cd)\\d?/g; __executed = __re.exec("aacd22"); __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} +assert(!__executed, 'The value of !__executed is expected to be true'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T2.js index b6fe126120f8..5661d8d60931 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T2.js @@ -14,14 +14,7 @@ var __re = /(?:ab|cd)\d?/g; __re.lastIndex=100; var __executed = __re.exec("aacd22 "); -//CHECK#1 -if (__executed) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=100; __executed = __re.exec("aacd22 "); __executed === true'); -} - -//CHECK#2 -if (__re.lastIndex !== 0) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=100; __executed = __re.exec("aacd22 "); __re.lastIndex === 0. Actual: ' + (__re.lastIndex)); -} +assert(!__executed, 'The value of !__executed is expected to be true'); +assert.sameValue(__re.lastIndex, 0, 'The value of __re.lastIndex is expected to be 0'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3.js index cfbd306ca717..274ae6775fe9 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3.js @@ -14,27 +14,13 @@ var __re = /(?:ab|cd)\d?/g; __re.lastIndex=-1; var __executed = __re.exec("aacd22 "); -//CHECK#1 -if (__executed[0] !== "cd2") { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=-1; __executed = __re.exec("aacd22 "); __executed[0] === "cd2"'); -} - -//CHECK#2 -if (__re.lastIndex !== 5) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=-1; __executed = __re.exec("aacd22 "); __re.lastIndex === 5. Actual: ' + (__re.lastIndex)); -} +assert.sameValue(__executed[0], "cd2", 'The value of __executed[0] is expected to be "cd2"'); +assert.sameValue(__re.lastIndex, 5, 'The value of __re.lastIndex is expected to be 5'); __re.lastIndex=-100; __executed = __re.exec("aacd22 "); -//CHECK#3 -if (__executed[0] !== "cd2") { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=-1; __executed = __re.exec("aacd22 "); __re.lastIndex=-100; __executed = __re.exec("aacd22 "); __executed[0] === "cd2"'); -} - -//CHECK#4 -if (__re.lastIndex !== 5) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=-1; __executed = __re.exec("aacd22 "); __re.lastIndex=-100; __executed = __re.exec("aacd22 "); __re.lastIndex === 5. Actual: ' + (__re.lastIndex)); -} +assert.sameValue(__executed[0], "cd2", 'The value of __executed[0] is expected to be "cd2"'); +assert.sameValue(__re.lastIndex, 5, 'The value of __re.lastIndex is expected to be 5'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A6.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A6.js index 59be6c1c797f..87f4b0238f63 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A6.js @@ -6,10 +6,10 @@ info: RegExp.prototype.exec has not prototype property es5id: 15.10.6.2_A6 description: Checking RegExp.prototype.exec.prototype ---*/ - -//CHECK#1 -if (RegExp.prototype.exec.prototype !== undefined) { - throw new Test262Error('#1: RegExp.prototype.exec.prototype === undefined. Actual: ' + (RegExp.prototype.exec.prototype)); -} +assert.sameValue( + RegExp.prototype.exec.prototype, + undefined, + 'The value of RegExp.prototype.exec.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A7.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A7.js index 0df521e23863..f5ac4392c152 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A7.js @@ -13,9 +13,13 @@ try { var __instance = new __FACTORY; throw new Test262Error('#1.1: __FACTORY = RegExp.prototype.exec throw TypeError. Actual: ' + (__instance)); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __FACTORY = RegExp.prototype.exec throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A8.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A8.js index 816acd82dfc7..bef663772f28 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A8.js @@ -8,26 +8,28 @@ description: > Checking if enumerating the RegExp.prototype.exec.length property fails ---*/ +assert.sameValue( + RegExp.prototype.exec.hasOwnProperty('length'), + true, + 'RegExp.prototype.exec.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if (RegExp.prototype.exec.hasOwnProperty('length') !== true) { - throw new Test262Error('#0: RegExp.prototype.exec.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + RegExp.prototype.exec.propertyIsEnumerable('length'), + false, + 'RegExp.prototype.exec.propertyIsEnumerable(\'length\') must return false' +); - //CHECK#1 -if (RegExp.prototype.exec.propertyIsEnumerable('length') !== false) { - throw new Test262Error('#1: RegExp.prototype.exec.propertyIsEnumerable(\'length\') === true'); -} - - //CHECK#2 var count=0; for (var p in RegExp.prototype.exec){ - if (p==="length") count++; + if (p==="length") { + count++; + } } -if (count !== 0) { - throw new Test262Error('#2: count = 0; for (p in RegExp.prototype.exec){ if (p==="length") count++; } count === 0. Actual: ' + (count)); -} +assert.sameValue(count, 0, 'The value of count is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A9.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A9.js index 199bbbc54e5f..ec0dda3895a1 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/S15.10.6.2_A9.js @@ -10,20 +10,24 @@ description: > Checking if deleting the RegExp.prototype.exec.length property fails ---*/ +assert.sameValue( + RegExp.prototype.exec.hasOwnProperty('length'), + true, + 'RegExp.prototype.exec.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if ((RegExp.prototype.exec.hasOwnProperty('length') !== true)) { - throw new Test262Error('#0: RegExp.prototype.exec.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + delete RegExp.prototype.exec.length, + true, + 'The value of `delete RegExp.prototype.exec.length` is expected to be true' +); -//CHECK#1 -if (delete RegExp.prototype.exec.length !== true) { - throw new Test262Error('#1: delete RegExp.prototype.exec.length === true'); -} +assert.sameValue( + RegExp.prototype.exec.hasOwnProperty('length'), + false, + 'RegExp.prototype.exec.hasOwnProperty(\'length\') must return false' +); -//CHECK#2 -if (RegExp.prototype.exec.hasOwnProperty('length') !== false) { - throw new Test262Error('#2: delete RegExp.prototype.exec.length; RegExp.prototype.exec.hasOwnProperty(\'length\') === false'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/exec/failure-lastindex-set.js b/js/src/tests/test262/built-ins/RegExp/prototype/exec/failure-lastindex-set.js new file mode 100644 index 000000000000..afa5f73f859c --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/prototype/exec/failure-lastindex-set.js @@ -0,0 +1,73 @@ +// Copyright (C) 2021 Richard Gibson. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + lastIndex is set to 0 after exhausting the string when global and/or sticky are set. +esid: sec-regexpbuiltinexec +info: | + RegExpBuiltinExec ( + _R_: an initialized RegExp instance, + _S_: a String, + ) + ... + 1. Let _length_ be the number of code units in _S_. + 2. Let _lastIndex_ be ℝ(? ToLength(? Get(_R_, *"lastIndex"*))). + 3. Let _flags_ be _R_.[[OriginalFlags]]. + 4. If _flags_ contains *"g"*, let _global_ be *true*; else let _global_ be *false*. + 5. If _flags_ contains *"y"*, let _sticky_ be *true*; else let _sticky_ be *false*. + ... + 9. Let _matchSucceeded_ be *false*. + 10. Repeat, while _matchSucceeded_ is *false*, + a. If _lastIndex_ > _length_, then + i. If _global_ is *true* or _sticky_ is *true*, then + 1. Perform ? Set(_R_, *"lastIndex"*, *+0*𝔽, *true*). + ii. Return *null*. +---*/ + +var R_g = /./g, R_y = /./y, R_gy = /./gy; + +var S = "test"; + +var lastIndex; +var bigLastIndexes = [ + Infinity, + Number.MAX_VALUE, + Number.MAX_SAFE_INTEGER, + Number.MAX_SAFE_INTEGER - 1, + 2**32 + 4, + 2**32 + 3, + 2**32 + 2, + 2**32 + 1, + 2**32, + 2**32 - 1, + 5 +]; +for ( var i = 0; i < bigLastIndexes.length; i++ ) { + lastIndex = bigLastIndexes[i]; + R_g.lastIndex = lastIndex; + R_y.lastIndex = lastIndex; + R_gy.lastIndex = lastIndex; + + assert.sameValue(R_g.exec(S), null, + "global RegExp instance must fail to match against '" + S + + "' at lastIndex " + lastIndex); + assert.sameValue(R_y.exec(S), null, + "sticky RegExp instance must fail to match against '" + S + + "' at lastIndex " + lastIndex); + assert.sameValue(R_gy.exec(S), null, + "global sticky RegExp instance must fail to match against '" + S + + "' at lastIndex " + lastIndex); + + assert.sameValue(R_g.lastIndex, 0, + "global RegExp instance lastIndex must be reset after " + lastIndex + + " exceeds string length"); + assert.sameValue(R_y.lastIndex, 0, + "sticky RegExp instance lastIndex must be reset after " + lastIndex + + " exceeds string length"); + assert.sameValue(R_gy.lastIndex, 0, + "global sticky RegExp instance lastIndex must be reset after " + lastIndex + + " exceeds string length"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A10.js b/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A10.js index 5ace934a5e89..9f1722c64251 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A10.js @@ -10,19 +10,13 @@ includes: [propertyHelper.js] var __re = RegExp.prototype; -//CHECK#1 -if (__re.hasOwnProperty('global') !== true) { - throw new Test262Error('#1: __re = RegExp.prototype; __re.hasOwnProperty(\'global\') === true'); -} +assert.sameValue(__re.hasOwnProperty('global'), true, '__re.hasOwnProperty(\'global\') must return true'); var __sample = /^|^/; var __obj = __sample.global; verifyNotWritable(__sample, "global", "global", "shifted"); -//CHECK#2 -if (__sample.global !== __obj) { - throw new Test262Error('#2: __sample = /^|^/; __obj = __sample.global; __sample.global = "shifted"; __sample.global === __obj. Actual: ' + (__sample.global)); -} +assert.sameValue(__sample.global, __obj, 'The value of __sample.global is expected to equal the value of __obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A8.js b/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A8.js index 0e659ac7d02b..c2f69b59ae78 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A8.js @@ -11,24 +11,23 @@ description: > var __re = RegExp.prototype; -//CHECK#0 -if (__re.hasOwnProperty('global') !== true) { - throw new Test262Error('#0: __re = RegExp.prototype; __re.hasOwnProperty(\'global\') === true'); -} +assert.sameValue(__re.hasOwnProperty('global'), true, '__re.hasOwnProperty(\'global\') must return true'); - //CHECK#1 -if (__re.propertyIsEnumerable('global') !== false) { - throw new Test262Error('#1: __re = RegExp.prototype; __re.propertyIsEnumerable(\'global\') === false'); -} +assert.sameValue( + __re.propertyIsEnumerable('global'), + false, + '__re.propertyIsEnumerable(\'global\') must return false' +); - //CHECK#2 var count = 0 for (var p in __re){ - if (p==="global") count++ + if (p==="global") { + count++ + } } -if (count !== 0) { - throw new Test262Error('#2: count = 0; __re = RegExp.prototype; for (p in __re){ if (p==="global") count++; } count === 0. Actual: ' + (count)); -} +assert.sameValue(count, 0, 'The value of count is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A9.js b/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A9.js index 61fc113bceda..2a2f0f14c0b8 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/global/S15.10.7.2_A9.js @@ -11,19 +11,10 @@ description: Checking if deleting the global property succeeds var __re = RegExp.prototype; -//CHECK#0 -if (__re.hasOwnProperty('global') !== true) { - throw new Test262Error('#0: __re = RegExp.prototype; __re.hasOwnProperty(\'global\') === true'); -} +assert.sameValue(__re.hasOwnProperty('global'), true, '__re.hasOwnProperty(\'global\') must return true'); +assert.sameValue(delete __re.global, true, 'The value of `delete __re.global` is expected to be true'); +assert.sameValue(__re.hasOwnProperty('global'), false, '__re.hasOwnProperty(\'global\') must return false'); -//CHECK#1 -if ((delete __re.global) !== true) { - throw new Test262Error('#1: __re = RegExp.prototype; (delete __re.global) === true'); -} - -//CHECK#2 -if (__re.hasOwnProperty('global') !== false) { - throw new Test262Error('#2: __re = RegExp.prototype;delete __re.global === true; __re.hasOwnProperty(\'global\') === false'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A10.js b/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A10.js index 03bf403a0e55..17c3ecb5bbb5 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A10.js @@ -10,19 +10,17 @@ includes: [propertyHelper.js] var __re = RegExp.prototype; -//CHECK#1 -if (__re.hasOwnProperty('ignoreCase') !== true) { - throw new Test262Error('#1: __re = RegExp.prototype; __re.hasOwnProperty(\'ignoreCase\') === true'); -} +assert.sameValue(__re.hasOwnProperty('ignoreCase'), true, '__re.hasOwnProperty(\'ignoreCase\') must return true'); var __sample = /a|b|c/; var __obj = __sample.ignoreCase; verifyNotWritable(__sample, "ignoreCase", "ignoreCase", "shifted"); -//CHECK#2 -if (__sample.ignoreCase !== __obj) { - throw new Test262Error('#2: __sample = /a|b|c/; __obj = __sample.ignoreCase; __sample.ignoreCase = "shifted"; __sample.ignoreCase === __obj. Actual: ' + (__sample.ignoreCase)); -} +assert.sameValue( + __sample.ignoreCase, + __obj, + 'The value of __sample.ignoreCase is expected to equal the value of __obj' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A8.js b/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A8.js index 4e27ef86b91a..a70df8a51e0c 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A8.js @@ -11,24 +11,23 @@ description: > var __re = RegExp.prototype; -//CHECK#0 -if (__re.hasOwnProperty('ignoreCase') !== true) { - throw new Test262Error('#0: __re = RegExp.prototype; __re.hasOwnProperty(\'ignoreCase\') === true'); -} +assert.sameValue(__re.hasOwnProperty('ignoreCase'), true, '__re.hasOwnProperty(\'ignoreCase\') must return true'); - //CHECK#1 -if (__re.propertyIsEnumerable('ignoreCase') !== false) { - throw new Test262Error('#1: __re = RegExp.prototype; __re.propertyIsEnumerable(\'ignoreCase\') === false'); -} +assert.sameValue( + __re.propertyIsEnumerable('ignoreCase'), + false, + '__re.propertyIsEnumerable(\'ignoreCase\') must return false' +); - //CHECK#2 var count = 0 for (var p in __re){ - if (p==="ignoreCase") count++ + if (p==="ignoreCase") { + count++ + } } -if (count !== 0) { - throw new Test262Error('#2: count = 0; __re = RegExp.prototype; for (p in __re){ if (p==="ignoreCase") count++; } count === 0. Actual: ' + (count)); -} +assert.sameValue(count, 0, 'The value of count is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A9.js b/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A9.js index 4236413a95fd..70edcce662a8 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A9.js @@ -11,19 +11,10 @@ description: Checking if deleting the ignoreCase property succeeds var __re = RegExp.prototype; -//CHECK#0 -if (__re.hasOwnProperty('ignoreCase') !== true) { - throw new Test262Error('#0: __re = RegExp.prototype; __re.hasOwnProperty(\'ignoreCase\') === true'); -} +assert.sameValue(__re.hasOwnProperty('ignoreCase'), true, '__re.hasOwnProperty(\'ignoreCase\') must return true'); +assert.sameValue(delete __re.ignoreCase, true, 'The value of `delete __re.ignoreCase` is expected to be true'); +assert.sameValue(__re.hasOwnProperty('ignoreCase'), false, '__re.hasOwnProperty(\'ignoreCase\') must return false'); -//CHECK#1 -if ((delete __re.ignoreCase) !== true) { - throw new Test262Error('#1: __re = RegExp.prototype; (delete __re.ignoreCase) === true'); -} - -//CHECK#2 -if (__re.hasOwnProperty('ignoreCase') !== false) { - throw new Test262Error('#2: __re = RegExp.prototype;delete __re.ignoreCase === true; __re.hasOwnProperty(\'ignoreCase\') === false'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A10.js b/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A10.js index 02f676d39cbe..b5d5653e0888 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A10.js @@ -10,19 +10,13 @@ includes: [propertyHelper.js] var __re = RegExp.prototype; -//CHECK#1 -if (__re.hasOwnProperty('multiline') !== true) { - throw new Test262Error('#1: __re = RegExp.prototype; __re.hasOwnProperty(\'multiline\') === true'); -} +assert.sameValue(__re.hasOwnProperty('multiline'), true, '__re.hasOwnProperty(\'multiline\') must return true'); var __sample = /\n/; var __obj = __sample.multiline; verifyNotWritable(__sample, "multiline", "multiline", "shifted"); -//CHECK#2 -if (__sample.multiline !== __obj) { - throw new Test262Error('#2: __sample = /\n/; __obj = __sample.multiline; __sample.multiline = "shifted"; __sample.multiline === __obj. Actual: ' + (__sample.multiline)); -} +assert.sameValue(__sample.multiline, __obj, 'The value of __sample.multiline is expected to equal the value of __obj'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A8.js b/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A8.js index 1241fe7bd7b6..f4a2868a7b83 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A8.js @@ -11,24 +11,23 @@ description: > var __re = RegExp.prototype; -//CHECK#0 -if (__re.hasOwnProperty('multiline') !== true) { - throw new Test262Error('#0: __re = RegExp.prototype; __re.hasOwnProperty(\'multiline\') === true'); -} +assert.sameValue(__re.hasOwnProperty('multiline'), true, '__re.hasOwnProperty(\'multiline\') must return true'); - //CHECK#1 -if (__re.propertyIsEnumerable('multiline') !== false) { - throw new Test262Error('#1: __re = RegExp.prototype; __re.propertyIsEnumerable(\'multiline\') === false'); -} +assert.sameValue( + __re.propertyIsEnumerable('multiline'), + false, + '__re.propertyIsEnumerable(\'multiline\') must return false' +); - //CHECK#2 var count = 0 for (var p in __re){ - if (p==="multiline") count++ + if (p==="multiline") { + count++ + } } -if (count !== 0) { - throw new Test262Error('#2: count = 0; __re = RegExp.prototype; for (p in __re){ if (p==="multiline") count++; } count === 0. Actual: ' + (count)); -} +assert.sameValue(count, 0, 'The value of count is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A9.js b/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A9.js index a83e8449bc3b..89a576a9782f 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/multiline/S15.10.7.4_A9.js @@ -11,19 +11,10 @@ description: Checking if deleting the multiline property succeeds var __re = RegExp.prototype; -//CHECK#0 -if (__re.hasOwnProperty('multiline') !== true) { - throw new Test262Error('#0: __re = RegExp.prototype; __re.hasOwnProperty(\'multiline\') === true'); -} +assert.sameValue(__re.hasOwnProperty('multiline'), true, '__re.hasOwnProperty(\'multiline\') must return true'); +assert.sameValue(delete __re.multiline, true, 'The value of `delete __re.multiline` is expected to be true'); +assert.sameValue(__re.hasOwnProperty('multiline'), false, '__re.hasOwnProperty(\'multiline\') must return false'); -//CHECK#1 -if ((delete __re.multiline) !== true) { - throw new Test262Error('#1: __re = RegExp.prototype; (delete __re.multiline) === true'); -} - -//CHECK#2 -if (__re.hasOwnProperty('multiline') !== false) { - throw new Test262Error('#2: __re = RegExp.prototype;delete __re.multiline === true; __re.hasOwnProperty(\'multiline\') === false'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A10.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A10.js index 159d582d35be..0a8d503e0891 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A10.js @@ -7,19 +7,22 @@ es5id: 15.10.6.3_A10 description: Checking if varying the RegExp.prototype.test.length property fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (RegExp.prototype.test.hasOwnProperty('length') !== true) { - throw new Test262Error('#1: RegExp.prototype.test.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + RegExp.prototype.test.hasOwnProperty('length'), + true, + 'RegExp.prototype.test.hasOwnProperty(\'length\') must return true' +); var __obj = RegExp.prototype.test.length; verifyNotWritable(RegExp.prototype.test, "length", null, function(){return "shifted";}); -//CHECK#2 -if (RegExp.prototype.test.length !== __obj) { - throw new Test262Error('#2: __obj = RegExp.prototype.test.length; RegExp.prototype.test.length = function(){return "shifted";}; RegExp.prototype.test.length === __obj. Actual: ' + (RegExp.prototype.test.length)); -} +assert.sameValue( + RegExp.prototype.test.length, + __obj, + 'The value of RegExp.prototype.test.length is expected to equal the value of __obj' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A11.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A11.js index 25d7bd1297ac..3dbaa2d9ab0f 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A11.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A11.js @@ -6,15 +6,12 @@ info: The length property of the test method is 1 es5id: 15.10.6.3_A11 description: Checking RegExp.prototype.test.length ---*/ +assert.sameValue( + RegExp.prototype.test.hasOwnProperty("length"), + true, + 'RegExp.prototype.test.hasOwnProperty("length") must return true' +); -//CHECK#1 -if (RegExp.prototype.test.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: RegExp.prototype.test.hasOwnProperty(\'length\') === true'); -} - -//CHECK#2 -if (RegExp.prototype.test.length !== 1) { - throw new Test262Error('#2: RegExp.prototype.test.length === 1. Actual: ' + (RegExp.prototype.test.length)); -} +assert.sameValue(RegExp.prototype.test.length, 1, 'The value of RegExp.prototype.test.length is expected to be 1'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T1.js index 27996aa2a23b..6a64ab568ddb 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T1.js @@ -10,9 +10,10 @@ description: RegExp is /1|12/ and tested string is "123" var __string = "123"; var __re = /1|12/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = "123";__re = /1|12/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test(""123"") must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T10.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T10.js index 9dff79194860..52d27fd63512 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T10.js @@ -10,9 +10,10 @@ description: RegExp is /1|12/ and tested string is 1.01 var __string = 1.01; var __re = /1|12/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = 1.01;__re = /1|12/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test(1.01) must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T11.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T11.js index f1e0cdd279d0..3c0caf4afb54 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T11.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T11.js @@ -10,9 +10,10 @@ description: RegExp is /2|12/ and tested string is new Number(1.012) var __string = new Number(1.012); var __re = /2|12/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = new Number(1.012); __re = /2|12/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test(new Number(1.012)) must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T12.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T12.js index a566fe307f7a..55adc9442467 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T12.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T12.js @@ -12,9 +12,10 @@ description: > var __string = {toString:function(){return Math.PI;}}; var __re = /\.14/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = {toString:function(){return Math.PI;}}; __re = /\\.14/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test({toString:function(){return Math.PI;}}) must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T13.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T13.js index 219c8ec46b4e..93b04052744b 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T13.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T13.js @@ -10,9 +10,10 @@ description: RegExp is /t[a-b|q-s]/ and tested string is true var __string = true; var __re = /t[a-b|q-s]/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = true;__re = /t[a-b|q-s]/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test(true) must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T14.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T14.js index 753be083a769..95460d84fb0e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T14.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T14.js @@ -10,9 +10,10 @@ description: RegExp is /AL|se/ and tested string is new Boolean var __string = new Boolean; var __re = /AL|se/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = new Boolean;__re = /AL|se/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test(new Boolean) must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T15.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T15.js index b46d6ee39d27..7017b295d337 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T15.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T15.js @@ -12,9 +12,10 @@ description: > var __string = {toString:function(){return false;}}; var __re = /LS/i; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = {toString:function(){return false;}}; __re = /LS/i; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test({toString:function(){return false;}}) must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T16.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T16.js index 5bd0f7bbc9ea..5bd90f169c8e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T16.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T16.js @@ -9,9 +9,6 @@ description: RegExp is /undefined/ and call test() without arguments var __re = /undefined/; -//CHECK#0 -if (__re.test() !== (__re.exec() !== null)) { - throw new Test262Error('#0: __re = /undefined/; __re.test() === (__re.exec() !== null)'); -} +assert.sameValue(__re.test(), __re.exec() !== null, '__re.test() must return __re.exec() !== null'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T17.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T17.js index b8c3a7e5ff24..2d2f52b5cb71 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T17.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T17.js @@ -9,9 +9,6 @@ description: RegExp is /ll|l/ and tested string is null var __re = /ll|l/; -//CHECK#0 -if (__re.test(null) !== (__re.exec(null) !== null)) { - throw new Test262Error('#0: __re = /ll|l/; __re.test(null) === (__re.exec(null) !== null)'); -} +assert.sameValue(__re.test(null), __re.exec(null) !== null, '__re.test(null) must return __re.exec(null) !== null'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T18.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T18.js index 69126116d8c1..0726b40eda28 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T18.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T18.js @@ -9,9 +9,10 @@ description: RegExp is /nd|ne/ and tested string is undefined var __re = /nd|ne/; -//CHECK#0 -if (__re.test(undefined) !== (__re.exec(undefined) !== null)) { - throw new Test262Error('#0: __re = /nd|ne/; __re.test(undefined) === (__re.exec(undefined) !== null)'); -} +assert.sameValue( + __re.test(undefined), + __re.exec(undefined) !== null, + '__re.test(undefined) must return __re.exec(undefined) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T19.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T19.js index 60938d9d68aa..a767ea20c63e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T19.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T19.js @@ -9,9 +9,10 @@ description: RegExp is /e{1}/ and tested string is void 0 var __re = /e{1}/; -//CHECK#0 -if (__re.test(void 0) !== (__re.exec(void 0) !== null)) { - throw new Test262Error('#0: __re = /e{1}/; __re.test(void 0) === (__re.exec(void 0) !== null)'); -} +assert.sameValue( + __re.test(void 0), + __re.exec(void 0) !== null, + '__re.test(void 0) must return __re.exec(void 0) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T2.js index 6f9ececce9c2..abe89629f4e9 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T2.js @@ -12,9 +12,10 @@ description: > var __string = new String("123"); var __re = /((1)|(12))((3)|(23))/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = new String("123"); __re = /((1)|(12))((3)|(23))/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test("new String("123")") must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T20.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T20.js index c492df3fd96b..50fcf0443c3a 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T20.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T20.js @@ -9,10 +9,7 @@ description: RegExp is /[a-f]d/ and tested string is x, where x is undefined var __re = /[a-f]d/; -//CHECK#0 -if (__re.test(x) !== (__re.exec(x) !== null)) { - throw new Test262Error('#0: __re = /[a-f]d/; __re.test(x) === (__re.exec(x) !== null); var x;'); -} +assert.sameValue(__re.test(x), __re.exec(x) !== null, '__re.test() must return __re.exec(x) !== null'); var x; diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T21.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T21.js index 4948ad25309b..1af7dfac0c38 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T21.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T21.js @@ -11,9 +11,10 @@ description: > var __re = /[a-z]n/; -//CHECK#0 -if (__re.test(function(){}()) !== (__re.exec(function(){}()) !== null)) { - throw new Test262Error('#0: __re = /[a-z]n/; __re.test(function(){}()) === (__re.exec(function(){}()) !== null)'); -} +assert.sameValue( + __re.test(function(){}()), + __re.exec(function(){}()) !== null, + '__re.test(function(){}()) must return __re.exec(function(){}()) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T22.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T22.js index 1c3c586c355e..cadeb79c93c2 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T22.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T22.js @@ -14,27 +14,13 @@ var __re = /(?:ab|cd)\d?/g; __re.lastIndex=-1; var __executed = __re.test("aacd22 "); -//CHECK#1 -if (!__executed) { - throw new Test262Error('#1: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=-1; __executed = __re.test("aacd22 "); __executed === true'); -} - -//CHECK#2 -if (__re.lastIndex !== 5) { - throw new Test262Error('#2: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=-1; __executed = __re.test("aacd22 "); __re.lastIndex === 5. Actual: ' + (__re.lastIndex)); -} +assert(!!__executed, 'The value of !!__executed is expected to be true'); +assert.sameValue(__re.lastIndex, 5, 'The value of __re.lastIndex is expected to be 5'); __re.lastIndex=-100; __executed = __re.test("aacd22 "); -//CHECK#3 -if (!__executed) { - throw new Test262Error('#3: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=-1; __executed = __re.test("aacd22 "); __re.lastIndex=-100; __executed = __re.test("aacd22 "); __executed === true'); -} - -//CHECK#4 -if (__re.lastIndex !== 5) { - throw new Test262Error('#4: __re = /(?:ab|cd)\\d?/g; __re.lastIndex=-1; __executed = __re.test("aacd22 "); __re.lastIndex=-100; __executed = __re.test("aacd22 "); __re.lastIndex === 5. Actual: ' + (__re.lastIndex)); -} +assert(!!__executed, 'The value of !!__executed is expected to be true'); +assert.sameValue(__re.lastIndex, 5, 'The value of __re.lastIndex is expected to be 5'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T3.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T3.js index 59b8ba594f4e..fe59bc5001d0 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T3.js @@ -12,9 +12,10 @@ description: > var __string = new Object("abcdefghi"); var __re = /a[a-z]{2,4}/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = new Object("abcdefghi"); __re = /a[a-z]{2,4}/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test("new Object("abcdefghi")") must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T4.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T4.js index be9e033ceb32..e4b4a1676bc0 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T4.js @@ -12,9 +12,10 @@ description: > var __string = {toString:function(){return "abcdefghi";}}; var __re = /a[a-z]{2,4}?/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = {toString:function(){return "abcdefghi";}}; __re = /a[a-z]{2,4}?/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test({toString:function(){return "abcdefghi";}}) must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T5.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T5.js index 7e3a467abbc8..d15cd5280893 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T5.js @@ -13,9 +13,10 @@ description: > var __string = {toString:function(){return {};}, valueOf:function(){return "aabaac";}}; var __re = /(aa|aabaac|ba|b|c)*/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string = {toString:function(){return {};}, valueOf:function(){return "aabaac";}}; __re = /(aa|aabaac|ba|b|c)*/; __re.test(__string) === (__re.exec(__string) !== null)'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test("{toString:function(){return {};}, valueOf:function(){return "aabaac";}}) must return __re.exec(__string) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T6.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T6.js index e0cc5dc20b20..dad55d3c3aee 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T6.js @@ -11,9 +11,10 @@ description: > var __re = /(z)((a+)?(b+)?(c))*/; -//CHECK#0 -if (__re.test((function(){return "zaacbbbcac"})()) !== (__re.exec((function(){return "zaacbbbcac"})()) !== null)) { - throw new Test262Error('#0: __re = /(z)((a+)?(b+)?(c))*/; __re.test((function(){return "zaacbbbcac"})()) === (__re.exec((function(){return "zaacbbbcac"})()) !== null)'); -} +assert.sameValue( + __re.test((function(){return "zaacbbbcac"})()), + __re.exec((function(){return "zaacbbbcac"})()) !== null, + '__re.test((function(){return "zaacbbbcac"})()) must return __re.exec((function(){return "zaacbbbcac"})()) !== null' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T7.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T7.js index b62b0fa6683d..43abe4e04b3e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T7.js @@ -9,13 +9,12 @@ description: > "intostr";}} ---*/ -//CHECK#1 try { - throw new Test262Error('#1.1: /[a-z]/.test({toString:function(){throw "intostr";}}) throw "intostr". Actual: ' + (/[a-z]/.test({toString:function(){throw "intostr";}}))); + throw new Test262Error('#1.1: /[a-z]/.test({toString:function(){throw "intostr";}}) throw "intostr". Actual: ' + (/[a-z]/.test({toString:function(){throw "intostr";}}))); } catch (e) { - if (e !== "intostr") { - throw new Test262Error('#1.2: /[a-z]/.test({toString:function(){throw "intostr";}}) throw "intostr". Actual: ' + (e)); - } + assert.sameValue(e, "intostr", 'The value of e is expected to be "intostr"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T8.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T8.js index 15c591915746..a068a2da6327 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T8.js @@ -9,13 +9,12 @@ description: > valueOf:function(){throw "invalof";}} ---*/ -//CHECK#1 try { throw new Test262Error('#1.1: /[a-z]/.test({toString:void 0, valueOf:function(){throw "invalof";}}) throw "invalof". Actual: ' + (/[a-z]/.test({toString:void 0, valueOf:function(){throw "invalof";}}))); } catch (e) { - if (e !== "invalof") { - throw new Test262Error('#1.2: /[a-z]/.test({toString:void 0, valueOf:function(){throw "invalof";}}) throw "invalof". Actual: ' + (e)); - } + assert.sameValue(e, "invalof", 'The value of e is expected to be "invalof"'); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T9.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T9.js index 30523287e5eb..dad72cb61402 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A1_T9.js @@ -10,11 +10,12 @@ description: RegExp is /1|12/ and tested string is function object var __string; var __re = /1|12/; -//CHECK#0 -if (__re.test(__string) !== (__re.exec(__string) !== null)) { - throw new Test262Error('#0: var __string;__re = /1|12/; __re.test(__string) === (__re.exec(__string) !== null); function __string(){};'); -} +assert.sameValue( + __re.test(__string), + __re.exec(__string) !== null, + '__re.test() must return __re.exec(__string) !== null' +); -function __string(){}; +function __string(){} reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T1.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T1.js index d0bcede257dc..aa7c94852727 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T1.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T1.js @@ -13,13 +13,16 @@ var __instance = new Object; __instance.test = RegExp.prototype.test; -//CHECK#1 try { throw new Test262Error('#1.1: __instance = new Object; __instance.test = RegExp.prototype.test; __instance.test("message to investigate"). Actual: ' + (__instance.test("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = new Object; __instance.test = RegExp.prototype.test. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T10.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T10.js index a0fbf54e1786..d674d38ae8c1 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T10.js @@ -11,13 +11,16 @@ description: The tested object is undefined var test = RegExp.prototype.test; -//CHECK#1 try { throw new Test262Error('#1.1: test = RegExp.prototype.test; test("message to investigate"). Actual: ' + (test("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: test = RegExp.prototype.test; test("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T2.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T2.js index 176a23920314..0690647f9ea9 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T2.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T2.js @@ -13,14 +13,17 @@ var __instance = Math; __instance.test = RegExp.prototype.test; -//CHECK#1 try { __instance.test("message to investigate"); throw new Test262Error('#1.1: __instance = Math; __instance.test = RegExp.prototype.test; __instance.test("message to investigate")'); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = Math; __instance.test = RegExp.prototype.test; __instance.test("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T3.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T3.js index 1327fa65d943..e304938ad068 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T3.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T3.js @@ -11,16 +11,19 @@ description: The tested object is function object __instance.test = RegExp.prototype.test; -//CHECK#1 try { __instance.test("message to investigate"); throw new Test262Error('#1.1: __instance.test = RegExp.prototype.test; __instance.test("message to investigate"); function __instance(){}'); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance.test = RegExp.prototype.test; __instance.test("message to investigate"); function __instance(){}. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } function __instance(){}; +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T4.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T4.js index 21dcd953ebd0..b22f6dc1b43a 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T4.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T4.js @@ -13,13 +13,16 @@ var __instance = new String("[a-b]"); __instance.test = RegExp.prototype.test; -//CHECK#1 try { throw new Test262Error('#1.1: __instance = new String("[a-b]"); __instance.test = RegExp.prototype.test; test("message to investigate"). Actual: ' + (__instance.test("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = new String("[a-b]"); __instance.test = RegExp.prototype.test; test("message to investigate"). Actual: ' + (e)); - } - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); + } + +// TODO: Convert to assert.throws() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T5.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T5.js index c13398a9ae22..47fcde5b880d 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T5.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T5.js @@ -13,13 +13,16 @@ var __instance = new Boolean(false); __instance.test = RegExp.prototype.test; -//CHECK#1 try { throw new Test262Error('#1.1: __instance = new Boolean(false); __instance.test = RegExp.prototype.test; test("message to investigate"). Actual: ' + (__instance.test("message to investigate"))); } catch (e) { - if ((e instanceof TypeError !== true)) { - throw new Test262Error('#1.2: __instance = new Boolean(false); __instance.test = RegExp.prototype.test; test("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T6.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T6.js index b58276fc4576..3f72ae952358 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T6.js @@ -13,13 +13,16 @@ var __instance = new Number(1.0); __instance.test = RegExp.prototype.test; -//CHECK#1 try { throw new Test262Error('#1.1: __instance = new Number(1.0); __instance.test = RegExp.prototype.test; __instance["test"]("message to investigate"). Actual: ' + (__instance["test"]("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = new Number(1.0); __instance.test = RegExp.prototype.test; __instance["test"]("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T7.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T7.js index b2f6e37765e2..19794986f5ab 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T7.js @@ -13,13 +13,16 @@ var __instance = false; Object.prototype.test = RegExp.prototype.test; -//CHECK#1 try { throw new Test262Error('#1.1: __instance = false; Object.prototype.test = RegExp.prototype.test; __instance.test("message to investigate"). Actual: ' + (__instance.test("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = false; Object.prototype.test = RegExp.prototype.test; __instance.test("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T8.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T8.js index bcd2ac0a5f7a..a50d1fcedd0e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T8.js @@ -13,13 +13,16 @@ var __instance = "."; Object.prototype.test = RegExp.prototype.test; -//CHECK#1 try { throw new Test262Error('#1.1: __instance = "."; Object.prototype.test = RegExp.prototype.test; __instance.test("message to investigate"). Actual: ' + (__instance.test("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = "."; Object.prototype.test = RegExp.prototype.test; __instance.test("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T9.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T9.js index e43deac83420..0ff585e300d5 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A2_T9.js @@ -13,13 +13,16 @@ var __instance = 1.0; Object.prototype.test = RegExp.prototype.test; -//CHECK#1 try { throw new Test262Error('#1.1: __instance = 1.0; Object.prototype.test = RegExp.prototype.test; __instance.test("message to investigate"). Actual: ' + (__instance.test("message to investigate"))); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __instance = 1.0; Object.prototype.test = RegExp.prototype.test; __instance.test("message to investigate"). Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A6.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A6.js index 2f91488573c2..288897860439 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A6.js @@ -6,10 +6,10 @@ info: RegExp.prototype.test has not prototype property es5id: 15.10.6.3_A6 description: Checking RegExp.prototype.test.prototype ---*/ - -//CHECK#1 -if (RegExp.prototype.test.prototype !== undefined) { - throw new Test262Error('#1: RegExp.prototype.test.prototype === undefined. Actual: ' + (RegExp.prototype.test.prototype)); -} +assert.sameValue( + RegExp.prototype.test.prototype, + undefined, + 'The value of RegExp.prototype.test.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A7.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A7.js index 3a8b0980fe74..db7364bd31cd 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A7.js @@ -13,9 +13,13 @@ try { var __instance = new __FACTORY; throw new Test262Error('#1.1: __FACTORY = RegExp.prototype.test throw TypeError. Actual: ' + (__instance)); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __FACTORY = RegExp.prototype.test throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A8.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A8.js index 5ae1b2551fe4..e956dacab2a0 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A8.js @@ -8,26 +8,28 @@ description: > Checking if enumerating the RegExp.prototype.test.length property fails ---*/ +assert.sameValue( + RegExp.prototype.test.hasOwnProperty('length'), + true, + 'RegExp.prototype.test.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if (RegExp.prototype.test.hasOwnProperty('length') !== true) { - throw new Test262Error('#0: RegExp.prototype.test.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + RegExp.prototype.test.propertyIsEnumerable('length'), + false, + 'RegExp.prototype.test.propertyIsEnumerable(\'length\') must return false' +); - //CHECK#1 -if (RegExp.prototype.test.propertyIsEnumerable('length') !== false) { - throw new Test262Error('#1: RegExp.prototype.test.propertyIsEnumerable(\'length\') === true'); -} - - //CHECK#2 var count=0; for (var p in RegExp.prototype.test){ - if (p==="length") count++; + if (p==="length") { + count++; + } } -if (count !== 0) { - throw new Test262Error('#2: count = 0; for (p in RegExp.prototype.test){ if (p==="length") count++; } count === 0. Actual: ' + (count)); -} +assert.sameValue(count, 0, 'The value of count is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A9.js b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A9.js index 4bba24257814..7667d3f3a3f5 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/test/S15.10.6.3_A9.js @@ -8,20 +8,24 @@ info: | es5id: 15.10.6.3_A9 description: Checking if deleting RegExp.prototype.test.length property fails ---*/ +assert.sameValue( + RegExp.prototype.exec.hasOwnProperty('length'), + true, + 'RegExp.prototype.exec.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if ((RegExp.prototype.exec.hasOwnProperty('length') !== true)) { - throw new Test262Error('#0: RegExp.prototype.exec.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + delete RegExp.prototype.exec.length, + true, + 'The value of `delete RegExp.prototype.exec.length` is expected to be true' +); -//CHECK#1 -if (delete RegExp.prototype.exec.length !== true) { - throw new Test262Error('#1: delete RegExp.prototype.exec.length === true'); -} +assert.sameValue( + RegExp.prototype.exec.hasOwnProperty('length'), + false, + 'RegExp.prototype.exec.hasOwnProperty(\'length\') must return false' +); -//CHECK#2 -if (RegExp.prototype.exec.hasOwnProperty('length') !== false) { - throw new Test262Error('#2: delete RegExp.prototype.exec.length; RegExp.prototype.exec.hasOwnProperty(\'length\') === false'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A10.js b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A10.js index 57f9fa482bcb..34498afafc51 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A10.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A10.js @@ -9,19 +9,22 @@ description: > fails includes: [propertyHelper.js] ---*/ - -//CHECK#1 -if (RegExp.prototype.toString.hasOwnProperty('length') !== true) { - throw new Test262Error('#1: RegExp.prototype.toString.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + RegExp.prototype.toString.hasOwnProperty('length'), + true, + 'RegExp.prototype.toString.hasOwnProperty(\'length\') must return true' +); var __obj = RegExp.prototype.toString.length; verifyNotWritable(RegExp.prototype.toString, "length", null, function(){return "shifted";}); -//CHECK#2 -if (RegExp.prototype.toString.length !== __obj) { - throw new Test262Error('#2: __obj = RegExp.prototype.toString.length; RegExp.prototype.toString.length = function(){return "shifted";}; RegExp.prototype.toString.length === __obj. Actual: ' + (RegExp.prototype.toString.length)); -} +assert.sameValue( + RegExp.prototype.toString.length, + __obj, + 'The value of RegExp.prototype.toString.length is expected to equal the value of __obj' +); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A11.js b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A11.js index f8c5b803ea03..ba322bd577ed 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A11.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A11.js @@ -6,15 +6,16 @@ info: The length property of the toString method is 1 es5id: 15.10.6.4_A11 description: Checking RegExp.prototype.toString.length ---*/ +assert.sameValue( + RegExp.prototype.toString.hasOwnProperty("length"), + true, + 'RegExp.prototype.toString.hasOwnProperty("length") must return true' +); -//CHECK#1 -if (RegExp.prototype.toString.hasOwnProperty("length") !== true) { - throw new Test262Error('#1: RegExp.prototype.toString.hasOwnProperty(\'length\') === true'); -} - -//CHECK#2 -if (RegExp.prototype.toString.length !== 0) { - throw new Test262Error('#2: RegExp.prototype.toString.length === 0. Actual: ' + (RegExp.prototype.toString.length)); -} +assert.sameValue( + RegExp.prototype.toString.length, + 0, + 'The value of RegExp.prototype.toString.length is expected to be 0' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A6.js b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A6.js index d76a63c06d0e..233154b78a9a 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A6.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A6.js @@ -6,10 +6,10 @@ info: RegExp.prototype.toString has not prototype property es5id: 15.10.6.4_A6 description: Checking RegExp.prototype.toString.prototype ---*/ - -//CHECK#1 -if (RegExp.prototype.toString.prototype !== undefined) { - throw new Test262Error('#1: RegExp.prototype.toString.prototype === undefined. Actual: ' + (RegExp.prototype.toString.prototype)); -} +assert.sameValue( + RegExp.prototype.toString.prototype, + undefined, + 'The value of RegExp.prototype.toString.prototype is expected to equal undefined' +); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A7.js b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A7.js index f71f6b7f323a..854653c6ffcf 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A7.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A7.js @@ -10,12 +10,16 @@ description: Checking if creating the RegExp.prototype.toString object fails var __FACTORY = RegExp.prototype.toString; try { - var __instance = new __FACTORY; - throw new Test262Error('#1.1: __FACTORY = RegExp.prototype.toString throw TypeError. Actual: ' + (__instance)); + var __instance = new __FACTORY; + throw new Test262Error('#1.1: __FACTORY = RegExp.prototype.toString throw TypeError. Actual: ' + (__instance)); } catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: __FACTORY = RegExp.prototype.toString throw TypeError. Actual: ' + (e)); - } + assert.sameValue( + e instanceof TypeError, + true, + 'The result of evaluating (e instanceof TypeError) is expected to be true' + ); } +// TODO: Convert to assert.throws() format. + reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A8.js b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A8.js index 26d31e3546c4..fe8d29d5126e 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A8.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A8.js @@ -8,26 +8,28 @@ description: > Checking if enumerating the RegExp.prototype.toString.length property fails ---*/ +assert.sameValue( + RegExp.prototype.toString.hasOwnProperty('length'), + true, + 'RegExp.prototype.toString.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if (RegExp.prototype.toString.hasOwnProperty('length') !== true) { - throw new Test262Error('#0: RegExp.prototype.toString.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + RegExp.prototype.toString.propertyIsEnumerable('length'), + false, + 'RegExp.prototype.toString.propertyIsEnumerable(\'length\') must return false' +); - //CHECK#1 -if (RegExp.prototype.toString.propertyIsEnumerable('length') !== false) { - throw new Test262Error('#1: RegExp.prototype.toString.propertyIsEnumerable(\'length\') === true'); -} - - //CHECK#2 var count=0; for (var p in RegExp.prototype.toString){ - if (p==="length") count++; + if (p==="length") { + count++; + } } -if (count !== 0) { - throw new Test262Error('#2: count = 0; for (p in RegExp.prototype.toString){ if (p==="length") count++; } count === 0. Actual: ' + (count)); -} +assert.sameValue(count, 0, 'The value of count is expected to be 0'); + +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A9.js b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A9.js index 29cfdccc0a55..34f1cdffc925 100644 --- a/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A9.js +++ b/js/src/tests/test262/built-ins/RegExp/prototype/toString/S15.10.6.4_A9.js @@ -10,20 +10,24 @@ description: > Checking if deleting the RegExp.prototype.toString.length property fails ---*/ +assert.sameValue( + RegExp.prototype.toString.hasOwnProperty('length'), + true, + 'RegExp.prototype.toString.hasOwnProperty(\'length\') must return true' +); -//CHECK#0 -if ((RegExp.prototype.toString.hasOwnProperty('length') !== true)) { - throw new Test262Error('#0: RegExp.prototype.toString.hasOwnProperty(\'length\') === true'); -} +assert.sameValue( + delete RegExp.prototype.toString.length, + true, + 'The value of `delete RegExp.prototype.toString.length` is expected to be true' +); -//CHECK#1 -if (delete RegExp.prototype.toString.length !== true) { - throw new Test262Error('#1: delete RegExp.prototype.toString.length === true'); -} +assert.sameValue( + RegExp.prototype.toString.hasOwnProperty('length'), + false, + 'RegExp.prototype.toString.hasOwnProperty(\'length\') must return false' +); -//CHECK#2 -if (RegExp.prototype.toString.hasOwnProperty('length') !== false) { - throw new Test262Error('#2: delete RegExp.prototype.toString.length; RegExp.prototype.toString.hasOwnProperty(\'length\') === false'); -} +// TODO: Convert to verifyProperty() format. reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExpStringIteratorPrototype/next/shell.js b/js/src/tests/test262/built-ins/RegExpStringIteratorPrototype/next/shell.js index acac42890065..1ad30bb1df39 100644 --- a/js/src/tests/test262/built-ins/RegExpStringIteratorPrototype/next/shell.js +++ b/js/src/tests/test262/built-ins/RegExpStringIteratorPrototype/next/shell.js @@ -42,7 +42,7 @@ assert.compareIterator = function(iter, validators, message) { /*--- description: | Collection of functions used to assert the correctness of RegExp objects. -defines: [buildString, testPropertyEscapes, matchValidator] +defines: [buildString, testPropertyEscapes, testPropertyOfStrings, matchValidator] ---*/ function buildString(args) { @@ -70,23 +70,65 @@ function buildString(args) { return result; } -function testPropertyEscapes(regex, string, expression) { - if (!regex.test(string)) { +function printCodePoint(codePoint) { + const hex = codePoint + .toString(16) + .toUpperCase() + .padStart(6, "0"); + return `U+${hex}`; +} + +function printStringCodePoints(string) { + const buf = []; + for (const symbol of string) { + const formatted = printCodePoint(symbol.codePointAt(0)); + buf.push(formatted); + } + return buf.join(' '); +} + +function testPropertyEscapes(regExp, string, expression) { + if (!regExp.test(string)) { for (const symbol of string) { - const hex = symbol - .codePointAt(0) - .toString(16) - .toUpperCase() - .padStart(6, "0"); + printCodePoint(symbol.codePointAt(0)); assert( - regex.test(symbol), + regExp.test(symbol), `\`${ expression }\` should match U+${ hex } (\`${ symbol }\`)` ); } } } -// Returns a function that will validate RegExp match result +function testPropertyOfStrings(args) { + // Use member expressions rather than destructuring `args` for improved + // compatibility with engines that only implement assignment patterns + // partially or not at all. + const regExp = args.regExp; + const expression = args.expression; + const matchStrings = args.matchStrings; + const nonMatchStrings = args.nonMatchStrings; + const allStrings = matchStrings.join(''); + if (!regExp.test(allStrings)) { + for (const string of matchStrings) { + assert( + regExp.test(string), + `\`${ expression }\` should match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } + + const allNonMatchStrings = nonMatchStrings.join(''); + if (regExp.test(allNonMatchStrings)) { + for (const string of nonMatchStrings) { + assert( + !regExp.test(string), + `\`${ expression }\` should not match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } +} + +// Returns a function that validates a RegExp match result. // // Example: // diff --git a/js/src/tests/test262/built-ins/Set/Symbol.species/length.js b/js/src/tests/test262/built-ins/Set/Symbol.species/length.js index 06474ae5bd8c..a4fc6ac666bd 100644 --- a/js/src/tests/test262/built-ins/Set/Symbol.species/length.js +++ b/js/src/tests/test262/built-ins/Set/Symbol.species/length.js @@ -2,7 +2,7 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.2.2 +esid: sec-get-set-@@species description: > get Set [ @@species ].length is 0. info: | diff --git a/js/src/tests/test262/built-ins/Set/Symbol.species/symbol-species-name.js b/js/src/tests/test262/built-ins/Set/Symbol.species/symbol-species-name.js index c9c06da821e6..4cbeaf5be9a2 100644 --- a/js/src/tests/test262/built-ins/Set/Symbol.species/symbol-species-name.js +++ b/js/src/tests/test262/built-ins/Set/Symbol.species/symbol-species-name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.2.2 +esid: sec-get-set-@@species description: > Set[Symbol.species] accessor property get name info: | diff --git a/js/src/tests/test262/built-ins/Set/Symbol.species/symbol-species.js b/js/src/tests/test262/built-ins/Set/Symbol.species/symbol-species.js index f52ab2c09374..8f80342ab90d 100644 --- a/js/src/tests/test262/built-ins/Set/Symbol.species/symbol-species.js +++ b/js/src/tests/test262/built-ins/Set/Symbol.species/symbol-species.js @@ -2,11 +2,11 @@ // See LICENSE for details. /*--- -info: | - Set has a property at `Symbol.species` esid: sec-get-set-@@species -author: Sam Mikes description: Set[Symbol.species] exists per spec +info: | + Set has a property at `Symbol.species` +author: Sam Mikes includes: [propertyHelper.js] features: [Symbol.species] ---*/ diff --git a/js/src/tests/test262/built-ins/Set/bigint-number-same-value.js b/js/src/tests/test262/built-ins/Set/bigint-number-same-value.js new file mode 100644 index 000000000000..23406648c3c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Set/bigint-number-same-value.js @@ -0,0 +1,46 @@ +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-set.prototype.add +description: > + Observing the expected behavior of keys when a BigInt and Number have + the same value. +info: | + Set.prototype.add ( value ) + + ... + For each element e of entries, do + If e is not empty and SameValueZero(e, value) is true, then + Return S. + If value is -0, set value to +0. + Append value as the last element of entries. + ... + +features: [BigInt] +---*/ + +const number = 9007199254740991; +const bigint = 9007199254740991n; + +const s = new Set([ + number, + bigint, +]); + +assert.sameValue(s.size, 2); +assert.sameValue(s.has(number), true); +assert.sameValue(s.has(bigint), true); + +s.delete(number); +assert.sameValue(s.size, 1); +assert.sameValue(s.has(number), false); +s.delete(bigint); +assert.sameValue(s.size, 0); +assert.sameValue(s.has(bigint), false); + +s.add(number); +assert.sameValue(s.size, 1); +s.add(bigint); +assert.sameValue(s.size, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Set/constructor.js b/js/src/tests/test262/built-ins/Set/constructor.js index fb34784c2eaf..0492e56a31b8 100644 --- a/js/src/tests/test262/built-ins/Set/constructor.js +++ b/js/src/tests/test262/built-ins/Set/constructor.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1 +esid: sec-set-constructor description: > The Set constructor is the %Set% intrinsic object and the initial value of the Set property of the global object. diff --git a/js/src/tests/test262/built-ins/Set/length.js b/js/src/tests/test262/built-ins/Set/length.js index 325ad0f7faf2..7e428774236e 100644 --- a/js/src/tests/test262/built-ins/Set/length.js +++ b/js/src/tests/test262/built-ins/Set/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.2 +esid: sec-set-constructor description: > Properties of the Set Constructor diff --git a/js/src/tests/test262/built-ins/Set/name.js b/js/src/tests/test262/built-ins/Set/name.js index f61b92982094..c4f6ac72ef58 100644 --- a/js/src/tests/test262/built-ins/Set/name.js +++ b/js/src/tests/test262/built-ins/Set/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/properties-of-the-set-prototype-object.js b/js/src/tests/test262/built-ins/Set/properties-of-the-set-prototype-object.js index 461d7ea80ad4..056b3ab72d26 100644 --- a/js/src/tests/test262/built-ins/Set/properties-of-the-set-prototype-object.js +++ b/js/src/tests/test262/built-ins/Set/properties-of-the-set-prototype-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3 +esid: sec-properties-of-the-set-prototype-object description: > The Set prototype object is the intrinsic object %SetPrototype%. The value of the [[Prototype]] internal slot of the Set prototype diff --git a/js/src/tests/test262/built-ins/Set/prototype-of-set.js b/js/src/tests/test262/built-ins/Set/prototype-of-set.js index 8e85286ed180..8b74372d0f2a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype-of-set.js +++ b/js/src/tests/test262/built-ins/Set/prototype-of-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.2 +esid: sec-properties-of-the-set-constructor description: > The value of the [[Prototype]] internal slot of the Set constructor is the intrinsic object %FunctionPrototype% (19.2.3). diff --git a/js/src/tests/test262/built-ins/Set/prototype/Symbol.iterator.js b/js/src/tests/test262/built-ins/Set/prototype/Symbol.iterator.js index 55de31cca582..d52cbf391e1e 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/Symbol.iterator.js +++ b/js/src/tests/test262/built-ins/Set/prototype/Symbol.iterator.js @@ -2,6 +2,7 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: sec-set.prototype-@@iterator description: Initial state of the Symbol.iterator property info: | The initial value of the @@iterator property is the same function object as @@ -11,7 +12,6 @@ info: | should be writable and configurable, but not enumerable. includes: [propertyHelper.js] features: [Symbol.iterator] -es6id: 23.2.3.11 ---*/ assert.sameValue(Set.prototype[Symbol.iterator], Set.prototype.values); diff --git a/js/src/tests/test262/built-ins/Set/prototype/Symbol.toStringTag.js b/js/src/tests/test262/built-ins/Set/prototype/Symbol.toStringTag.js index 4b7453e215cd..c1defb804122 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/Symbol.toStringTag.js +++ b/js/src/tests/test262/built-ins/Set/prototype/Symbol.toStringTag.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.12 +esid: sec-set.prototype-@@tostringtag description: > `Symbol.toStringTag` property descriptor info: | diff --git a/js/src/tests/test262/built-ins/Set/prototype/Symbol.toStringTag/property-descriptor.js b/js/src/tests/test262/built-ins/Set/prototype/Symbol.toStringTag/property-descriptor.js index f1a3519fc562..592676334381 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/Symbol.toStringTag/property-descriptor.js +++ b/js/src/tests/test262/built-ins/Set/prototype/Symbol.toStringTag/property-descriptor.js @@ -2,11 +2,11 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: sec-set.prototype-@@tostringtag description: > `Object.prototype.getOwnPropertyDescriptor` should reflect the value and writability of the @@toStringTag attribute. includes: [propertyHelper.js] -es6id: 23.2.3.12 features: [Symbol.toStringTag] ---*/ diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/add.js b/js/src/tests/test262/built-ins/Set/prototype/add/add.js index c08e4b374710..159a0ef0298c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/add.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/add.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-array.js b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-array.js index a233a6f56171..e28138f16f53 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-array.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-array.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-map.js b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-map.js index f345df3fda83..4049431f0495 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-map.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-object.js b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-object.js index 05079acb3ad5..b40f08509a0a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-object.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-set-prototype.js b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-set-prototype.js index e0700dabb2a2..373a9c8583af 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-set-prototype.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-set-prototype.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-weakset.js b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-weakset.js index a618778d6198..42c33b2a27dc 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-weakset.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-weakset.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/length.js b/js/src/tests/test262/built-ins/Set/prototype/add/length.js index fb48f6820405..88b79c7daef5 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/length.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/name.js b/js/src/tests/test262/built-ins/Set/prototype/add/name.js index 0d3c76fe1a50..f8f5441845d7 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/name.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/preserves-insertion-order.js b/js/src/tests/test262/built-ins/Set/prototype/add/preserves-insertion-order.js index 45e1504efbfe..1cef6a0cc736 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/preserves-insertion-order.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/preserves-insertion-order.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/returns-this-when-ignoring-duplicate.js b/js/src/tests/test262/built-ins/Set/prototype/add/returns-this-when-ignoring-duplicate.js index 561f3de320e9..5635af8eb64c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/returns-this-when-ignoring-duplicate.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/returns-this-when-ignoring-duplicate.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/returns-this.js b/js/src/tests/test262/built-ins/Set/prototype/add/returns-this.js index e329e9c978ec..da84ccde06cd 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/returns-this.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/returns-this.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-boolean.js index 4424328e19c5..f21abae91230 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-null.js b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-null.js index 5ce1502da33f..e99e6729d693 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-number.js b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-number.js index 83409429e192..d5abae701c9a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-string.js b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-string.js index 0d1bc49f4db5..bf2e69fc9142 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-symbol.js index b65ee411def3..5e6996de6482 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-undefined.js index 7e058f903d28..3d301c001fc2 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/this-not-object-throw-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry-initial-iterable.js b/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry-initial-iterable.js index e5443abcbe3f..5b078d29bbd3 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry-initial-iterable.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry-initial-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry-normalizes-zero.js b/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry-normalizes-zero.js index 9946369ad8d1..9cc716735192 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry-normalizes-zero.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry-normalizes-zero.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry.js b/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry.js index aace203963d5..28d5c75759fc 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry.js +++ b/js/src/tests/test262/built-ins/Set/prototype/add/will-not-add-duplicate-entry.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.1 +esid: sec-set.prototype.add description: > Set.prototype.add ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/clear.js b/js/src/tests/test262/built-ins/Set/prototype/clear/clear.js index 245168270089..802c67227a53 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/clear.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/clear.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/clears-all-contents-from-iterable.js b/js/src/tests/test262/built-ins/Set/prototype/clear/clears-all-contents-from-iterable.js index 58cd67e1e6ec..5b0c5adbd49a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/clears-all-contents-from-iterable.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/clears-all-contents-from-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/clears-all-contents.js b/js/src/tests/test262/built-ins/Set/prototype/clear/clears-all-contents.js index 0f9c79443971..44c4ecf59bc5 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/clears-all-contents.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/clears-all-contents.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/clears-an-empty-set.js b/js/src/tests/test262/built-ins/Set/prototype/clear/clears-an-empty-set.js index 808ae93a49fb..47fe4dd05b3c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/clears-an-empty-set.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/clears-an-empty-set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-array.js b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-array.js index 4fa993ea902b..a892c1d9d1e6 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-array.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-array.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-map.js b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-map.js index d7f49ddd269f..4177ce9c6d4e 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-map.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-object.js b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-object.js index d41d6efca9ef..fc0ac57bd81e 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-object.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-set.prototype.js b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-set.prototype.js index fd77749f250c..b13aee60b994 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-set.prototype.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-set.prototype.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-weakset.js b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-weakset.js index 2544e4188d0a..e693c1e5bd77 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-weakset.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-weakset.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/length.js b/js/src/tests/test262/built-ins/Set/prototype/clear/length.js index 6ccdef652d38..84e1dd114671 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/length.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/name.js b/js/src/tests/test262/built-ins/Set/prototype/clear/name.js index 3e970e0450bf..722a8af8f10f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/name.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/returns-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/clear/returns-undefined.js index 8c9c849e0cf1..8857aa8a85b7 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/returns-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/returns-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-boolean.js index 3bc06aba853d..8b8a18b1caa7 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-null.js b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-null.js index 7e38151ad736..c21931f3e11c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-number.js b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-number.js index 4d38be7c3113..211fa883ffe8 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-string.js b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-string.js index b30769b168f5..8097a19afac0 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-symbol.js index 8ada33784a17..3b284170fb9c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-undefined.js index 00d8b0aaf000..35b9fc665a24 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/clear/this-not-object-throw-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.2 +esid: sec-set.prototype.clear description: > Set.prototype.clear ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/constructor/set-prototype-constructor-intrinsic.js b/js/src/tests/test262/built-ins/Set/prototype/constructor/set-prototype-constructor-intrinsic.js index a3d086197ffb..356342fe069d 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/constructor/set-prototype-constructor-intrinsic.js +++ b/js/src/tests/test262/built-ins/Set/prototype/constructor/set-prototype-constructor-intrinsic.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.3 +esid: sec-ecmascript-standard-built-in-objects description: > Set.prototype.constructor diff --git a/js/src/tests/test262/built-ins/Set/prototype/constructor/set-prototype-constructor.js b/js/src/tests/test262/built-ins/Set/prototype/constructor/set-prototype-constructor.js index 43a75c485267..0c48222b34f0 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/constructor/set-prototype-constructor.js +++ b/js/src/tests/test262/built-ins/Set/prototype/constructor/set-prototype-constructor.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-ecmascript-standard-built-in-objects description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry-initial-iterable.js b/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry-initial-iterable.js index 22358b27c81d..688b467b3011 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry-initial-iterable.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry-initial-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry-normalizes-zero.js b/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry-normalizes-zero.js index 3be137ba0eec..fb17ea0e00a9 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry-normalizes-zero.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry-normalizes-zero.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry.js b/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry.js index 69d5a0f5ad69..cc84a3a36897 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/delete-entry.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/delete.js b/js/src/tests/test262/built-ins/Set/prototype/delete/delete.js index 59d622321796..1cea6e61033c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/delete.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/delete.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-array.js b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-array.js index 16570d385d6b..b69fc404d707 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-array.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-array.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-map.js b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-map.js index 7968e71b97b2..9ac5ce0e033c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-map.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-object.js b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-object.js index ab07ec39b204..0bf57e4ce0ed 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-object.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-set-prototype.js b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-set-prototype.js index 2cd83436d1da..6c564ec06456 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-set-prototype.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-set-prototype.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-weakset.js b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-weakset.js index ba38153667bf..60e1ef49e3e7 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-weakset.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-weakset.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/length.js b/js/src/tests/test262/built-ins/Set/prototype/delete/length.js index 9b694e8cb4d0..5d28a0ad401d 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/length.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/name.js b/js/src/tests/test262/built-ins/Set/prototype/delete/name.js index 5dd8788e41ee..538d7b437063 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/name.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/returns-false-when-delete-is-noop.js b/js/src/tests/test262/built-ins/Set/prototype/delete/returns-false-when-delete-is-noop.js index 52d7d31027c4..8a8e69e8862f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/returns-false-when-delete-is-noop.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/returns-false-when-delete-is-noop.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/returns-true-when-delete-operation-occurs.js b/js/src/tests/test262/built-ins/Set/prototype/delete/returns-true-when-delete-operation-occurs.js index 2e5cff31f6ed..e622e9bc1747 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/returns-true-when-delete-operation-occurs.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/returns-true-when-delete-operation-occurs.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-boolean.js index c07d237b4561..3f407635716f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-null.js b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-null.js index 42bbf5dd35ba..11415e35c03c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-number.js b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-number.js index 156cf3700080..4dfc55488ed4 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-string.js b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-string.js index a7bae769f7b6..5d97d8fb2aff 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-symbol.js index 9d04fef452ee..cf01f94cb3f4 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-undefined.js index 59c99746446a..ffa90305f176 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/delete/this-not-object-throw-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.4 +esid: sec-set.prototype.delete description: > Set.prototype.delete ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-array.js b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-array.js index 9f5f20f93712..771d461f6591 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-array.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-array.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-map.js b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-map.js index 52df3d8a2ee9..5326a8eb6be4 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-map.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-object.js b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-object.js index 4779601fb359..37e0b7f7a4fb 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-object.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-set-prototype.js b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-set-prototype.js index 65786ed6fe0d..588d45aee6db 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-set-prototype.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-set-prototype.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-weakset.js b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-weakset.js index 53f11499e7ce..b8b7c9797492 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-weakset.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-weakset.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/entries.js b/js/src/tests/test262/built-ins/Set/prototype/entries/entries.js index 604eb3b36424..2dc649d63a7e 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/entries.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/entries.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/length.js b/js/src/tests/test262/built-ins/Set/prototype/entries/length.js index 77edd62b26a4..5f7ab9dd4caf 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/length.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/name.js b/js/src/tests/test262/built-ins/Set/prototype/entries/name.js index 18f62e87f987..ffcfec6df13d 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/name.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/returns-iterator-empty.js b/js/src/tests/test262/built-ins/Set/prototype/entries/returns-iterator-empty.js index effaedef871a..306b48546fad 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/returns-iterator-empty.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/returns-iterator-empty.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/returns-iterator.js b/js/src/tests/test262/built-ins/Set/prototype/entries/returns-iterator.js index f447869a8d33..8193ffd31f77 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/returns-iterator.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/returns-iterator.js @@ -1,7 +1,7 @@ // Copyright (C) 2014 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-boolean.js index da9654b0d2b9..d3ebbfdc38c9 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-null.js b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-null.js index 635f15f890e0..93613ac76d34 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-number.js b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-number.js index 05424ec17617..6d03bbba3e5f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-string.js b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-string.js index 9ec8e0f0c94a..8230c391d929 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-symbol.js index fa92de9f1ec4..cddd8e20f3d2 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-undefined.js index 2fc641b5759c..cbae89d89d6e 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/entries/this-not-object-throw-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.5 +esid: sec-set.prototype.entries description: > Set.prototype.entries ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-boolean.js index 0c77c6c132c4..f24c6d0adec8 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-null.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-null.js index 3b7bac8cc674..89b29d27371b 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-number.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-number.js index 999dbbefb5c7..38740e4dd026 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-string.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-string.js index db68ff5d77c5..071fd839e279 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-symbol.js index 21deec14ee1e..0fccfd438aa2 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-undefined.js index 2c91f31b265f..40afeda4dbc0 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/callback-not-callable-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-array.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-array.js index 7b3bedd148f1..d462ba579be6 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-array.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-array.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-map.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-map.js index f4e72b528499..50f6171e365a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-map.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-object.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-object.js index 3147d7d687f7..a8f2bb3d1e08 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-object.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-set-prototype.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-set-prototype.js index da80ca5c2ece..8ec937a84ca9 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-set-prototype.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-set-prototype.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-weakset.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-weakset.js index e4d452f2de00..e407f5e46c69 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-weakset.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-weakset.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/forEach.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/forEach.js index 2e3f31513af4..e1ec73eb15f7 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/forEach.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/forEach.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-in-insertion-order.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-in-insertion-order.js index 2650e3cb31ce..594b2c0735e5 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-in-insertion-order.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-in-insertion-order.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-in-iterable-entry-order.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-in-iterable-entry-order.js index 655aa550f5f7..920de93dff88 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-in-iterable-entry-order.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-in-iterable-entry-order.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-added-after-foreach-begins.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-added-after-foreach-begins.js index 5b931a40385a..4a6eb0a13e6c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-added-after-foreach-begins.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-added-after-foreach-begins.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-deleted-then-readded.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-deleted-then-readded.js index 29142104f2d7..b764598d7247 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-deleted-then-readded.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-deleted-then-readded.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-not-deleted.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-not-deleted.js index 54f21f8c348e..97f5bde0790c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-not-deleted.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-not-deleted.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-revisits-after-delete-re-add.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-revisits-after-delete-re-add.js index c55a11a3c446..11de01c1be2c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-revisits-after-delete-re-add.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/iterates-values-revisits-after-delete-re-add.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/length.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/length.js index d4f654944155..8304c7844779 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/length.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/name.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/name.js index c27b5064bac7..390b016c64a5 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/name.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/returns-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/returns-undefined.js index bffa40ec39a4..27cac6eb4535 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/returns-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/returns-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-arg-explicit-cannot-override-lexical-this-arrow.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-arg-explicit-cannot-override-lexical-this-arrow.js index 6c0aace0aa6e..7c20508936f9 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-arg-explicit-cannot-override-lexical-this-arrow.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-arg-explicit-cannot-override-lexical-this-arrow.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-arg-explicit.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-arg-explicit.js index c4c2e0062609..dcae47e9468f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-arg-explicit.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-arg-explicit.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-non-strict.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-non-strict.js index f4627dc63955..b7d3a08faf26 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-non-strict.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-non-strict.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-boolean.js index ff928e1c34c3..d06d23cec108 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-null.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-null.js index 6c2cfda6b13e..9fb0dd41775c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-number.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-number.js index 20ecdc89dd65..2ee877c8dcb7 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-string.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-string.js index 5f48fc3405fe..0e12d3fdc55f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-symbol.js index 52a3be80d7cb..acf72f3e031a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-undefined.js index c4433cd528f4..cc97196396d2 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-not-object-throw-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-strict-strict.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-strict-strict.js index 873a70b7a1cc..8360f34120b5 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/this-strict-strict.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/this-strict-strict.js @@ -2,7 +2,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/forEach/throws-when-callback-throws.js b/js/src/tests/test262/built-ins/Set/prototype/forEach/throws-when-callback-throws.js index 885aa6359650..423b0d2fe5e6 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/forEach/throws-when-callback-throws.js +++ b/js/src/tests/test262/built-ins/Set/prototype/forEach/throws-when-callback-throws.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.6 +esid: sec-set.prototype.forEach description: > Set.prototype.forEach ( callbackfn [ , thisArg ] ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-array.js b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-array.js index ea7976fea4d1..3ae1b82da535 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-array.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-array.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-map.js b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-map.js index 319f6bb8b46b..1730d3589f10 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-map.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-object.js b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-object.js index 155680afdf0a..ec257eb5544d 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-object.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-set-prototype.js b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-set-prototype.js index 4088d43ec6f0..aa82cb1ade68 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-set-prototype.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-set-prototype.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-weakset.js b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-weakset.js index cdb2d2c45122..e2137cc90396 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-weakset.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-weakset.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/has.js b/js/src/tests/test262/built-ins/Set/prototype/has/has.js index e0e91284865f..c8f3c054ae52 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/has.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/has.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/length.js b/js/src/tests/test262/built-ins/Set/prototype/has/length.js index 993947b2ec53..93326a356509 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/length.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/name.js b/js/src/tests/test262/built-ins/Set/prototype/has/name.js index 27e854db3de7..c95b4ff0b595 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/name.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-undefined-added-deleted-not-present-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-undefined-added-deleted-not-present-undefined.js index b47906774ecf..4391df70be4a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-undefined-added-deleted-not-present-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-undefined-added-deleted-not-present-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-boolean.js index 5c66d3699bdc..366a6940502c 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-nan.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-nan.js index 04d9233459d2..7ce69a5c8b1e 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-nan.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-nan.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-null.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-null.js index 3249bcf87608..ddfada5bf37a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-number.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-number.js index 304becb6eda8..9075d36884ee 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-string.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-string.js index b2e04b1c9839..f244b2ee8751 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-symbol.js index aa971561fbeb..8f974f799cd6 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-undefined.js index 3cef7982331c..6863c7a53f37 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-false-when-value-not-present-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-boolean.js index dd197d1972a9..4809af3dc6d5 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-nan.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-nan.js index 5e016620e963..dcc51d54e5b6 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-nan.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-nan.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-null.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-null.js index 1b54877cd731..7c90fcd66f23 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-number.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-number.js index b5fa8735e80d..1831aaa35f9f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-string.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-string.js index de466241a648..938bcae841bd 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-symbol.js index 74787833eea4..f8c5b80400ec 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-undefined.js index fa02a989864e..0f14f5c490fe 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/returns-true-when-value-present-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-boolean.js index 2260eebffa37..c954fa957217 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-null.js b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-null.js index e7b5fdcd8994..150cb8fb8389 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-number.js b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-number.js index 2fb8083dc3d5..067c2918bd9f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-string.js b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-string.js index 7ffca592ff43..e8f4b2ec5b22 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-symbol.js index b7623d956b69..8254cab3571f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-undefined.js index 8c6276c34fad..bee6d27e3e2e 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/has/this-not-object-throw-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.7 +esid: sec-set.prototype.has description: > Set.prototype.has ( value ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/keys/keys.js b/js/src/tests/test262/built-ins/Set/prototype/keys/keys.js index a674b3de3e7a..0f4325be910f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/keys/keys.js +++ b/js/src/tests/test262/built-ins/Set/prototype/keys/keys.js @@ -2,10 +2,10 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- - description: > - The initial value of the keys property is the same function object as the - initial value of the values property. - es6id: 23.2.3.8 +esid: sec-set.prototype.keys +description: > + The initial value of the keys property is the same function object as the + initial value of the values property. ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/Set/prototype/set-prototype.js b/js/src/tests/test262/built-ins/Set/prototype/set-prototype.js deleted file mode 100644 index 66b5a2f0a997..000000000000 --- a/js/src/tests/test262/built-ins/Set/prototype/set-prototype.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2015 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -es6id: 23.2.1.1 -description: > - Set ( [ iterable ] ) - - 17 ECMAScript Standard Built-in Objects - -includes: [propertyHelper.js] ----*/ - -verifyNotEnumerable(this, "Set"); -verifyWritable(this, "Set"); -verifyConfigurable(this, "Set"); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Set/prototype/size/length.js b/js/src/tests/test262/built-ins/Set/prototype/size/length.js index 9ba1b86f7811..4b0b0675dd7b 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/size/length.js +++ b/js/src/tests/test262/built-ins/Set/prototype/size/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.9 +esid: sec-get-set.prototype.size description: > get Set.prototype.size diff --git a/js/src/tests/test262/built-ins/Set/prototype/size/name.js b/js/src/tests/test262/built-ins/Set/prototype/size/name.js index d8d974941ce6..79723d8f0e0d 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/size/name.js +++ b/js/src/tests/test262/built-ins/Set/prototype/size/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.9 +esid: sec-get-set.prototype.size description: > get Set.prototype.size diff --git a/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-before-after-add-delete.js b/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-before-after-add-delete.js index 40430b095f0a..6a6c083bae3f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-before-after-add-delete.js +++ b/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-before-after-add-delete.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.9 +esid: sec-get-set.prototype.size description: > get Set.prototype.size diff --git a/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-by-insertion.js b/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-by-insertion.js index c264a5c1ddc5..b1ea12fc5f07 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-by-insertion.js +++ b/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-by-insertion.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.9 +esid: sec-get-set.prototype.size description: > get Set.prototype.size diff --git a/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-by-iterable.js b/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-by-iterable.js index e97fa3123553..9ef5423a7085 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-by-iterable.js +++ b/js/src/tests/test262/built-ins/Set/prototype/size/returns-count-of-present-values-by-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.9 +esid: sec-get-set.prototype.size description: > get Set.prototype.size diff --git a/js/src/tests/test262/built-ins/Set/prototype/size/size.js b/js/src/tests/test262/built-ins/Set/prototype/size/size.js index ff64bb2a0971..18b0566e2cf4 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/size/size.js +++ b/js/src/tests/test262/built-ins/Set/prototype/size/size.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.9 +esid: sec-get-set.prototype.size description: > get Set.prototype.size diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-array.js b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-array.js index 2cedb8d58718..8c09871a1a0d 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-array.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-array.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-map.js b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-map.js index e399cfcbf8a6..ba9452f718fc 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-map.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-map.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-object.js b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-object.js index a56b2754a0fb..8c96537bd794 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-object.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-object.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-set-prototype.js b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-set-prototype.js index 4e16133e02c1..6d9fcceecb10 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-set-prototype.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-set-prototype.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-weakset.js b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-weakset.js index 30f013e9c8be..24a79a9138cd 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-weakset.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-weakset.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/length.js b/js/src/tests/test262/built-ins/Set/prototype/values/length.js index 13c6cc19744b..8e49d1bc5173 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/length.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/length.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/name.js b/js/src/tests/test262/built-ins/Set/prototype/values/name.js index d3ffda7b7e41..a2458e9505fc 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/name.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/name.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/returns-iterator-empty.js b/js/src/tests/test262/built-ins/Set/prototype/values/returns-iterator-empty.js index e94de1e90926..92c4dff059a0 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/returns-iterator-empty.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/returns-iterator-empty.js @@ -2,9 +2,9 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- - description: > - Returns an iterator that's already done if Set is empty. - es6id: 23.2.3.10 +esid: sec-set.prototype.values +description: > + Returns an iterator that's already done if Set is empty. ---*/ var set = new Set(); diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/returns-iterator.js b/js/src/tests/test262/built-ins/Set/prototype/values/returns-iterator.js index f70d95efd8ac..319cbbddbe31 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/returns-iterator.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/returns-iterator.js @@ -2,10 +2,10 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- - description: > - The method should return a valid iterator with the context as the - IteratedObject. - es6id: 23.2.3.10 +esid: sec-set.prototype.values +description: > + The method should return a valid iterator with the context as the + IteratedObject. ---*/ var set = new Set(); diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-boolean.js b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-boolean.js index 56836529e800..83828a339d3f 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-boolean.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-boolean.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-null.js b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-null.js index 7876bbb481ed..253f10a31d4a 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-null.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-null.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-number.js b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-number.js index 125e8c812413..1c8319a523f8 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-number.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-number.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-string.js b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-string.js index d2394a65ebaa..e6e81fdba227 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-string.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-string.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-symbol.js b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-symbol.js index a25109889427..bd88d0fabf10 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-symbol.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-symbol.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-undefined.js b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-undefined.js index 9d3be925b1fc..14c2ec0a0eca 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-undefined.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/this-not-object-throw-undefined.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/values-iteration-mutable.js b/js/src/tests/test262/built-ins/Set/prototype/values/values-iteration-mutable.js index cc943f0a3ba3..c0ba8093c5a8 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/values-iteration-mutable.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/values-iteration-mutable.js @@ -2,12 +2,12 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- - description: > - When an item is added to the set after the iterator is created but before - the iterator is "done" (as defined by 23.2.5.2.1), the new item should be - accessible via iteration. When an item is added to the set after the - iterator is "done", the new item should not be accessible via iteration. - es6id: 23.2.3.10 +esid: sec-set.prototype.values +description: > + When an item is added to the set after the iterator is created but before + the iterator is "done" (as defined by 23.2.5.2.1), the new item should be + accessible via iteration. When an item is added to the set after the + iterator is "done", the new item should not be accessible via iteration. ---*/ var set = new Set(); diff --git a/js/src/tests/test262/built-ins/Set/prototype/values/values.js b/js/src/tests/test262/built-ins/Set/prototype/values/values.js index 08068a23e20d..4a02e37d00ca 100644 --- a/js/src/tests/test262/built-ins/Set/prototype/values/values.js +++ b/js/src/tests/test262/built-ins/Set/prototype/values/values.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.10 +esid: sec-set.prototype.values description: > Set.prototype.values ( ) diff --git a/js/src/tests/test262/built-ins/Set/set-does-not-throw-when-add-is-not-callable.js b/js/src/tests/test262/built-ins/Set/set-does-not-throw-when-add-is-not-callable.js index 6ef5492164af..b76957c90e0a 100644 --- a/js/src/tests/test262/built-ins/Set/set-does-not-throw-when-add-is-not-callable.js +++ b/js/src/tests/test262/built-ins/Set/set-does-not-throw-when-add-is-not-callable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-get-add-method-failure.js b/js/src/tests/test262/built-ins/Set/set-get-add-method-failure.js index e097904635ad..c201c60f6ce1 100644 --- a/js/src/tests/test262/built-ins/Set/set-get-add-method-failure.js +++ b/js/src/tests/test262/built-ins/Set/set-get-add-method-failure.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-iterable-calls-add.js b/js/src/tests/test262/built-ins/Set/set-iterable-calls-add.js index e1334788326e..5655c98e82d1 100644 --- a/js/src/tests/test262/built-ins/Set/set-iterable-calls-add.js +++ b/js/src/tests/test262/built-ins/Set/set-iterable-calls-add.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-iterable-empty-does-not-call-add.js b/js/src/tests/test262/built-ins/Set/set-iterable-empty-does-not-call-add.js index e928b3683915..2ccd6a1a039a 100644 --- a/js/src/tests/test262/built-ins/Set/set-iterable-empty-does-not-call-add.js +++ b/js/src/tests/test262/built-ins/Set/set-iterable-empty-does-not-call-add.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-iterable-throws-when-add-is-not-callable.js b/js/src/tests/test262/built-ins/Set/set-iterable-throws-when-add-is-not-callable.js index e327969137bf..da2d3da374eb 100644 --- a/js/src/tests/test262/built-ins/Set/set-iterable-throws-when-add-is-not-callable.js +++ b/js/src/tests/test262/built-ins/Set/set-iterable-throws-when-add-is-not-callable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-iterable.js b/js/src/tests/test262/built-ins/Set/set-iterable.js index 8f7eef779c9f..7ab3f202f32e 100644 --- a/js/src/tests/test262/built-ins/Set/set-iterable.js +++ b/js/src/tests/test262/built-ins/Set/set-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-iterator-close-after-add-failure.js b/js/src/tests/test262/built-ins/Set/set-iterator-close-after-add-failure.js index 4ec88ecb78aa..8b78343ba67e 100644 --- a/js/src/tests/test262/built-ins/Set/set-iterator-close-after-add-failure.js +++ b/js/src/tests/test262/built-ins/Set/set-iterator-close-after-add-failure.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-iterator-next-failure.js b/js/src/tests/test262/built-ins/Set/set-iterator-next-failure.js index d5a4eb3c6533..a4bc2cc4c90d 100644 --- a/js/src/tests/test262/built-ins/Set/set-iterator-next-failure.js +++ b/js/src/tests/test262/built-ins/Set/set-iterator-next-failure.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-iterator-value-failure.js b/js/src/tests/test262/built-ins/Set/set-iterator-value-failure.js index 5ad4ffff8259..ef62c3864468 100644 --- a/js/src/tests/test262/built-ins/Set/set-iterator-value-failure.js +++ b/js/src/tests/test262/built-ins/Set/set-iterator-value-failure.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-newtarget.js b/js/src/tests/test262/built-ins/Set/set-newtarget.js index 8ef18f0fabc1..2a32deaffd58 100644 --- a/js/src/tests/test262/built-ins/Set/set-newtarget.js +++ b/js/src/tests/test262/built-ins/Set/set-newtarget.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-no-iterable.js b/js/src/tests/test262/built-ins/Set/set-no-iterable.js index 9dd7698822c4..5ccdc4f7639f 100644 --- a/js/src/tests/test262/built-ins/Set/set-no-iterable.js +++ b/js/src/tests/test262/built-ins/Set/set-no-iterable.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set-undefined-newtarget.js b/js/src/tests/test262/built-ins/Set/set-undefined-newtarget.js index d905d0743dea..f1f5dbb15e26 100644 --- a/js/src/tests/test262/built-ins/Set/set-undefined-newtarget.js +++ b/js/src/tests/test262/built-ins/Set/set-undefined-newtarget.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/set.js b/js/src/tests/test262/built-ins/Set/set.js index 66b5a2f0a997..244eb8b69b42 100644 --- a/js/src/tests/test262/built-ins/Set/set.js +++ b/js/src/tests/test262/built-ins/Set/set.js @@ -1,7 +1,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.1.1 +esid: sec-set-constructor description: > Set ( [ iterable ] ) diff --git a/js/src/tests/test262/built-ins/Set/symbol-as-entry.js b/js/src/tests/test262/built-ins/Set/symbol-as-entry.js deleted file mode 100644 index 6981566146b5..000000000000 --- a/js/src/tests/test262/built-ins/Set/symbol-as-entry.js +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2013 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -es6id: 19.4 -description: > - Symbol as Set entry -features: [Symbol, Set] ----*/ -var set = new Set(); -var sym = Symbol(); - -set.add(sym); - -assert.sameValue(set.size, 1, "The value of `set.size` is `1`, after executing `set.add(sym)`"); -assert.sameValue(set.has(sym), true, "`set.has(sym)` returns `true`"); -assert.sameValue(set.delete(sym), true, "`set.delete(sym)` returns `true`"); -assert.sameValue(set.size, 0, "The value of `set.size` is `0`"); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Set/valid-values.js b/js/src/tests/test262/built-ins/Set/valid-values.js new file mode 100644 index 000000000000..719c179e5f5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Set/valid-values.js @@ -0,0 +1,390 @@ +// |reftest| skip-if(!this.hasOwnProperty('WeakRef')) -- WeakRef is not enabled unconditionally +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-set.prototype.add +description: Observing the expected behavior of valid values +info: | + Set.prototype.add ( value ) + + ... + For each element e of entries, do + If e is not empty and SameValueZero(e, value) is true, then + Return S. + If value is -0, set value to +0. + Append value as the last element of entries. + ... + +features: [BigInt, Symbol, TypedArray, WeakRef] +---*/ + + +const negativeZero = -0; +const positiveZero = +0; +const zero = 0; +const one = 1; +const twoRaisedToFiftyThreeMinusOne = 2 ** 53 - 1; +const int32Array = new Int32Array([zero, one]); +const uint32Array = new Uint32Array([zero, one]); +const n = 100000000000000000000000000000000000000000000000000000000000000000000000000000000001n; +const bigInt = BigInt('100000000000000000000000000000000000000000000000000000000000000000000000000000000001'); +const n1 = 1n; +const n53 = 9007199254740991n; +const fiftyThree = BigInt('9007199254740991'); +const bigInt64Array = new BigInt64Array([n1, n53]); +const bigUint64Array = new BigUint64Array([n1, n53]); +const symbol = Symbol(''); +const object = {}; +const array = {}; +const string = ''; +const booleanTrue = true; +const booleanFalse = true; +const functionExprValue = function() {}; +const arrowFunctionValue = () => {}; +const classValue = class {}; +const map = new Map(); +const set = new Set(); +const weakMap = new WeakMap(); +const weakRef = new WeakRef({}); +const weakSet = new WeakSet(); +const nullValue = null; +const undefinedValue = undefined; +let unassigned; + +{ + const s = new Set([negativeZero, negativeZero]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(negativeZero), true); + s.delete(negativeZero); + assert.sameValue(s.size, 0); + s.add(negativeZero); + assert.sameValue(s.has(negativeZero), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([positiveZero, positiveZero]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(positiveZero), true); + s.delete(positiveZero); + assert.sameValue(s.size, 0); + s.add(positiveZero); + assert.sameValue(s.has(positiveZero), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([zero, zero]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(zero), true); + s.delete(zero); + assert.sameValue(s.size, 0); + s.add(zero); + assert.sameValue(s.has(zero), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([one, one]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(one), true); + s.delete(one); + assert.sameValue(s.size, 0); + s.add(one); + assert.sameValue(s.has(one), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([twoRaisedToFiftyThreeMinusOne, twoRaisedToFiftyThreeMinusOne]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(twoRaisedToFiftyThreeMinusOne), true); + s.delete(twoRaisedToFiftyThreeMinusOne); + assert.sameValue(s.size, 0); + s.add(twoRaisedToFiftyThreeMinusOne); assert.sameValue(s.has(twoRaisedToFiftyThreeMinusOne), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([int32Array, int32Array]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(int32Array), true); + s.delete(int32Array); + assert.sameValue(s.size, 0); + s.add(int32Array); + assert.sameValue(s.has(int32Array), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([uint32Array, uint32Array]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(uint32Array), true); + s.delete(uint32Array); + assert.sameValue(s.size, 0); + s.add(uint32Array); + assert.sameValue(s.has(uint32Array), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([n, n]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(n), true); + s.delete(n); + assert.sameValue(s.size, 0); + s.add(n); + assert.sameValue(s.has(n), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([bigInt, bigInt]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(bigInt), true); + s.delete(bigInt); + assert.sameValue(s.size, 0); + s.add(bigInt); + assert.sameValue(s.has(bigInt), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([n1, n1]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(n1), true); + s.delete(n1); + assert.sameValue(s.size, 0); + s.add(n1); + assert.sameValue(s.has(n1), true); +} +{ const s = new Set([n53, n53]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(n53), true); + s.delete(n53); + assert.sameValue(s.size, 0); + s.add(n53); + assert.sameValue(s.has(n53), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([fiftyThree, fiftyThree]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(fiftyThree), true); + s.delete(fiftyThree); + assert.sameValue(s.size, 0); + s.add(fiftyThree); + assert.sameValue(s.has(fiftyThree), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([bigInt64Array, bigInt64Array]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(bigInt64Array), true); + s.delete(bigInt64Array); + assert.sameValue(s.size, 0); + s.add(bigInt64Array); + assert.sameValue(s.has(bigInt64Array), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([bigUint64Array, bigUint64Array]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(bigUint64Array), true); + s.delete(bigUint64Array); + assert.sameValue(s.size, 0); + s.add(bigUint64Array); + assert.sameValue(s.has(bigUint64Array), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([symbol, symbol]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(symbol), true); + s.delete(symbol); + assert.sameValue(s.size, 0); + s.add(symbol); + assert.sameValue(s.has(symbol), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([object, object]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(object), true); + s.delete(object); + assert.sameValue(s.size, 0); + s.add(object); + assert.sameValue(s.has(object), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([array, array]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(array), true); + s.delete(array); + assert.sameValue(s.size, 0); + s.add(array); + assert.sameValue(s.has(array), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([string, string]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(string), true); + s.delete(string); + assert.sameValue(s.size, 0); + s.add(string); + assert.sameValue(s.has(string), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([booleanTrue, booleanTrue]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(booleanTrue), true); + s.delete(booleanTrue); + assert.sameValue(s.size, 0); + s.add(booleanTrue); + assert.sameValue(s.has(booleanTrue), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([booleanFalse, booleanFalse]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(booleanFalse), true); + s.delete(booleanFalse); + assert.sameValue(s.size, 0); + s.add(booleanFalse); + assert.sameValue(s.has(booleanFalse), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([functionExprValue, functionExprValue]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(functionExprValue), true); + s.delete(functionExprValue); + assert.sameValue(s.size, 0); + s.add(functionExprValue); assert.sameValue(s.has(functionExprValue), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([arrowFunctionValue, arrowFunctionValue]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(arrowFunctionValue), true); + s.delete(arrowFunctionValue); + assert.sameValue(s.size, 0); + s.add(arrowFunctionValue); assert.sameValue(s.has(arrowFunctionValue), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([classValue, classValue]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(classValue), true); + s.delete(classValue); + assert.sameValue(s.size, 0); + s.add(classValue); + assert.sameValue(s.has(classValue), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([map, map]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(map), true); + s.delete(map); + assert.sameValue(s.size, 0); + s.add(map); + assert.sameValue(s.has(map), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([set, set]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(set), true); + s.delete(set); + assert.sameValue(s.size, 0); + s.add(set); + assert.sameValue(s.has(set), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([weakMap, weakMap]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(weakMap), true); + s.delete(weakMap); + assert.sameValue(s.size, 0); + s.add(weakMap); + assert.sameValue(s.has(weakMap), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([weakRef, weakRef]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(weakRef), true); + s.delete(weakRef); + assert.sameValue(s.size, 0); + s.add(weakRef); + assert.sameValue(s.has(weakRef), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([weakSet, weakSet]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(weakSet), true); + s.delete(weakSet); + assert.sameValue(s.size, 0); + s.add(weakSet); + assert.sameValue(s.has(weakSet), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([nullValue, nullValue]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(nullValue), true); + s.delete(nullValue); + assert.sameValue(s.size, 0); + s.add(nullValue); + assert.sameValue(s.has(nullValue), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([undefinedValue, undefinedValue]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(undefinedValue), true); + s.delete(undefinedValue); + assert.sameValue(s.size, 0); + s.add(undefinedValue); + assert.sameValue(s.has(undefinedValue), true); + assert.sameValue(s.size, 1); +}; + +{ + const s = new Set([unassigned, unassigned]); + assert.sameValue(s.size, 1); + assert.sameValue(s.has(unassigned), true); + s.delete(unassigned); + assert.sameValue(s.size, 0); + s.add(unassigned); + assert.sameValue(s.has(unassigned), true); + assert.sameValue(s.size, 1); +}; + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/SetIteratorPrototype/next/iteration-mutable.js b/js/src/tests/test262/built-ins/SetIteratorPrototype/next/iteration-mutable.js index d4bd85f500e1..5f08a84c1d68 100644 --- a/js/src/tests/test262/built-ins/SetIteratorPrototype/next/iteration-mutable.js +++ b/js/src/tests/test262/built-ins/SetIteratorPrototype/next/iteration-mutable.js @@ -1,7 +1,7 @@ // Copyright (C) 2014 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.11 +esid: sec-set.prototype-@@iterator description: > When an item is added to the set after the iterator is created but before the iterator is "done" (as defined by 23.2.5.2.1), the new item should be diff --git a/js/src/tests/test262/built-ins/SetIteratorPrototype/next/iteration.js b/js/src/tests/test262/built-ins/SetIteratorPrototype/next/iteration.js index 0006a3028587..18db7e2108e1 100644 --- a/js/src/tests/test262/built-ins/SetIteratorPrototype/next/iteration.js +++ b/js/src/tests/test262/built-ins/SetIteratorPrototype/next/iteration.js @@ -1,7 +1,7 @@ // Copyright (C) 2014 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 23.2.3.11 +esid: sec-set.prototype-@@iterator description: > The method should return a valid iterator with the context as the IteratedObject. diff --git a/js/src/tests/test262/built-ins/Realm/prototype/browser.js b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/prototype/browser.js rename to js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/browser.js diff --git a/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/length-throws-typeerror.js b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/length-throws-typeerror.js new file mode 100644 index 000000000000..1b16a7174029 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/length-throws-typeerror.js @@ -0,0 +1,39 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrappedfunctioncreate +description: > + WrappedFunctionCreate throws a TypeError from its caller realm. +info: | + WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) + + ... + 7. Let result be CopyNameAndLength(wrapped, Target). + 8. If result is an Abrupt Completion, throw a TypeError exception. + ... + +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.throws(TypeError, () => r.evaluate(` +function fn() {} +Object.defineProperty(fn, 'length', { + get: () => { + throw new Error('blah'); + }, + enumerable: false, + configurable: true, +}); +fn; +`), 'expect a TypeError on length getter throwing'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/length.js b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/length.js new file mode 100644 index 000000000000..8334670630c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/length.js @@ -0,0 +1,125 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrappedfunctioncreate +description: > + The value of WrappedFunction.name is copied from the target function +info: | + WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) + + ... + 7. Let result be CopyNameAndLength(wrapped, Target). + ... + + CopyNameAndLength ( F: a function object, Target: a function object, prefix: a String, optional argCount: a Number, ) + + 1. If argCount is undefined, then set argCount to 0. + 2. Let L be 0. + 3. Let targetHasLength be ? HasOwnProperty(Target, "length"). + 4. If targetHasLength is true, then + a. Let targetLen be ? Get(Target, "length"). + b. If Type(targetLen) is Number, then + i. If targetLen is +∞𝔽, set L to +∞. + ii. Else if targetLen is -∞𝔽, set L to 0. + iii. Else, + 1. Let targetLenAsInt be ! ToIntegerOrInfinity(targetLen). + 2. Assert: targetLenAsInt is finite. + 3. Set L to max(targetLenAsInt - argCount, 0). + 5. Perform ! SetFunctionLength(F, L). + ... + + SetFunctionLength ( F, length ) + + ... + 2. Return ! DefinePropertyOrThrow(F, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }). + +includes: [propertyHelper.js] +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + + +let wrapped = r.evaluate(` +function fn(foo, bar) {} +fn; +`); +verifyProperty(wrapped, "length", { + value: 2, + enumerable: false, + writable: false, + configurable: true, +}); + + +wrapped = r.evaluate(` +function fn() {} +delete fn.length; +fn; +`); +verifyProperty(wrapped, "length", { + value: 0, + enumerable: false, + writable: false, + configurable: true, +}); + + +wrapped = r.evaluate(` +function fn() {} +Object.defineProperty(fn, 'length', { + get: () => Infinity, + enumerable: false, + configurable: true, +}); +fn; +`); +verifyProperty(wrapped, "length", { + value: Infinity, + enumerable: false, + writable: false, + configurable: true, +}); + + +wrapped = r.evaluate(` +function fn() {} +Object.defineProperty(fn, 'length', { + get: () => -Infinity, + enumerable: false, + configurable: true, +}); +fn; +`); +verifyProperty(wrapped, "length", { + value: 0, + enumerable: false, + writable: false, + configurable: true, +}); + + +wrapped = r.evaluate(` +function fn() {} +Object.defineProperty(fn, 'length', { + get: () => -1, + enumerable: false, + configurable: true, +}); +fn; +`); +verifyProperty(wrapped, "length", { + value: 0, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/name-throws-typeerror.js b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/name-throws-typeerror.js new file mode 100644 index 000000000000..ba2ef3afdd57 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/name-throws-typeerror.js @@ -0,0 +1,39 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrappedfunctioncreate +description: > + WrappedFunctionCreate throws a TypeError from its caller realm. +info: | + WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) + + ... + 7. Let result be CopyNameAndLength(wrapped, Target). + 8. If result is an Abrupt Completion, throw a TypeError exception. + ... + +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.throws(TypeError, () => r.evaluate(` +function fn() {} +Object.defineProperty(fn, 'name', { + get: () => { + throw new Error('blah'); + }, + enumerable: false, + configurable: true, +}); +fn; +`), 'expect a TypeError on name getter throwing'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/name.js b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/name.js new file mode 100644 index 000000000000..ebe39e58f9e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/name.js @@ -0,0 +1,86 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrappedfunctioncreate +description: > + The value of WrappedFunction.name is copied from the target function +info: | + WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) + + ... + 7. Let result be CopyNameAndLength(wrapped, Target). + ... + + CopyNameAndLength ( F: a function object, Target: a function object, prefix: a String, optional argCount: a Number, ) + + ... + 6. Let targetName be ? Get(Target, "name"). + 7. If Type(targetName) is not String, set targetName to the empty String. + 8. Perform ! SetFunctionName(F, targetName, prefix). + + SetFunctionName ( F, name [ , prefix ] ) + + ... + 6. Return ! DefinePropertyOrThrow(F, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }). + +includes: [propertyHelper.js] +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +let wrapped = r.evaluate(` +function fn() {} +fn; +`); +verifyProperty(wrapped, "name", { + value: "fn", + enumerable: false, + writable: false, + configurable: true, +}); + +// The name property is an accessor. +wrapped = r.evaluate(` +function fn() {} +Object.defineProperty(fn, 'name', { + get: () => "bar", + enumerable: false, + configurable: true, +}); +fn; +`); +verifyProperty(wrapped, "name", { + value: "bar", + enumerable: false, + writable: false, + configurable: true, +}); + +// The value of fn.name is not a string. +for (const name of [null, undefined, 0, '1n', false, NaN, Infinity, 'Symbol()', '[]', '{}']) { + wrapped = r.evaluate(` +function fn() {} +Object.defineProperty(fn, 'name', { + value: ${String(name)}, + enumerable: false, + configurable: true, +}); +fn; +`); + verifyProperty(wrapped, "name", { + value: "", + enumerable: false, + writable: false, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/shell.js b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/shell.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/shell.js rename to js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/shell.js diff --git a/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js new file mode 100644 index 000000000000..765b6cbad003 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js @@ -0,0 +1,43 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrapped-function-exotic-objects-call-thisargument-argumentslist +description: > + WrappedFunctionCreate throws a TypeError the target is a revoked proxy. + +info: | + WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) + 1. Let target be F.[[WrappedTargetFunction]]. + 2. Assert: IsCallable(target) is true. + 3. Let callerRealm be F.[[Realm]]. + 4. NOTE: Any exception objects produced after this point are associated with callerRealm. + 5. Let targetRealm be ? GetFunctionRealm(target). + ... + + GetFunctionRealm ( obj ) + ... + 3. If obj is a Proxy exotic object, then + a. If obj.[[ProxyHandler]] is null, throw a TypeError exception. + ... + +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +const fn = r.evaluate(` +globalThis.revocable = Proxy.revocable(() => {}, {}); + +globalThis.revocable.proxy; +`); +r.evaluate('revocable.revoke()'); +assert.throws(TypeError, () => fn()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/browser.js b/js/src/tests/test262/built-ins/ShadowRealm/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/browser.js rename to js/src/tests/test262/built-ins/ShadowRealm/browser.js diff --git a/js/src/tests/test262/built-ins/ShadowRealm/constructor.js b/js/src/tests/test262/built-ins/ShadowRealm/constructor.js new file mode 100644 index 000000000000..5a75c106ae41 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/constructor.js @@ -0,0 +1,21 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm-constructor +description: > + ShadowRealm is a constructor and has [[Construct]] internal method. +includes: [isConstructor.js] +features: [ShadowRealm, Reflect.construct] +---*/ +assert.sameValue( + typeof ShadowRealm, + 'function', + 'This test must fail if ShadowRealm is not a function' +); + +assert(isConstructor(ShadowRealm)); +assert.sameValue(Object.getPrototypeOf(ShadowRealm), Function.prototype); +new ShadowRealm(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/descriptor.js b/js/src/tests/test262/built-ins/ShadowRealm/descriptor.js similarity index 52% rename from js/src/tests/test262/built-ins/Realm/descriptor.js rename to js/src/tests/test262/built-ins/ShadowRealm/descriptor.js index 6d83ff53aff8..f92fab146fb2 100644 --- a/js/src/tests/test262/built-ins/Realm/descriptor.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/descriptor.js @@ -1,15 +1,15 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm-constructor +esid: sec-shadowrealm-constructor description: > - The Realm constructor is the initial value of the "Realm" property of the global object. + The ShadowRealm constructor is the initial value of the "ShadowRealm" property of the global object. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(this, "Realm", { +verifyProperty(this, "ShadowRealm", { enumerable: false, writable: true, configurable: true, diff --git a/js/src/tests/test262/built-ins/Realm/extensibility.js b/js/src/tests/test262/built-ins/ShadowRealm/extensibility.js similarity index 61% rename from js/src/tests/test262/built-ins/Realm/extensibility.js rename to js/src/tests/test262/built-ins/ShadowRealm/extensibility.js index d7076ca62049..6f60fddc66c8 100644 --- a/js/src/tests/test262/built-ins/Realm/extensibility.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/extensibility.js @@ -1,18 +1,18 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Leo Balter. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm-constructor +esid: sec-shadowrealm-constructor description: > - The Realm constructor is extensible + The ShadowRealm constructor is extensible info: | 17 ECMAScript Standard Built-in Objects Unless specified otherwise, the [[Extensible]] internal slot of a built-in object initially has the value true. -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -assert.sameValue(Object.isExtensible(Realm), true); +assert.sameValue(Object.isExtensible(ShadowRealm), true); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/instance-extensibility.js b/js/src/tests/test262/built-ins/ShadowRealm/instance-extensibility.js similarity index 70% rename from js/src/tests/test262/built-ins/Realm/instance-extensibility.js rename to js/src/tests/test262/built-ins/ShadowRealm/instance-extensibility.js index c156afebff3e..7661d75acac8 100644 --- a/js/src/tests/test262/built-ins/Realm/instance-extensibility.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/instance-extensibility.js @@ -1,17 +1,17 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Leo Balter. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm +esid: sec-shadowrealm description: > The new instance is extensible info: | - Realm ( ) + ShadowRealm ( ) ... - 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Realm.prototype%", - « [[Realm]], [[ExecutionContext]] »). + 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%ShadowRealm.prototype%", + « [[ShadowRealm]], [[ExecutionContext]] »). ... 13. Return O. @@ -19,14 +19,14 @@ info: | internal slots [[Prototype]] and [[Extensible]]. The latter will have its value set to true. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -const realm = new Realm(); +const realm = new ShadowRealm(); assert(Object.isExtensible(realm)); -Object.defineProperty(realm, 'foo', {}); +Object.defineProperty(realm, 'foo', { configurable: true }); assert(realm.hasOwnProperty('foo'), 'confirms extensibility adding a new property'); Object.defineProperty(realm, 'foo', { diff --git a/js/src/tests/test262/built-ins/ShadowRealm/instance.js b/js/src/tests/test262/built-ins/ShadowRealm/instance.js new file mode 100644 index 000000000000..cbb8a4d47ab1 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/instance.js @@ -0,0 +1,36 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm-constructor +description: > + new ShadowRealm() returns a shadow realm instance +info: | + ShadowRealm ( ) + + ... + 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%ShadowRealm.prototype%", + « [[ShadowRealm]], [[ExecutionContext]] »). + ... + 13. Return O. +features: [ShadowRealm] +---*/ +assert.sameValue( + typeof ShadowRealm, + 'function', + 'This test must fail if ShadowRealm is not a function' +); + +var realm = new ShadowRealm(); + +assert(realm instanceof ShadowRealm); +assert.sameValue( + Object.getPrototypeOf(realm), + ShadowRealm.prototype, + '[[Prototype]] is set to %ShadowRealm.prototype%' +); + +var otherRealm = new ShadowRealm(); +assert.notSameValue(realm, otherRealm, 'each instance is different'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/length.js b/js/src/tests/test262/built-ins/ShadowRealm/length.js similarity index 80% rename from js/src/tests/test262/built-ins/Realm/length.js rename to js/src/tests/test262/built-ins/ShadowRealm/length.js index c1750aea5dbf..af51e618273b 100644 --- a/js/src/tests/test262/built-ins/Realm/length.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/length.js @@ -1,12 +1,12 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm-constructor +esid: sec-shadowrealm-constructor description: > - The value of Realm.length is 0 + The value of ShadowRealm.length is 0 info: | - Realm ( ) + ShadowRealm ( ) Every built-in function object, including constructors, has a "length" property whose value is a non-negative integral Number. Unless otherwise specified, this value @@ -18,10 +18,10 @@ info: | the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(Realm, "length", { +verifyProperty(ShadowRealm, "length", { value: 0, enumerable: false, writable: false, diff --git a/js/src/tests/test262/built-ins/Realm/name.js b/js/src/tests/test262/built-ins/ShadowRealm/name.js similarity index 65% rename from js/src/tests/test262/built-ins/Realm/name.js rename to js/src/tests/test262/built-ins/ShadowRealm/name.js index 81e126c46a58..ed86fe4e49f9 100644 --- a/js/src/tests/test262/built-ins/Realm/name.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/name.js @@ -1,25 +1,25 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-ecmascript-standard-built-in-objects description: > - The value of Realm.name is 'Realm' + The value of ShadowRealm.name is 'ShadowRealm' info: | - Every built-in function object, including constructors, has a "name" property - whose value is a String. Unless otherwise specified, this value is the name - that is given to the function in this specification. + Every built-in function object, including constructors, has a "name" property + whose value is a String. Unless otherwise specified, this value is the name + that is given to the function in this specification. - Unless otherwise specified, the "name" property of a built-in function - object has the attributes + Unless otherwise specified, the "name" property of a built-in function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(Realm, "name", { - value: "Realm", +verifyProperty(ShadowRealm, "name", { + value: "ShadowRealm", enumerable: false, writable: false, configurable: true, diff --git a/js/src/tests/test262/built-ins/Realm/proto.js b/js/src/tests/test262/built-ins/ShadowRealm/proto.js similarity index 61% rename from js/src/tests/test262/built-ins/Realm/proto.js rename to js/src/tests/test262/built-ins/ShadowRealm/proto.js index 475dcac72cb9..46ec1a7b7ebc 100644 --- a/js/src/tests/test262/built-ins/Realm/proto.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/proto.js @@ -1,18 +1,18 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-properties-of-the-realm-constructor +esid: sec-properties-of-the-shadowrealm-constructor description: > - The [[Prototype]] of Realm is Function.Prototype. + The [[Prototype]] of ShadowRealm is Function.Prototype. info: | Unless otherwise specified every built-in function and every built-in constructor has the Function prototype object, which is the initial value of the expression Function.prototype, as the value of its [[Prototype]] internal slot. -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -assert.sameValue(Object.getPrototypeOf(Realm), Function.prototype); +assert.sameValue(Object.getPrototypeOf(ShadowRealm), Function.prototype); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/Symbol.toStringTag.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/Symbol.toStringTag.js similarity index 67% rename from js/src/tests/test262/built-ins/Realm/prototype/Symbol.toStringTag.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/Symbol.toStringTag.js index 43b18c9b5494..415009d3d122 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/Symbol.toStringTag.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/Symbol.toStringTag.js @@ -1,22 +1,22 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Leo Balter. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype-@@tostringtag +esid: sec-shadowrealm.prototype-@@tostringtag description: > `Symbol.toStringTag` property descriptor info: | The initial value of the @@toStringTag property is the String value - "Realm". + "ShadowRealm". This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [callable-boundary-realms, Symbol.toStringTag] +features: [ShadowRealm, Symbol.toStringTag] ---*/ -verifyProperty(Realm.prototype, Symbol.toStringTag, { - value: 'Realm', +verifyProperty(ShadowRealm.prototype, Symbol.toStringTag, { + value: 'ShadowRealm', enumerable: false, writable: false, configurable: true diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/browser.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/browser.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/era/browser.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/Calendar/prototype/era/browser.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/browser.js diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/descriptor.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/descriptor.js similarity index 51% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/descriptor.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/descriptor.js index bd75d8fcac23..3d9628ea3608 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/descriptor.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/descriptor.js @@ -1,15 +1,15 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate is an ECMAScript Standard built-in object function. + ShadowRealm.prototype.evaluate is an ECMAScript Standard built-in object function. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(Realm.prototype, "evaluate", { +verifyProperty(ShadowRealm.prototype, "evaluate", { enumerable: false, writable: true, configurable: true, diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/errors-from-the-other-realm-is-wrapped-into-a-typeerror.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/errors-from-the-other-realm-is-wrapped-into-a-typeerror.js new file mode 100644 index 000000000000..843a16590053 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/errors-from-the-other-realm-is-wrapped-into-a-typeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm.prototype.evaluate wraps errors from other realm into TypeErrors +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.throws(SyntaxError, () => r.evaluate('...'), 'SyntaxError exposed to Parent'); +assert.throws(TypeError, () => r.evaluate('throw 42'), 'throw primitive => TypeError'); +assert.throws(TypeError, () => r.evaluate('throw new ReferenceError("aaa")'), 'custom ctor => TypeError'); +assert.throws(TypeError, () => r.evaluate('throw new TypeError("aaa")'), 'Child TypeError => Parent TypeError'); +assert.throws(TypeError, () => r.evaluate('eval("...");'), 'syntaxerror parsing coming after runtime evaluation'); +assert.throws(TypeError, () => r.evaluate(` + 'use strict'; + eval("var public = 1;"); +`), 'strict-mode only syntaxerror parsing coming after runtime evaluation'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-available-properties.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-available-properties.js new file mode 100644 index 000000000000..ec179979f535 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-available-properties.js @@ -0,0 +1,108 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + The ShadowRealm global must include ECMAScript global properties +info: | + ShadowRealm ( ) + + ... + 3. Let realmRec be CreateRealm(). + 4. Set O.[[ShadowRealm]] to realmRec. + ... + 10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined). + 11. Perform ? SetDefaultGlobalBindings(O.[[ShadowRealm]]). + 12. Perform ? HostInitializeShadowRealm(O.[[ShadowRealm]]). + + SetDefaultGlobalBindings ( realmRec ) + + 1. Let global be realmRec.[[GlobalObject]]. + 2. For each property of the Global Object specified in clause 19, do + a. Let name be the String value of the property name. + b. Let desc be the fully populated data Property Descriptor for the property, containing the specified attributes for the property. For properties listed in 19.2, 19.3, or 19.4 the value of the [[Value]] attribute is the corresponding intrinsic object from realmRec. + c. Perform ? DefinePropertyOrThrow(global, name, desc). + 3. Return global. +features: [ShadowRealm] +includes: [compareArray.js] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +const properties = [ + 'globalThis', + 'Infinity', + 'NaN', + 'undefined', + 'eval', + 'isFinite', + 'isNaN', + 'parseFloat', + 'parseInt', + 'decodeURI', + 'decodeURIComponent', + 'encodeURI', + 'encodeURIComponent', + 'AggregateError', + 'Array', + 'ArrayBuffer', + 'BigInt', + 'BigInt64Array', + 'BigUint64Array', + 'Boolean', + 'DataView', + 'Date', + 'Error', + 'EvalError', + 'FinalizationRegistry', + 'Float32Array', + 'Float64Array', + 'Function', + 'Int8Array', + 'Int16Array', + 'Int32Array', + 'Map', + 'Number', + 'Object', + 'Promise', + 'Proxy', + 'RangeError', + 'ReferenceError', + 'RegExp', + 'Set', + 'SharedArrayBuffer', + 'String', + 'Symbol', + 'SyntaxError', + 'TypeError', + 'Uint8Array', + 'Uint8ClampedArray', + 'Uint16Array', + 'Uint32Array', + 'URIError', + 'WeakMap', + 'WeakRef', + 'WeakSet', + 'Atomics', + 'JSON', + 'Math', + 'Reflect', +]; + +const available = properties.filter(name => { + // This test is intentionally not using wrapped functions. + // This test should not depend on wrapped functions. + return r.evaluate(`Object.prototype.hasOwnProperty.call(globalThis, '${name}')`); +}); + +// This comparison is intentional to list difference in names if the the assertion fails +assert.compareArray(properties, available); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-config-only-properties.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-config-only-properties.js new file mode 100644 index 000000000000..d1ee466f58b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-config-only-properties.js @@ -0,0 +1,101 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + Properties of globalThis must be configurable +info: | + ShadowRealm ( ) + + ... + 3. Let realmRec be CreateRealm(). + 4. Set O.[[ShadowRealm]] to realmRec. + ... + 10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined). + 11. Perform ? SetDefaultGlobalBindings(O.[[ShadowRealm]]). + 12. Perform ? HostInitializeShadowRealm(O.[[ShadowRealm]]). + + Runtime Semantics: HostInitializeShadowRealm ( realm ) + + HostInitializeShadowRealm is an implementation-defined abstract operation + used to inform the host of any newly created realms from the ShadowRealm + constructor. Its return value is not used, though it may throw an exception. + The idea of this hook is to initialize host data structures related to the + ShadowRealm, e.g., for module loading. + + The host may use this hook to add properties to the ShadowRealm's global + object. Those properties must be configurable. +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +const anyMissed = r.evaluate(` + // These names are the only exception as non configurable values. + // Yet, they don't represent any object value. + const esNonConfigValues = [ + 'undefined', + 'Infinity', + 'NaN' + ]; + + const entries = Object.entries(Object.getOwnPropertyDescriptors(globalThis)); + + const missed = entries + .filter(entry => entry[1].configurable === false) + .map(([name]) => name) + .filter(name => !esNonConfigValues.includes(name)) + .join(', '); + + missed; +`); + +assert.sameValue(anyMissed, '', 'All globalThis properties must be configurable'); + +const result = r.evaluate(` + const ObjectKeys = Object.keys; + const hasOwn = Object.prototype.hasOwnProperty; + const savedGlobal = globalThis; + const names = Object.keys(Object.getOwnPropertyDescriptors(globalThis)); + + // These names are the only exception as non configurable values. + // Yet, they don't represent any object value. + const esNonConfigValues = [ + 'undefined', + 'Infinity', + 'NaN' + ]; + + // Delete every name except globalThis, for now + const remainingNames = names.filter(name => { + if (esNonConfigValues.includes(name)) { + return false; + } + + if (name !== 'globalThis') { + delete globalThis[name]; + return hasOwn.call(globalThis, name); + } + }); + + delete globalThis['globalThis']; + + if (hasOwn.call(savedGlobal, 'globalThis')) { + remainingNames.push('globalThis'); + } + + const failedDelete = remainingNames.join(', '); + + failedDelete; +`); + +assert.sameValue(result, '', 'deleting any globalThis property must be effective'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-orginary-object.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-orginary-object.js new file mode 100644 index 000000000000..aff781f8042c --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/globalthis-orginary-object.js @@ -0,0 +1,69 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + The globalThis must be an ordinary object from OrdinaryObjectCreate +info: | + ShadowRealm ( ) + + ... + 3. Let realmRec be CreateRealm(). + 4. Set O.[[ShadowRealm]] to realmRec. + ... + 10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined). + 11. Perform ? SetDefaultGlobalBindings(O.[[ShadowRealm]]). + 12. Perform ? HostInitializeShadowRealm(O.[[ShadowRealm]]). + + SetRealmGlobalObject ( realmRec, globalObj, thisValue ) + + 1. If globalObj is undefined, then + a. Let intrinsics be realmRec.[[Intrinsics]]. + b. Set globalObj to ! OrdinaryObjectCreate(intrinsics.[[%Object.prototype%]]). + 2. Assert: Type(globalObj) is Object. + 3. If thisValue is undefined, set thisValue to globalObj. + ... + + OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] ) + + 1. Let internalSlotsList be « [[Prototype]], [[Extensible]] ». + 2. If additionalInternalSlotsList is present, append each of its elements to internalSlotsList. + 3. Let O be ! MakeBasicObject(internalSlotsList). + 4. Set O.[[Prototype]] to proto. + 5. Return O. + + MakeBasicObject ( internalSlotsList ) + + ... + 5. If internalSlotsList contains [[Extensible]], set obj.[[Extensible]] to true. +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.sameValue( + r.evaluate('Object.getPrototypeOf(globalThis) === Object.prototype'), + true, + 'The [[Prototype]] of globalThis is Object.prototype' +); + +assert.sameValue( + r.evaluate('Object.isExtensible(globalThis)'), + true, + 'globalThis is extensible' +); + +assert.sameValue( + r.evaluate('globalThis.constructor === Object'), + true, + 'globalThis.constructor is Object' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/length.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/length.js similarity index 74% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/length.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/length.js index d87d4bdad5d5..12cfee648602 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/length.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/length.js @@ -1,12 +1,12 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - The value of Realm.prototype.evaluate.length is 1 + The value of ShadowRealm.prototype.evaluate.length is 1 info: | - Realm.prototype.evaluate ( sourceText ) + ShadowRealm.prototype.evaluate ( sourceText ) Every built-in function object, including constructors, has a "length" property whose value is a non-negative integral Number. Unless otherwise specified, this value @@ -18,10 +18,10 @@ info: | the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(Realm.prototype.evaluate, "length", { +verifyProperty(ShadowRealm.prototype.evaluate, "length", { value: 1, enumerable: false, writable: false, diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/name.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/name.js similarity index 60% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/name.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/name.js index 6c1708c77e56..8fd83468f7c7 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/name.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/name.js @@ -1,24 +1,24 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - The value of Realm.prototype.evaluate.name is 'evaluate' + The value of ShadowRealm.prototype.evaluate.name is 'evaluate' info: | - Every built-in function object, including constructors, has a "name" property - whose value is a String. Unless otherwise specified, this value is the name - that is given to the function in this specification. + Every built-in function object, including constructors, has a "name" property + whose value is a String. Unless otherwise specified, this value is the name + that is given to the function in this specification. - Unless otherwise specified, the "name" property of a built-in function - object has the attributes + Unless otherwise specified, the "name" property of a built-in function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(Realm.prototype.evaluate, "name", { +verifyProperty(ShadowRealm.prototype.evaluate, "name", { value: "evaluate", enumerable: false, writable: false, diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/nested-realms.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/nested-realms.js new file mode 100644 index 000000000000..2bbe715247df --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/nested-realms.js @@ -0,0 +1,40 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm can create a nested ShadowRealm +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +globalThis.myValue = 'a'; +const realm1 = new ShadowRealm(); + +realm1.evaluate('globalThis.myValue = "b";'); + +const realm2Evaluate = realm1.evaluate(` + const realm2 = new ShadowRealm(); + + (str) => realm2.evaluate(str); +`); + +realm2Evaluate('globalThis.myValue = "c";'); + +assert.sameValue(globalThis.myValue, 'a'); +assert.sameValue(realm1.evaluate('globalThis.myValue'), 'b'); +assert.sameValue(realm2Evaluate('globalThis.myValue'), 'c'); + +realm1.evaluate('globalThis.myValue = "d"'); + +assert.sameValue(globalThis.myValue, 'a', 'no side effects'); +assert.sameValue(realm1.evaluate('globalThis.myValue'), 'd', 'no side effects'); +assert.sameValue(realm2Evaluate('globalThis.myValue'), 'c', 'no side effects'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/no-conditional-strict-mode.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/no-conditional-strict-mode.js new file mode 100644 index 000000000000..107f59450b84 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/no-conditional-strict-mode.js @@ -0,0 +1,37 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + The new realm has no conditional strict mode based on its outer realm +info: | + This test should always run with the outer realm in both strict and non + strict mode to verify the realm code starts in non-strict mode. +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +const res = r.evaluate(` + function lol() { + arguments = 42; // This would be a SyntaxError if in strict mode + + return arguments; + } + lol; +`); + +assert.sameValue(res(), 42); + +const res2 = r.evaluate('var public = 1; 42'); + +assert.sameValue(res2, 42); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/not-constructor.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/not-constructor.js new file mode 100644 index 000000000000..c29b8f1d35a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/not-constructor.js @@ -0,0 +1,37 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm.prototype.evaluate is not a constructor. +includes: [isConstructor.js] +features: [ShadowRealm, Reflect.construct] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +assert.sameValue( + isConstructor(ShadowRealm.prototype.evaluate), + false, + 'isConstructor(ShadowRealm.prototype.evaluate) must return false' +); + +assert.throws(TypeError, () => { + new ShadowRealm.prototype.evaluate(""); +}, '`new ShadowRealm.prototype.evaluate("")` throws TypeError'); + +const r = new ShadowRealm(); +r.evaluate('globalThis.x = 0'); + +assert.throws(TypeError, () => { + new r.evaluate("globalThis.x += 1;"); +}, '`new r.evaluate("...")` throws TypeError'); + +assert.sameValue(r.evaluate('globalThis.x'), 0, 'No code evaluated in the new expression'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/proto.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/proto.js similarity index 58% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/proto.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/proto.js index b49e287072b5..5f1d4cc326fa 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/proto.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/proto.js @@ -1,18 +1,18 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - The [[Prototype]] of Realm.prototype.evaluate is Function.Prototype. + The [[Prototype]] of ShadowRealm.prototype.evaluate is Function.Prototype. Unless otherwise specified every built-in function and every built-in constructor has the Function prototype object, which is the initial value of the expression Function.prototype, as the value of its [[Prototype]] internal slot. -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -assert.sameValue(Object.getPrototypeOf(Realm.prototype.evaluate), Function.prototype); +assert.sameValue(Object.getPrototypeOf(ShadowRealm.prototype.evaluate), Function.prototype); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/returns-primitive-values.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-primitive-values.js similarity index 72% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/returns-primitive-values.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-primitive-values.js index a47844b93bf2..cdc06d87517d 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/returns-primitive-values.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-primitive-values.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate returns primitive values -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate returns primitive values +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); assert.sameValue(r.evaluate('1 + 1'), 2); assert.sameValue(r.evaluate('null'), null); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-proxy-callable-object.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-proxy-callable-object.js new file mode 100644 index 000000000000..434d2d9f8222 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-proxy-callable-object.js @@ -0,0 +1,28 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm.prototype.evaluate wrapped proxy callable object. +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +const proxyCallable = r.evaluate(` +function fn() { return 42; } +new Proxy(fn, {}); +`); + +assert.sameValue(typeof proxyCallable, 'function', 'wrapped proxy callable object is typeof function'); +assert.sameValue(proxyCallable(), 42, 'wrappedpfn() returns 42'); +assert.sameValue((new Proxy(proxyCallable, {}))(), 42, 'wrapped functions can be proxied'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-symbol-values.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-symbol-values.js new file mode 100644 index 000000000000..13999f1f56ef --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/returns-symbol-values.js @@ -0,0 +1,54 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm.prototype.evaluate returns symbol values +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); +const s = r.evaluate('Symbol("foobar")'); + +assert.sameValue(typeof s, 'symbol'); +assert.sameValue(s.constructor, Symbol, 'primitive does not expose other ShadowRealm constructor'); +assert.sameValue(Object.getPrototypeOf(s), Symbol.prototype); +assert.sameValue(Symbol.prototype.toString.call(s), 'Symbol(foobar)'); + +const shadowX = r.evaluate('Symbol.for("my symbol name")'); +const myX = Symbol.for('my symbol name') + +assert.sameValue( + shadowX, + myX, + 'The shadow realms observes the symbol global registry used in Symbol.for' +); + +assert.sameValue( + Symbol.keyFor(shadowX), + 'my symbol name', + 'Symbol.keyFor observes the string key name of a symbol originally registered in the shadow realm' +); + +assert.sameValue( + Symbol.keyFor(s), + undefined, + 'Symbol.keyFor cannot find a key for a regular symbol created in the shadow realm' +); + +const { get: description } = Object.getOwnPropertyDescriptor(Symbol.prototype, 'description'); + +assert.sameValue( + description.call(s), + 'foobar', + 'get description for the symbol created in the shadow realm' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/shell.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/shell.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/prototype/shell.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/shell.js diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-error-from-ctor-realm.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-error-from-ctor-realm.js new file mode 100644 index 000000000000..20df4a967d6c --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-error-from-ctor-realm.js @@ -0,0 +1,35 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm.prototype.evaluate throws a TypeError from ShadowRealm's creation realm. +features: [ShadowRealm, cross-realm, Reflect] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +var other = $262.createRealm().global; +var OtherTypeError = other.TypeError; +var OtherSyntaxError = other.SyntaxError; +var OtherShadowRealm = other.ShadowRealm; + +var realm = Reflect.construct(OtherShadowRealm, []); + +assert.throws(OtherTypeError, () => realm.evaluate('globalThis'), 'throws a TypeError if return value can not be wrapped'); +assert.throws(OtherTypeError, () => realm.evaluate('throw new Error()'), 'throws a TypeError if completion is abrupt'); + +assert.throws(OtherTypeError, () => realm.evaluate(1), 'throws a TypeError if sourceText is not a string'); +assert.throws(OtherSyntaxError, () => realm.evaluate('...'), 'throws a SyntaxError if the sourceText is not valid'); + +const bogus = {}; +assert.throws(OtherTypeError, function() { + realm.evaluate.call(bogus, 'This is invalid code and should not be evaluated'); +}, 'throws a TypeError if this is not a ShadowRealm object'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-syntaxerror-on-bad-syntax.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-syntaxerror-on-bad-syntax.js new file mode 100644 index 000000000000..f79d126f560c --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-syntaxerror-on-bad-syntax.js @@ -0,0 +1,33 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm.prototype.evaluate throws a SyntaxError if the syntax can't be parsed +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.throws(SyntaxError, () => r.evaluate('...'), 'SyntaxError exposed to Parent'); +assert.throws(SyntaxError, () => r.evaluate(` + "use strict"; + throw "do not evaluate"; + function lol(){ + arguments = 1; + } +`), 'Strict mode only SyntaxError, setting value to a fn arguments'); +assert.throws(SyntaxError, () => r.evaluate(` + "use strict"; + throw "do not evaluate"; + var public = 1; +`), 'Strict mode only SyntaxError, var public'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/throws-typeerror-if-evaluation-resolves-to-non-primitive.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-if-evaluation-resolves-to-non-primitive.js similarity index 66% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/throws-typeerror-if-evaluation-resolves-to-non-primitive.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-if-evaluation-resolves-to-non-primitive.js index 1e6651fec96d..4170e08223f3 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/throws-typeerror-if-evaluation-resolves-to-non-primitive.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-if-evaluation-resolves-to-non-primitive.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate throws a TypeError if evaluate resolves to non-primitive values -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate throws a TypeError if evaluate resolves to non-primitive values +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); assert.throws(TypeError, () => r.evaluate('globalThis'), 'globalThis'); assert.throws(TypeError, () => r.evaluate('[]'), 'array literal'); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js new file mode 100644 index 000000000000..d481d0166f21 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js @@ -0,0 +1,73 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrappedfunctioncreate +description: > + WrappedFunctionCreate throws a TypeError if the accessing target's property may throw. + +info: | + WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) + ... + 7. Let result be CopyNameAndLength(wrapped, Target). + ... + + CopyNameAndLength ( F: a function object, Target: a function object, optional prefix: a String, optional argCount: a Number, ) + ... + 3. Let targetHasLength be ? HasOwnProperty(Target, "length"). + 4. If targetHasLength is true, then + a. Let targetLen be ? Get(Target, "length"). + ... + 6. Let targetName be ? Get(Target, "name"). + +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.throws(TypeError, () => r.evaluate(` +const revocable = Proxy.revocable(() => {}, {}); +revocable.revoke(); + +revocable.proxy; +`), 'TypeError on wrapping a revoked callable proxy'); + +assert.throws(TypeError, () => r.evaluate(` +const fn = () => {}; +Object.defineProperty(fn, 'name', { + get() { + throw new Error(); + }, +}); + +fn; +`), 'TypeError on wrapping a fn with throwing name accessor'); + +assert.throws(TypeError, () => r.evaluate(` +const fn = () => {}; +Object.defineProperty(fn, 'length', { + get() { + throw new Error(); + }, +}); + +fn; +`), 'TypeError on wrapping a fn with throwing length accessor'); + +assert.throws(TypeError, () => r.evaluate(` +const proxy = new Proxy(() => {}, { + getOwnPropertyDescriptor(target, key) { + throw new Error(); + }, +}); + +proxy; +`), 'TypeError on wrapping a callable proxy with throwing getOwnPropertyDescriptor trap'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/throws-when-argument-is-not-a-string.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-when-argument-is-not-a-string.js similarity index 66% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/throws-when-argument-is-not-a-string.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-when-argument-is-not-a-string.js index b9f236801f99..17be0a1874cc 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/throws-when-argument-is-not-a-string.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/throws-when-argument-is-not-a-string.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate throws when argument is not a string. -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate throws when argument is not a string. +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); assert.throws(TypeError, () => r.evaluate(['1+1'])); assert.throws(TypeError, () => r.evaluate({ [Symbol.toPrimitive]() { return '1+1'; }})); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/validates-realm-object.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/validates-realm-object.js new file mode 100644 index 000000000000..6141c284876e --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/validates-realm-object.js @@ -0,0 +1,24 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm.prototype.evaluate validates realm object. +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); +const bogus = {}; + +assert.throws(TypeError, function() { + r.evaluate.call(bogus, 'This is invalid code and should not be evaluated'); +}, 'throws a TypeError if this is not a ShadowRealm object'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm-extended.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm-extended.js similarity index 70% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm-extended.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm-extended.js index afe564ab4f94..082562e32f8d 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm-extended.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm-extended.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate wrapped function arguments are wrapped into the inner realm, extended. -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate wrapped function arguments are wrapped into the inner realm, extended. +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); const blueFn = (x, y) => x + y; const redWrappedFn = r.evaluate(` diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm.js similarity index 53% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm.js index 6e4250912075..69a0028de9d9 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-arguments-are-wrapped-into-the-inner-realm.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate wrapped function arguments are wrapped into the inner realm -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate wrapped function arguments are wrapped into the inner realm +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); const blueFn = (x, y) => x + y; const redWrappedFn = r.evaluate(` diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-from-return-values-share-no-identity.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-from-return-values-share-no-identity.js similarity index 88% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-from-return-values-share-no-identity.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-from-return-values-share-no-identity.js index 95b5aa2f7a4e..544f5efa311d 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-from-return-values-share-no-identity.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-from-return-values-share-no-identity.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate wrapped function from return values share no identity. -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate wrapped function from return values share no identity. +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); r.evaluate(` function fn() { return 42; } diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-multiple-different-realms-nested.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-multiple-different-realms-nested.js new file mode 100644 index 000000000000..c57b99c9976b --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-multiple-different-realms-nested.js @@ -0,0 +1,58 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm can wrap a function to multiple nested realms. +features: [ShadowRealm] +---*/ +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +globalThis.count = 0; +const realm1 = new ShadowRealm(); + +const r1wrapped = realm1.evaluate(` + globalThis.count = 0; + () => globalThis.count += 1; +`); + +const realm2Evaluate = realm1.evaluate(` + const realm2 = new ShadowRealm(); + + (str) => realm2.evaluate(str); +`); + +const r2wrapper = realm2Evaluate(` + globalThis.wrapped = undefined; + globalThis.count = 0; // Bait + (fn) => globalThis.wrapped = fn; +`); + +const rewrapped = r2wrapper(r1wrapped); + +assert.notSameValue(rewrapped, r1wrapped, 'rewrapped !== r1wrapped'); + +const r2wrapped = realm2Evaluate('globalThis.wrapped'); + +assert.notSameValue(r2wrapped, r1wrapped, 'r2wrapped !== r1wrapped'); +assert.notSameValue(r2wrapped, rewrapped, 'r2wrapped !== rewrapped'); + +assert.sameValue(realm1.evaluate('globalThis.count'), 0, `getting wrapped function won't trigger a call`); + +assert.sameValue(r2wrapped(), 1, 'call from r2 wrapped (r2wrapped) cycles back to r1'); + +assert.sameValue(realm1.evaluate('globalThis.count'), 1, 'effects produced in a third realm, #1'); + +assert.sameValue(rewrapped(), 2, 'call from r2 wrapped (rewrapped) cycles back to r1'); + +assert.sameValue(realm1.evaluate('globalThis.count'), 2, 'effects produced in a third realm, #2'); + +assert.sameValue(realm2Evaluate('globalThis.count'), 0, 'no side effects produced in the wrong realm (realm2)'); +assert.sameValue(globalThis.count, 0, 'no side effects produced in the wrong realm (main realm)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-multiple-different-realms.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-multiple-different-realms.js new file mode 100644 index 000000000000..c0b08349a122 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-multiple-different-realms.js @@ -0,0 +1,51 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + ShadowRealm can wrap a function to multiple realms. +features: [ShadowRealm] +---*/ + +const realm1 = new ShadowRealm(); +const realm2 = new ShadowRealm(); + +globalThis.count = 0; + +assert.notSameValue(realm1, realm2); + +const r1wrapped = realm1.evaluate(` + globalThis.count = 0; + () => globalThis.count += 1; +`); + +const r2wrapper = realm2.evaluate(` + globalThis.wrapped = undefined; + globalThis.count = 0; // Bait + (fn) => globalThis.wrapped = fn; +`); + +const rewrapped = r2wrapper(r1wrapped); + +assert.notSameValue(rewrapped, r1wrapped, 'rewrapped !== r1wrapped'); + +const r2wrapped = realm2.evaluate('globalThis.wrapped'); + +assert.notSameValue(r2wrapped, r1wrapped, 'r2wrapped !== r1wrapped'); +assert.notSameValue(r2wrapped, rewrapped, 'r2wrapped !== rewrapped'); + +assert.sameValue(realm1.evaluate('globalThis.count'), 0, `getting wrapped function won't trigger a call`); + +assert.sameValue(r2wrapped(), 1, 'call from r2 wrapped (r2wrapped) cycles back to r1'); + +assert.sameValue(realm1.evaluate('globalThis.count'), 1, 'effects produced in a third realm, #1'); + +assert.sameValue(rewrapped(), 2, 'call from r2 wrapped (rewrapped) cycles back to r1'); + +assert.sameValue(realm1.evaluate('globalThis.count'), 2, 'effects produced in a third realm, #2'); + +assert.sameValue(realm2.evaluate('globalThis.count'), 0, 'no side effects produced in the wrong realm (realm2)'); +assert.sameValue(globalThis.count, 0, 'no side effects produced in the wrong realm (main realm)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-observing-their-scopes.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-observing-their-scopes.js similarity index 54% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-observing-their-scopes.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-observing-their-scopes.js index 689db7784a94..a3a4ed43f37a 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-function-observing-their-scopes.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-observing-their-scopes.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate wrapped function observing their scopes -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate wrapped function observing their scopes +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); let myValue; function blueFn(x) { @@ -22,7 +22,7 @@ function blueFn(x) { return myValue; } -// cb is a new function in the red Realm that chains the call to the blueFn +// cb is a new function in the red ShadowRealm that chains the call to the blueFn const redFunction = r.evaluate(` var myValue = 'red'; 0, function(cb) { diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-proto-from-caller-realm.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-proto-from-caller-realm.js new file mode 100644 index 000000000000..aa138ef99fb3 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-proto-from-caller-realm.js @@ -0,0 +1,56 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + WrappedFunctionCreate should create a function derived from the caller realm +info: | + ShadowRealm.prototype.evaluate ( sourceText ) + ... + 4. Let callerRealm be the current Realm Record. + 5. Let evalRealm be O.[[ShadowRealm]]. + 6. Return ? PerformRealmEval(sourceText, callerRealm, evalRealm). + + PerformRealmEval ( sourceText, callerRealm, evalRealm ) + ... + 25. Return ? GetWrappedValue(callerRealm, result). + + GetWrappedValue ( callerRealm, value ) + ... + 2.b. Return ? WrappedFunctionCreate(callerRealm, value). + + WrappedFunctionCreate ( callerRealm, targetFunction ) + ... + 5. Set obj.[[Prototype]] to callerRealm.[[Intrinsics]].[[%Function.prototype%]]. +features: [ShadowRealm, cross-realm, Reflect] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +var other = $262.createRealm().global; +var OtherShadowRealm = other.ShadowRealm; +var OtherFunctionPrototype = other.Function.prototype; + +var yetAnother = $262.createRealm().global; +var YetAnotherShadowRealm = yetAnother.ShadowRealm; +var YetAnotherFunctionPrototype = yetAnother.Function.prototype; + +var realm = Reflect.construct(OtherShadowRealm, []); + +var checkArgWrapperFn = realm.evaluate('(x) => { return Object.getPrototypeOf(x) === Function.prototype }') +assert.sameValue(checkArgWrapperFn(() => {}), true, 'callable arguments passed into WrappedFunction should be wrapped in target realm'); + +var fn = realm.evaluate('() => { return () => { return 1 } }'); +assert.sameValue(Object.getPrototypeOf(fn), OtherFunctionPrototype, 'WrappedFunction should be derived from the caller realm'); +assert.sameValue(Object.getPrototypeOf(fn()), OtherFunctionPrototype, 'callable results from WrappedFunction should be wrapped in caller realm'); + +var fn = YetAnotherShadowRealm.prototype.evaluate.call(realm, '() => { return () => { return 1 } }'); +assert.sameValue(Object.getPrototypeOf(fn), YetAnotherFunctionPrototype, 'WrappedFunction should be derived from the caller realm'); +assert.sameValue(Object.getPrototypeOf(fn()), YetAnotherFunctionPrototype, 'callable results from WrappedFunction should be wrapped in caller realm'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-proxied-observes-boundary.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-proxied-observes-boundary.js new file mode 100644 index 000000000000..e6b57b420281 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-proxied-observes-boundary.js @@ -0,0 +1,44 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.evaluate +description: > + Proxying a wrapped function and invoking it still performs boundary checks +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +const wrapped = r.evaluate(`() => { return 1; };`); + +const secretObj = {x: 2}; + +let received; + +const proxiedWrapped = new Proxy(wrapped, { + apply(target, _, args) { + assert.sameValue(target, wrapped); + received = args; + + // Object can't be sent to the other Realm + return target({x: 1}); + } +}); + +assert.throws( + TypeError, + () => proxiedWrapped(secretObj), + 'Proxying a wrapped function and invoking it still performs boundary checks' +); + +assert.sameValue(received[0], secretObj, 'proxy still calls the handler trap'); +assert.sameValue(received.length, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-from-caller-realm.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-from-caller-realm.js new file mode 100644 index 000000000000..60bbd0c6486e --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-from-caller-realm.js @@ -0,0 +1,42 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrapped-function-exotic-objects-call-thisargument-argumentslist +description: > + WrappedFunction throws a TypeError from its creation realm. +features: [ShadowRealm, cross-realm, Reflect] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +var other = $262.createRealm().global; +var OtherTypeError = other.TypeError; +var OtherShadowRealm = other.ShadowRealm; + +var yetAnother = $262.createRealm().global; +var YetAnotherTypeError = yetAnother.TypeError; +var YetAnotherShadowRealm = yetAnother.ShadowRealm; + +var realm = Reflect.construct(OtherShadowRealm, []); + +{ + let wrappedFunction = realm.evaluate('() => {}'); + let wrappedFunction2 = realm.evaluate('() => globalThis'); + + assert.throws(OtherTypeError, () => wrappedFunction(1, globalThis), 'throws TypeError if arguments are not wrappable'); + assert.throws(OtherTypeError, () => wrappedFunction2(), 'throws TypeError if return value is not wrappable'); +} + +{ + let wrappedFunction = YetAnotherShadowRealm.prototype.evaluate.call(realm, '() => {}'); + let wrappedFunction2 = YetAnotherShadowRealm.prototype.evaluate.call(realm, '() => globalThis'); + assert.throws(YetAnotherTypeError, () => wrappedFunction(1, globalThis), 'throws TypeError if arguments are not wrappable'); + assert.throws(YetAnotherTypeError, () => wrappedFunction2(), 'throws TypeError if return value is not wrappable'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-exceptional-exit.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-exceptional-exit.js new file mode 100644 index 000000000000..3df6d7301327 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-exceptional-exit.js @@ -0,0 +1,42 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Igalia SL. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrapped-function-exotic-objects-call-thisargument-argumentslist +description: > + WrappedFunction throws a TypeError if the wrapped function throws. +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.sameValue( + r.evaluate(`(f) => { + try { + f(); + } catch (e) { + if (e instanceof TypeError) { + return 'ok'; + } else { + return e.toString(); + } + } + return 'normal exit'; + }`)(() => { throw Error("ahh"); }), + 'ok', + 'WrappedFunction throws TypeError (from the calling realm) if the wrapped callable throws any exception' +); + +assert.throws( + TypeError, + () => r.evaluate('() => { throw new Error("ahh"); }')(), + 'WrappedFunction throws TypeError if the wrapped callable throws any exception' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-non-primitive-arguments.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-non-primitive-arguments.js new file mode 100644 index 000000000000..a484c43cfda4 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-non-primitive-arguments.js @@ -0,0 +1,36 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrapped-function-exotic-objects-call-thisargument-argumentslist +description: > + WrappedFunction throws a TypeError if any of the arguments are non-primitive +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); +const wrappedFunction = r.evaluate('() => {}'); + +assert.sameValue( + typeof wrappedFunction, + 'function', + 'This test must fail if wrappedFunction is not a function' +); + +assert.throws(TypeError, () => wrappedFunction(1, globalThis), 'globalThis'); +assert.throws(TypeError, () => wrappedFunction(1, []), 'array literal'); +assert.throws(TypeError, () => wrappedFunction(1, { + [Symbol.toPrimitive]() { return 'string'; }, + toString() { return 'str'; }, + valueOf() { return 1; } +}), 'object literal with immediate primitive coercion methods'); +assert.throws(TypeError, () => wrappedFunction(1, Object.create(null)), 'ordinary object with null __proto__'); +assert.throws(TypeError, () => wrappedFunction(1, new Proxy({}, { apply() {} })), 'non-callable proxy'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-non-primitive-returns.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-non-primitive-returns.js new file mode 100644 index 000000000000..8060f0ee0899 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-function-throws-typeerror-on-non-primitive-returns.js @@ -0,0 +1,31 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrapped-function-exotic-objects-call-thisargument-argumentslist +description: > + WrappedFunction throws a TypeError if it returns non-primitive values +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.throws(TypeError, r.evaluate('() => globalThis'), 'globalThis'); +assert.throws(TypeError, r.evaluate('() => []'), 'array literal'); +assert.throws(TypeError, r.evaluate(` + () => ({ + [Symbol.toPrimitive]() { return 'string'; }, + toString() { return 'str'; }, + valueOf() { return 1; } + }); +`), 'object literal with immediate primitive coercion methods'); +assert.throws(TypeError, r.evaluate('() => Object.create(null)'), 'ordinary object with null __proto__'); +assert.throws(TypeError, r.evaluate('() => new Proxy({}, { apply() {} })'), 'non-callable proxy'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-accepts-callable-objects.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-accepts-callable-objects.js similarity index 64% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-accepts-callable-objects.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-accepts-callable-objects.js index 11dbb6a5d696..a5b0a0a8b2b7 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-accepts-callable-objects.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-accepts-callable-objects.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate accepts callable objects -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate accepts callable objects +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); assert.sameValue(typeof r.evaluate('function fn() {} fn'), 'function', 'value from a fn declaration'); assert.sameValue(typeof r.evaluate('(function() {})'), 'function', 'function expression'); @@ -22,5 +22,6 @@ assert.sameValue(typeof r.evaluate('(async function() {})'), 'function', 'async assert.sameValue(typeof r.evaluate('(function*() {})'), 'function', 'generator expression'); assert.sameValue(typeof r.evaluate('(async function*() {})'), 'function', 'async generator expression'); assert.sameValue(typeof r.evaluate('() => {}'), 'function', 'arrow function'); +assert.sameValue(typeof r.evaluate('new Proxy(() => {}, { apply() {} })'), 'function', 'callable proxy'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-can-resolve-callable-returns.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-can-resolve-callable-returns.js similarity index 59% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-can-resolve-callable-returns.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-can-resolve-callable-returns.js index f0b917999ebc..82142d15c93f 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-can-resolve-callable-returns.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-can-resolve-callable-returns.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate wrapped functions can resolve callable returns. -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate wrapped functions can resolve callable returns. +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); const wrapped = r.evaluate('x => y => x * y'); const nestedWrapped = wrapped(2); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-new-wrapping-on-each-evaluation.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-new-wrapping-on-each-evaluation.js similarity index 55% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-new-wrapping-on-each-evaluation.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-new-wrapping-on-each-evaluation.js index ff142f4b67df..b618e9cc62e0 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-new-wrapping-on-each-evaluation.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-new-wrapping-on-each-evaluation.js @@ -1,25 +1,25 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate wrapped functions produce new wrapping on each evaluation. -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate wrapped functions produce new wrapping on each evaluation. +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); r.evaluate(` -0, function fn() { +function fn() { return 42; -}; +} `); const wrapped = r.evaluate('fn'); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-share-no-properties-extended.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-share-no-properties-extended.js similarity index 86% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-share-no-properties-extended.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-share-no-properties-extended.js index c889fa55ae25..ab9b700d9c52 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-share-no-properties-extended.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-share-no-properties-extended.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate wrapped functions share no properties, extended -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate wrapped functions share no properties, extended +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); r.evaluate(` function fn() { return 42; } diff --git a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-share-no-properties.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-share-no-properties.js similarity index 55% rename from js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-share-no-properties.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-share-no-properties.js index ffc85eb6d49e..4255da74d87f 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/evaluate/wrapped-functions-share-no-properties.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/evaluate/wrapped-functions-share-no-properties.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.evaluate +esid: sec-shadowrealm.prototype.evaluate description: > - Realm.prototype.evaluate wrapped functions share no properties -features: [callable-boundary-realms] + ShadowRealm.prototype.evaluate wrapped functions share no properties +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.evaluate, + typeof ShadowRealm.prototype.evaluate, 'function', - 'This test must fail if Realm.prototype.evaluate is not a function' + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); const wrapped = r.evaluate(` function fn() { diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/eraYear/browser.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/Calendar/prototype/eraYear/browser.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/browser.js diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/descriptor.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/descriptor.js similarity index 50% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/descriptor.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/descriptor.js index 13318d7099b3..1621128aa750 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/descriptor.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/descriptor.js @@ -1,15 +1,15 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.importvalue +esid: sec-shadowrealm.prototype.importvalue description: > - Realm.prototype.importValue is an ECMAScript Standard built-in object function. + ShadowRealm.prototype.importValue is an ECMAScript Standard built-in object function. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(Realm.prototype, "importValue", { +verifyProperty(ShadowRealm.prototype, "importValue", { enumerable: false, writable: true, configurable: true, diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/exportName-tostring.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/exportName-tostring.js similarity index 55% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/exportName-tostring.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/exportName-tostring.js index 022112b9dbc8..8b6aab028dbf 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/exportName-tostring.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/exportName-tostring.js @@ -1,20 +1,20 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.importvalue +esid: sec-shadowrealm.prototype.importvalue description: > - Realm.prototype.importValue coerces exportName to string. -features: [callable-boundary-realms] + ShadowRealm.prototype.importValue coerces exportName to string. +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.importValue, + typeof ShadowRealm.prototype.importValue, 'function', - 'This test must fail if Realm.prototype.importValue is not a function' + 'This test must fail if ShadowRealm.prototype.importValue is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); let count = 0; const exportName = { diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value.js new file mode 100644 index 000000000000..02dcb18392a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value.js @@ -0,0 +1,24 @@ +// |reftest| skip module async -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.importvalue +description: > + ShadowRealm.prototype.importValue can import a value. +flags: [async, module] +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.importValue, + 'function', + 'This test must fail if ShadowRealm.prototype.importValue is not a function' +); + +const r = new ShadowRealm(); + +r.importValue('./import-value_FIXTURE.js', 'x').then(x => { + + assert.sameValue(x, 1); + +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/import-value_FIXTURE.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_FIXTURE.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/import-value_FIXTURE.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_FIXTURE.js diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_syntax_error_FIXTURE.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_syntax_error_FIXTURE.js new file mode 100644 index 000000000000..7e0b9c2e843d --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_syntax_error_FIXTURE.js @@ -0,0 +1,5 @@ +// |reftest| skip -- not a test file +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +This is an invalid JavaScript Module file. diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_throws_FIXTURE.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_throws_FIXTURE.js new file mode 100644 index 000000000000..152521f5aed1 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/import-value_throws_FIXTURE.js @@ -0,0 +1,5 @@ +// |reftest| skip -- not a test file +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +throw new Error('foobar'); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/length.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/length.js similarity index 77% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/length.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/length.js index 12499f55a4dc..7f3a0e78eab5 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/length.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/length.js @@ -1,10 +1,10 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.importvalue +esid: sec-shadowrealm.prototype.importvalue description: > - The value of Realm.prototype.importValue.length is 2 + The value of ShadowRealm.prototype.importValue.length is 2 info: | Every built-in function object, including constructors, has a "length" property whose value is a non-negative integral Number. Unless otherwise specified, this value @@ -16,10 +16,10 @@ info: | the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(Realm.prototype.importValue, "length", { +verifyProperty(ShadowRealm.prototype.importValue, "length", { value: 2, enumerable: false, writable: false, diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/name.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/name.js similarity index 58% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/name.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/name.js index 55fcd2028371..da16a927170e 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/name.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/name.js @@ -1,26 +1,26 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.importValue +esid: sec-shadowrealm.prototype.importValue description: > - The value of Realm.prototype.importValue.name is 'importValue' + The value of ShadowRealm.prototype.importValue.name is 'importValue' info: | - Realm.prototype.importValue + ShadowRealm.prototype.importValue - Every built-in function object, including constructors, has a "name" property - whose value is a String. Unless otherwise specified, this value is the name - that is given to the function in this specification. + Every built-in function object, including constructors, has a "name" property + whose value is a String. Unless otherwise specified, this value is the name + that is given to the function in this specification. - Unless otherwise specified, the "name" property of a built-in function - object has the attributes + Unless otherwise specified, the "name" property of a built-in function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -verifyProperty(Realm.prototype.importValue, "name", { +verifyProperty(ShadowRealm.prototype.importValue, "name", { value: "importValue", enumerable: false, writable: false, diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/not-constructor.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/not-constructor.js new file mode 100644 index 000000000000..bd323d5b23e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/not-constructor.js @@ -0,0 +1,34 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.importvalue +description: > + ShadowRealm.prototype.importValue is not a constructor. +includes: [isConstructor.js] +features: [ShadowRealm, Reflect.construct] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.importValue, + 'function', + 'This test must fail if ShadowRealm.prototype.importValue is not a function' +); + +assert.sameValue( + isConstructor(ShadowRealm.prototype.importValue), + false, + 'isConstructor(ShadowRealm.prototype.importValue) must return false' +); + +assert.throws(TypeError, () => { + new ShadowRealm.prototype.importValue("", "name"); +}, '`new ShadowRealm.prototype.importValue("")` throws TypeError'); + +const r = new ShadowRealm(); + +assert.throws(TypeError, () => { + new r.importValue("./import-value_FIXTURE.js", "x"); +}, '`new r.importValue("...")` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/proto.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/proto.js similarity index 58% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/proto.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/proto.js index 2277bb1fa3b6..0b25a7b4e4bd 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/proto.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/proto.js @@ -1,18 +1,18 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-realm.prototype.importvalue +esid: sec-shadowrealm.prototype.importvalue description: > - The [[Prototype]] of Realm.prototype.importValue is AsyncFunction.Prototype. + The [[Prototype]] of ShadowRealm.prototype.importValue is AsyncFunction.Prototype. info: | Unless otherwise specified every built-in function and every built-in constructor has the Function prototype object, which is the initial value of the expression Function.prototype, as the value of its [[Prototype]] internal slot. -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -assert.sameValue(Object.getPrototypeOf(Realm.prototype.importValue), Function.prototype); +assert.sameValue(Object.getPrototypeOf(ShadowRealm.prototype.importValue), Function.prototype); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/era/shell.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/shell.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/Calendar/prototype/era/shell.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/shell.js diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/specifier-tostring.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/specifier-tostring.js new file mode 100644 index 000000000000..a603c4054dcc --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/specifier-tostring.js @@ -0,0 +1,76 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.importvalue +description: > + ShadowRealm.prototype.importValue coerces specifier to string. +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.importValue, + 'function', + 'This test must fail if ShadowRealm.prototype.importValue is not a function' +); + +const r = new ShadowRealm(); +let count = 0; + +const specifier = Object.create(null); + +// A - valueOF + +specifier.valueOf = function() { + count += 1; + throw new Test262Error(); +}; + +assert.throws(Test262Error, () => { + r.importValue(specifier); +}, 'ToString(specifier) returns abrupt from valueOf'); + +assert.sameValue(count, 1, 'ToString calls the valueOf method'); + + +// B - toString + +count = 0; + +specifier.valueOf = function() { + count += 1000; + throw new Error('valueOf is not reached if toString is present'); +}; + +specifier.toString = function() { + count += 1; + throw new Test262Error(); +}; + +assert.throws(Test262Error, () => { + r.importValue(specifier); +}, 'ToString(specifier) returns abrupt from toString'); + +assert.sameValue(count, 1, 'ToString calls the toString method'); + +// C - @@toPrimitive + +count = 0; + +specifier[Symbol.toPrimitive] = function() { + count += 1; + throw new Test262Error(); +}; + +specifier.toString = function() { + count += 1000; + throw new Error('toString is not reached if @@toPrimitive is present'); +}; + +assert.throws(Test262Error, () => { + r.importValue(specifier); +}, 'ToString(specifier) returns abrupt from @@toPrimitive'); + +assert.sameValue(count, 1, 'ToString calls the @@toPrimitive method'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/importValue/throws-if-import-value-does-not-exist.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-if-import-value-does-not-exist.js similarity index 71% rename from js/src/tests/test262/built-ins/Realm/prototype/importValue/throws-if-import-value-does-not-exist.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-if-import-value-does-not-exist.js index e754d4685f60..3e50271b8f74 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/importValue/throws-if-import-value-does-not-exist.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-if-import-value-does-not-exist.js @@ -1,18 +1,18 @@ -// |reftest| skip module async -- callable-boundary-realms is not supported +// |reftest| skip module async -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-realmimportvalue description: > - Realm.prototype.importValue rejects when export name does not exist + ShadowRealm.prototype.importValue rejects when export name does not exist info: | RealmImportValue ( specifierString, exportNameString, callerRealm, evalRealm, evalContext ) Assert: Type(specifierString) is String. Assert: Type(exportNameString) is String. - Assert: callerRealm is a Realm Record. - Assert: evalRealm is a Realm Record. - Assert: evalContext is an execution context associated to a Realm instance's [[ExecutionContext]]. + Assert: callerRealm is a ShadowRealm Record. + Assert: evalRealm is a ShadowRealm Record. + Assert: evalContext is an execution context associated to a ShadowRealm instance's [[ExecutionContext]]. Let innerCapability be ! NewPromiseCapability(%Promise%). Let runningContext be the running execution context. If runningContext is not already suspended, suspend runningContext. @@ -36,19 +36,24 @@ info: | ... flags: [async, module] -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ assert.sameValue( - typeof Realm.prototype.importValue, + typeof ShadowRealm.prototype.importValue, 'function', - 'This test must fail if Realm.prototype.importValue is not a function' + 'This test must fail if ShadowRealm.prototype.importValue is not a function' ); -const r = new Realm(); +const r = new ShadowRealm(); r.importValue('./import-value_FIXTURE.js', 'y') .then( - () => $DONE('Expected rejection'), - () => $DONE() - ); + () => { + throw new Test262Error("Expected rejection"); + }, + err => { + assert.sameValue(Object.getPrototypeOf(err), TypeError.prototype, 'should be rejected with TypeError'); + } + ) + .then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-syntax-error.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-syntax-error.js new file mode 100644 index 000000000000..8352596679c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-syntax-error.js @@ -0,0 +1,35 @@ +// |reftest| skip module async -- ShadowRealm is not supported +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-realmimportvalue +description: > + ShadowRealm.prototype.importValue rejects with TypeError when the imported script unable to be parsed. +info: | + RealmImportValue ( specifierString, exportNameString, callerRealm, evalRealm, evalContext ) + + ... + 17. Return ! PerformPromiseThen(innerCapability.[[Promise]], onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability). + +flags: [async, module] +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.importValue, + 'function', + 'This test must fail if ShadowRealm.prototype.importValue is not a function' +); + +const r = new ShadowRealm(); + +r.importValue('./import-value_syntax_error_FIXTURE.js', 'y') + .then( + () => { + throw new Test262Error("unreachable"); + }, + err => { + assert.sameValue(Object.getPrototypeOf(err), TypeError.prototype, 'should be rejected with TypeError'); + } + ) + .then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-throws.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-throws.js new file mode 100644 index 000000000000..f2d5be735d1f --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-throws.js @@ -0,0 +1,35 @@ +// |reftest| skip module async -- ShadowRealm is not supported +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-realmimportvalue +description: > + ShadowRealm.prototype.importValue rejects with TypeError when the imported script throws. +info: | + RealmImportValue ( specifierString, exportNameString, callerRealm, evalRealm, evalContext ) + + ... + 17. Return ! PerformPromiseThen(innerCapability.[[Promise]], onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability). + +flags: [async, module] +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.importValue, + 'function', + 'This test must fail if ShadowRealm.prototype.importValue is not a function' +); + +const r = new ShadowRealm(); + +r.importValue('./import-value_throws_FIXTURE.js', 'y') + .then( + () => { + throw new Test262Error("unreachable"); + }, + err => { + assert.sameValue(Object.getPrototypeOf(err), TypeError.prototype, 'should be rejected with TypeError'); + } + ) + .then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/validates-realm-object.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/validates-realm-object.js new file mode 100644 index 000000000000..0597b50330e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/importValue/validates-realm-object.js @@ -0,0 +1,24 @@ +// |reftest| skip -- ShadowRealm is not supported +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-shadowrealm.prototype.importvalue +description: > + ShadowRealm.prototype.importValue validates realm object. +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.importValue, + 'function', + 'This test must fail if ShadowRealm.prototype.importValue is not a function' +); + +const r = new ShadowRealm(); +const bogus = {}; + +assert.throws(TypeError, function() { + r.importValue.call(bogus, "specifier", "name"); +}, 'throws a TypeError if this is not a ShadowRealm object'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Realm/prototype/proto.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/proto.js similarity index 67% rename from js/src/tests/test262/built-ins/Realm/prototype/proto.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/proto.js index df4ad22fb5c3..6f8ab32b2cbf 100644 --- a/js/src/tests/test262/built-ins/Realm/prototype/proto.js +++ b/js/src/tests/test262/built-ins/ShadowRealm/prototype/proto.js @@ -1,18 +1,18 @@ -// |reftest| skip -- callable-boundary-realms is not supported +// |reftest| skip -- ShadowRealm is not supported // Copyright (C) 2021 Rick Waldron. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-properties-of-the-realm-prototype-object description: > - The [[Prototype]] of Realm.prototype is Object.Prototype. + The [[Prototype]] of ShadowRealm.prototype is Object.Prototype. info: | Unless otherwise specified every built-in prototype object has the Object prototype object, which is the initial value of the expression Object.prototype, as the value of its [[Prototype]] internal slot, except the Object prototype object itself. -features: [callable-boundary-realms] +features: [ShadowRealm] ---*/ -assert.sameValue(Object.getPrototypeOf(Realm.prototype), Object.prototype); +assert.sameValue(Object.getPrototypeOf(ShadowRealm.prototype), Object.prototype); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/eraYear/shell.js b/js/src/tests/test262/built-ins/ShadowRealm/prototype/shell.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/Calendar/prototype/eraYear/shell.js rename to js/src/tests/test262/built-ins/ShadowRealm/prototype/shell.js diff --git a/js/src/tests/test262/built-ins/Realm/shell.js b/js/src/tests/test262/built-ins/ShadowRealm/shell.js similarity index 100% rename from js/src/tests/test262/built-ins/Realm/shell.js rename to js/src/tests/test262/built-ins/ShadowRealm/shell.js diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-diminuitive.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-diminuitive.js index 4c089ce5e9f3..0d7a8615fec8 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-diminuitive.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-diminuitive.js @@ -15,7 +15,7 @@ info: | 4. If requestedMaxByteLength is empty, then a. [...] 5. If byteLength > requestedMaxByteLength, throw a RangeError exception. -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert.throws(RangeError, function() { diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-excessive.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-excessive.js index 14d12799dee9..b036374a626f 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-excessive.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-excessive.js @@ -20,7 +20,7 @@ info: | 2. Let maxByteLength be ? Get(options, "maxByteLength"). 3. If maxByteLength is undefined, return empty. 4. Return ? ToIndex(maxByteLength). -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert.throws(RangeError, function() { diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-negative.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-negative.js index 0fd428164c68..17440e112164 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-negative.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-negative.js @@ -18,7 +18,7 @@ info: | 2. Let maxByteLength be ? Get(options, "maxByteLength"). 3. If maxByteLength is undefined, return empty. 4. Return ? ToIndex(maxByteLength). -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert.throws(RangeError, function() { diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-object.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-object.js index 6282bfc31d2e..4a427cf33c9c 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-object.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-object.js @@ -20,7 +20,7 @@ info: | 2. Let maxByteLength be ? Get(options, "maxByteLength"). 3. If maxByteLength is undefined, return empty. 4. Return ? ToIndex(maxByteLength). -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var log = []; diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-poisoned.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-poisoned.js index 8aa84a655d4c..5d79ea780580 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-poisoned.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-poisoned.js @@ -16,7 +16,7 @@ info: | 1. If Type(options) is not Object, return empty. 2. Let maxByteLength be ? Get(options, "maxByteLength"). -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var options = { diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-undefined.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-undefined.js index 2fdfd96cc32c..9dc03c8c9f6c 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-undefined.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-maxbytelength-undefined.js @@ -18,7 +18,7 @@ info: | 1. If Type(options) is not Object, return empty. 2. Let maxByteLength be ? Get(options, "maxByteLength"). 3. If maxByteLength is undefined, return empty. -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert.sameValue(new SharedArrayBuffer(0, {}).growable, false); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-non-object.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-non-object.js index 6ba06030a904..22151ed9ce40 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/options-non-object.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/options-non-object.js @@ -16,7 +16,7 @@ info: | 1.1.5 GetArrayBufferMaxByteLengthOption ( options ) 1. If Type(options) is not Object, return empty. -features: [resizable-arraybuffer] +features: [BigInt, SharedArrayBuffer, Symbol, resizable-arraybuffer] ---*/ assert.sameValue(new SharedArrayBuffer(0, null).growable, false, 'null'); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype-from-newtarget.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype-from-newtarget.js index b6c7ac55e87d..dc84cfbf1cd5 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype-from-newtarget.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype-from-newtarget.js @@ -19,7 +19,7 @@ info: | 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%SharedArrayBufferPrototype%", «[[ArrayBufferData]], [[ArrayBufferByteLength]]» ). ... -features: [SharedArrayBuffer, Reflect.construct] +features: [Reflect, Reflect.construct, SharedArrayBuffer] ---*/ var arrayBuffer = Reflect.construct(SharedArrayBuffer, [8], Object); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/descriptor.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/descriptor.js index 7f0e75545a1b..b7d3f5ac726b 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/descriptor.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/descriptor.js @@ -13,7 +13,7 @@ info: | Annex B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. includes: [propertyHelper.js] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ verifyProperty(SharedArrayBuffer.prototype, 'grow', { diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/extensible.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/extensible.js index a4349e71a304..3465ce0753ed 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/extensible.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/extensible.js @@ -10,7 +10,7 @@ info: | 17 ECMAScript Standard Built-in Objects: Unless specified otherwise, the [[Extensible]] internal slot of a built-in object initially has the value true. -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert(Object.isExtensible(SharedArrayBuffer.prototype.grow)); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-larger-size.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-larger-size.js index 958d1d042559..fadedb47974a 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-larger-size.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-larger-size.js @@ -15,7 +15,7 @@ info: | 5. Let hostHandled be ? HostGrowSharedArrayBuffer(O, newByteLength). 6. If hostHandled is handled, return undefined. [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var sab = new SharedArrayBuffer(4, {maxByteLength: 5}); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-same-size.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-same-size.js index 9ac33fe6d973..9148d630a5fd 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-same-size.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-same-size.js @@ -15,7 +15,7 @@ info: | 5. Let hostHandled be ? HostGrowSharedArrayBuffer(O, newByteLength). 6. If hostHandled is handled, return undefined. [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var sab = new SharedArrayBuffer(4, {maxByteLength: 5}); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-smaller-size.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-smaller-size.js index f9a08a8ac300..1c2b7a193d5c 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-smaller-size.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/grow-smaller-size.js @@ -15,7 +15,7 @@ info: | 5. Let hostHandled be ? HostGrowSharedArrayBuffer(O, newByteLength). 6. If hostHandled is handled, return undefined. [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var sab = new SharedArrayBuffer(4, {maxByteLength: 5}); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/length.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/length.js index e91f52a49997..19c62cddb6b4 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/length.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/length.js @@ -20,7 +20,7 @@ info: | object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ verifyProperty(SharedArrayBuffer.prototype.grow, 'length', { diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/name.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/name.js index 2c07817961b4..56fccca7ea76 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/name.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/name.js @@ -16,7 +16,7 @@ info: | Unless otherwise specified, the name property of a built-in Function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] includes: [propertyHelper.js] ---*/ diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-excessive.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-excessive.js index 3f1842a56e15..d66f1bd919c1 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-excessive.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-excessive.js @@ -15,7 +15,7 @@ info: | 5. If newByteLength < 0 or newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception. [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var ab = new SharedArrayBuffer(4, {maxByteLength: 4}); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-negative.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-negative.js index e0e7708fff15..0c03abb4eabe 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-negative.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-negative.js @@ -15,7 +15,7 @@ info: | 5. If newByteLength < 0 or newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception. [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var ab = new SharedArrayBuffer(4, {maxByteLength: 4}); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-non-number.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-non-number.js index 29d351db16d3..a2ead7246081 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-non-number.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/new-length-non-number.js @@ -12,7 +12,7 @@ info: | 3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception. 4. Let newByteLength be ? ToIntegerOrInfinity(newLength). [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var log = []; diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/nonconstructor.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/nonconstructor.js index 3b52579423b4..ae4b722e578d 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/nonconstructor.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/nonconstructor.js @@ -12,7 +12,7 @@ info: | Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function. -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-arraybuffer-object.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-arraybuffer-object.js index a9bd3d022eb4..271064ba5c2a 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-arraybuffer-object.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-arraybuffer-object.js @@ -11,7 +11,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]). [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert.sameValue(typeof SharedArrayBuffer.prototype.grow, 'function'); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-object.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-object.js index 312bbc21bf7c..cfcdbbfa6917 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-object.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-object.js @@ -10,7 +10,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]). [...] -features: [resizable-arraybuffer, Symbol, BigInt] +features: [BigInt, SharedArrayBuffer, Symbol, resizable-arraybuffer] ---*/ assert.sameValue(typeof SharedArrayBuffer.prototype.grow, "function"); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-resizable-arraybuffer-object.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-resizable-arraybuffer-object.js index 9b5577c0dcb1..34ccedf87919 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-resizable-arraybuffer-object.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-not-resizable-arraybuffer-object.js @@ -11,7 +11,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]). [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var ab; diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-sharedarraybuffer.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-sharedarraybuffer.js index bf3260dfd858..09f7eafe017d 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-sharedarraybuffer.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/grow/this-is-sharedarraybuffer.js @@ -11,7 +11,7 @@ info: | 2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]). 3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception. [...] -features: [ArrayBuffer, resizable-arraybuffer] +features: [ArrayBuffer, SharedArrayBuffer, resizable-arraybuffer] ---*/ var ab = new ArrayBuffer(0); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/invoked-as-accessor.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/invoked-as-accessor.js index c34e8b9ecc53..9a124c9d045a 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/invoked-as-accessor.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/invoked-as-accessor.js @@ -10,7 +10,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert.throws(TypeError, function() { diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/invoked-as-func.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/invoked-as-func.js index 7f1d02e03623..05bb0383f04b 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/invoked-as-func.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/invoked-as-func.js @@ -10,7 +10,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var getter = Object.getOwnPropertyDescriptor( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/length.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/length.js index d961c7e4a51d..f63fa5a6a319 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/length.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/length.js @@ -20,7 +20,7 @@ info: | object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var desc = Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'growable'); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/name.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/name.js index e55b9b36541f..abfcf3c8f2ee 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/name.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/name.js @@ -12,7 +12,7 @@ description: > properties have "get " or "set " prepended to the property name string. includes: [propertyHelper.js] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var desc = Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'growable'); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/prop-desc.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/prop-desc.js index 293e87cdf871..7714b87db3ed 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/prop-desc.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/prop-desc.js @@ -12,7 +12,7 @@ info: | Section 17: Every accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes {[[Enumerable]]: false, [[Configurable]]: true } includes: [propertyHelper.js] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var desc = Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'growable'); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/return-growable.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/return-growable.js index 1ec6817b1848..72dd317a4795 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/return-growable.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/return-growable.js @@ -18,7 +18,7 @@ info: | [[ArrayBufferData]] internal slot. 2. If buffer has an [[ArrayBufferMaxByteLength]] internal slot, return true. 3. Return false. -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var sab1 = new SharedArrayBuffer(1); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-has-no-arraybufferdata-internal.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-has-no-arraybufferdata-internal.js index efa703c77358..4c3edb6d58a9 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-has-no-arraybufferdata-internal.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-has-no-arraybufferdata-internal.js @@ -12,7 +12,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). [...] -features: [DataView, Int8Array, resizable-arraybuffer] +features: [DataView, SharedArrayBuffer, TypedArray, resizable-arraybuffer] ---*/ var getter = Object.getOwnPropertyDescriptor( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-is-arraybuffer.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-is-arraybuffer.js index 04cd32222e8b..d6a3dcd8daac 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-is-arraybuffer.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-is-arraybuffer.js @@ -11,7 +11,7 @@ info: | 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). 3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception. [...] -features: [SharedArrayBuffer, resizable-arraybuffer] +features: [ArrayBuffer, SharedArrayBuffer, resizable-arraybuffer] ---*/ var growable = Object.getOwnPropertyDescriptor( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-is-not-object.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-is-not-object.js index d31151245c5e..7ba2cfb2c5ec 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-is-not-object.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/growable/this-is-not-object.js @@ -10,7 +10,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). [...] -features: [Symbol, resizable-arraybuffer] +features: [SharedArrayBuffer, Symbol, resizable-arraybuffer] ---*/ var getter = Object.getOwnPropertyDescriptor( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/invoked-as-accessor.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/invoked-as-accessor.js index f9399d27b69b..a0827878f263 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/invoked-as-accessor.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/invoked-as-accessor.js @@ -10,7 +10,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ assert.throws(TypeError, function() { diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/invoked-as-func.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/invoked-as-func.js index cb7b00eae374..4ddb9dc47ce0 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/invoked-as-func.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/invoked-as-func.js @@ -10,7 +10,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). [...] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var getter = Object.getOwnPropertyDescriptor( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/length.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/length.js index aa6ebbeb67e2..def0904c0eb3 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/length.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/length.js @@ -20,7 +20,7 @@ info: | object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var desc = Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'maxByteLength'); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/name.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/name.js index 1854ac55adc9..da6c9f3069d3 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/name.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/name.js @@ -12,7 +12,7 @@ description: > properties have "get " or "set " prepended to the property name string. includes: [propertyHelper.js] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var desc = Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'maxByteLength'); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/prop-desc.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/prop-desc.js index 9ca9167e8f5b..d64176a81ad6 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/prop-desc.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/prop-desc.js @@ -12,7 +12,7 @@ info: | Section 17: Every accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes {[[Enumerable]]: false, [[Configurable]]: true } includes: [propertyHelper.js] -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var desc = Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'maxByteLength'); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/return-maxbytelength-growable.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/return-maxbytelength-growable.js index 755b5fddc29c..c417ca9bd58f 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/return-maxbytelength-growable.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/return-maxbytelength-growable.js @@ -15,7 +15,7 @@ info: | 5. Else, [...] 6. Return 𝔽(length). -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var ab1 = new SharedArrayBuffer(0, { maxByteLength: 0 }); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/return-maxbytelength-non-growable.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/return-maxbytelength-non-growable.js index afb623cd1be8..279088bff4be 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/return-maxbytelength-non-growable.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/return-maxbytelength-non-growable.js @@ -15,7 +15,7 @@ info: | 5. Else, a. Let length be O.[[ArrayBufferByteLength]]. 6. Return 𝔽(length). -features: [resizable-arraybuffer] +features: [SharedArrayBuffer, resizable-arraybuffer] ---*/ var ab1 = new SharedArrayBuffer(0); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-has-no-arraybufferdata-internal.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-has-no-arraybufferdata-internal.js index 1dfcde319096..e692194ce22c 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-has-no-arraybufferdata-internal.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-has-no-arraybufferdata-internal.js @@ -12,7 +12,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). [...] -features: [DataView, Int8Array, resizable-arraybuffer] +features: [DataView, SharedArrayBuffer, TypedArray, resizable-arraybuffer] ---*/ var getter = Object.getOwnPropertyDescriptor( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-is-arraybuffer.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-is-arraybuffer.js index 4899174e7daf..ebd09399ffa0 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-is-arraybuffer.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-is-arraybuffer.js @@ -11,7 +11,7 @@ info: | 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). 3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception. [...] -features: [ArrayBuffer, resizable-arraybuffer] +features: [ArrayBuffer, SharedArrayBuffer, resizable-arraybuffer] ---*/ var maxByteLength = Object.getOwnPropertyDescriptor( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-is-not-object.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-is-not-object.js index f0f294741fed..0fd8c2a6c7f8 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-is-not-object.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/maxByteLength/this-is-not-object.js @@ -10,7 +10,7 @@ info: | 1. Let O be the this value. 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). [...] -features: [Symbol, resizable-arraybuffer] +features: [SharedArrayBuffer, Symbol, resizable-arraybuffer] ---*/ var getter = Object.getOwnPropertyDescriptor( diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/prop-desc.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/prop-desc.js new file mode 100644 index 000000000000..1e4b08474134 --- /dev/null +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/prop-desc.js @@ -0,0 +1,18 @@ +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-sharedarraybuffer.prototype +description: Property descriptor of the 'prototype' property +info: | + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: false }. +includes: [propertyHelper.js] +---*/ + +verifyProperty(SharedArrayBuffer, 'prototype', { + enumerable: false, + writable: false, + configurable: false +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/slice/this-is-arraybuffer.js b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/slice/this-is-arraybuffer.js index 376f0dd24eb6..ebe64e1ba941 100644 --- a/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/slice/this-is-arraybuffer.js +++ b/js/src/tests/test262/built-ins/SharedArrayBuffer/prototype/slice/this-is-arraybuffer.js @@ -6,7 +6,7 @@ esid: sec-sharedarraybuffer.prototype.slice description: > Throws a TypeError if `this` is an ArrayBuffer -features: [SharedArrayBuffer] +features: [ArrayBuffer, SharedArrayBuffer] ---*/ assert.throws(TypeError, function() { diff --git a/js/src/tests/test262/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js b/js/src/tests/test262/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js index 7d688338d8d4..65f9289ccb05 100644 --- a/js/src/tests/test262/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js +++ b/js/src/tests/test262/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js @@ -1,15 +1,21 @@ // Copyright 2012 Norbert Lindenberg. All rights reserved. // Copyright 2012 Mozilla Corporation. All rights reserved. // Copyright 2013 Microsoft Corporation. All rights reserved. +// Copyright (C) 2022 Richard Gibson. All rights reserved. // This code is governed by the license found in the LICENSE file. /*--- -es5id: 15.5.4.9_CE description: > - Tests that String.prototype.localeCompare returns 0 when - comparing Strings that are considered canonically equivalent by - the Unicode standard. -author: Norbert Lindenberg + String.prototype.localeCompare must return 0 when + comparing Strings that are considered canonically equivalent by + the Unicode Standard. +esid: sec-string.prototype.localecompare +info: | + String.prototype.localeCompare ( _that_ [ , _reserved1_ [ , _reserved2_ ] ] ) + + This function must treat Strings that are canonically equivalent + according to the Unicode standard as identical and must return `0` + when comparing Strings that are considered canonically equivalent. ---*/ // pairs with characters not in Unicode 3.0 are commented out @@ -49,26 +55,12 @@ var pairs = [ // ["\uD87E\uDC2B", "北"] ]; -// Detect whether we are using locale-sensitive comparisons or a bitwise comparison -if ("a".localeCompare("Z") < 0) { - // We are using locale-sensitive comparison, so all pairs should be canonically equivalent - var i; - for (i = 0; i < pairs.length; i++) { - var pair = pairs[i]; - if (pair[0].localeCompare(pair[1]) !== 0) { - throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + - ") ≠ " + pair[1] + " (" + toU(pair[1]) + ")."); - } - } -} else { - // We are using bitwise comparison, so all pairs should not be equivalent - var i; - for (i = 0; i < pairs.length; i++) { - var pair = pairs[i]; - if (pair[0].localeCompare(pair[1]) === 0) { - throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + - ") = " + pair[1] + " (" + toU(pair[1]) + ")."); - } +var i; +for (i = 0; i < pairs.length; i++) { + var pair = pairs[i]; + if (pair[0].localeCompare(pair[1]) !== 0) { + throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + + ") ≠ " + pair[1] + " (" + toU(pair[1]) + ")."); } } diff --git a/js/src/tests/test262/built-ins/String/prototype/matchAll/shell.js b/js/src/tests/test262/built-ins/String/prototype/matchAll/shell.js index acac42890065..1ad30bb1df39 100644 --- a/js/src/tests/test262/built-ins/String/prototype/matchAll/shell.js +++ b/js/src/tests/test262/built-ins/String/prototype/matchAll/shell.js @@ -42,7 +42,7 @@ assert.compareIterator = function(iter, validators, message) { /*--- description: | Collection of functions used to assert the correctness of RegExp objects. -defines: [buildString, testPropertyEscapes, matchValidator] +defines: [buildString, testPropertyEscapes, testPropertyOfStrings, matchValidator] ---*/ function buildString(args) { @@ -70,23 +70,65 @@ function buildString(args) { return result; } -function testPropertyEscapes(regex, string, expression) { - if (!regex.test(string)) { +function printCodePoint(codePoint) { + const hex = codePoint + .toString(16) + .toUpperCase() + .padStart(6, "0"); + return `U+${hex}`; +} + +function printStringCodePoints(string) { + const buf = []; + for (const symbol of string) { + const formatted = printCodePoint(symbol.codePointAt(0)); + buf.push(formatted); + } + return buf.join(' '); +} + +function testPropertyEscapes(regExp, string, expression) { + if (!regExp.test(string)) { for (const symbol of string) { - const hex = symbol - .codePointAt(0) - .toString(16) - .toUpperCase() - .padStart(6, "0"); + printCodePoint(symbol.codePointAt(0)); assert( - regex.test(symbol), + regExp.test(symbol), `\`${ expression }\` should match U+${ hex } (\`${ symbol }\`)` ); } } } -// Returns a function that will validate RegExp match result +function testPropertyOfStrings(args) { + // Use member expressions rather than destructuring `args` for improved + // compatibility with engines that only implement assignment patterns + // partially or not at all. + const regExp = args.regExp; + const expression = args.expression; + const matchStrings = args.matchStrings; + const nonMatchStrings = args.nonMatchStrings; + const allStrings = matchStrings.join(''); + if (!regExp.test(allStrings)) { + for (const string of matchStrings) { + assert( + regExp.test(string), + `\`${ expression }\` should match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } + + const allNonMatchStrings = nonMatchStrings.join(''); + if (regExp.test(allNonMatchStrings)) { + for (const string of nonMatchStrings) { + assert( + !regExp.test(string), + `\`${ expression }\` should not match ${ string } (U+${ printStringCodePoints(string) })` + ); + } + } +} + +// Returns a function that validates a RegExp match result. // // Example: // diff --git a/js/src/tests/test262/built-ins/Symbol/species/basic.js b/js/src/tests/test262/built-ins/Symbol/species/basic.js index 4e542448eac2..cb6e400e0278 100644 --- a/js/src/tests/test262/built-ins/Symbol/species/basic.js +++ b/js/src/tests/test262/built-ins/Symbol/species/basic.js @@ -7,8 +7,7 @@ info: | es6id: 19.4.2.10 author: Sam Mikes description: Symbol.species exists -includes: - - propertyHelper.js +includes: [propertyHelper.js] features: [Symbol.species] ---*/ diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/builtin.js new file mode 100644 index 000000000000..d0617956a31b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: Tests that Temporal.Calendar meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.Calendar.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/constructor.js new file mode 100644 index 000000000000..745c8c63f786 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: Temporal.Calendar constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.Calendar()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/era/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/era/browser.js rename to js/src/tests/test262/built-ins/Temporal/Calendar/from/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/builtin.js new file mode 100644 index 000000000000..d46972856936 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Tests that Temporal.Calendar.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object-invalid.js new file mode 100644 index 000000000000..f22e9726e50b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object-invalid.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Converting objects to Temporal.Calendar +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.Calendar.from({ calendar: "local" })); +assert.throws(RangeError, () => Temporal.Calendar.from({ calendar: { calendar: "iso8601" } })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object-operations.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object-operations.js new file mode 100644 index 000000000000..a125d1ccb14c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object-operations.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Converting objects to Temporal.Calendar +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "has outer.calendar", + "get outer.calendar", + "has inner.calendar", + "get inner.toString", + "call inner.toString", +]; +const actual = []; +const calendar = new Proxy({}, { + has(t, p) { + actual.push(`has outer.${p}`); + return true; + }, + get(t, p) { + actual.push(`get outer.${p}`); + return new Proxy(TemporalHelpers.toPrimitiveObserver(actual, "iso8601", "inner"), { + has(t, p) { + actual.push(`has inner.${p}`); + return true; + }, + get(t, p) { + return t[p]; + }, + }); + }, +}); +const result = Temporal.Calendar.from(calendar); +assert.sameValue(result.id, "iso8601"); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object.js new file mode 100644 index 000000000000..c27e952acd9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Converting objects to Temporal.Calendar +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); +const calFromObject = Temporal.Calendar.from({ calendar: cal }); +assert(calFromObject instanceof Temporal.Calendar); +assert.sameValue(calFromObject.id, "iso8601"); + +const calFromString = Temporal.Calendar.from({ calendar: "iso8601" }); +assert(calFromString instanceof Temporal.Calendar); +assert.sameValue(calFromString.id, "iso8601"); + +const custom = { id: "custom-calendar" }; +assert.sameValue(Temporal.Calendar.from({ calendar: custom }), custom); +assert.sameValue(Temporal.Calendar.from(custom), custom); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-builtin.js new file mode 100644 index 000000000000..7a8f6e0381cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-builtin.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Calendar.from should support iso8601. +features: [Temporal] +---*/ + +const tests = [ + "iso8601", + "1994-11-05T08:15:30-05:00", +]; + +for (const item of tests) { + const calendar = Temporal.Calendar.from(item); + assert(calendar instanceof Temporal.Calendar); + assert.sameValue(calendar.id, "iso8601"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-not-builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-not-builtin.js new file mode 100644 index 000000000000..5c5134952453 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-not-builtin.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: from() throws if the argument is not a built-in calendar name. +features: [Temporal] +---*/ + +const tests = [ + "local", + "iso-8601", + "[u-ca=iso8601]", + "invalid-calendar", +]; + +for (const item of tests) { + assert.throws(RangeError, () => Temporal.Calendar.from(item)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-temporal-object.js new file mode 100644 index 000000000000..ea34a99d6db9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-temporal-object.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.from step 1: + 1. Return ? ToTemporalCalendar(_item_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const newCalendar = Temporal.Calendar.from(temporalObject); + assert.sameValue(newCalendar, calendar, "calendar object retrieved from internal slot"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/length.js new file mode 100644 index 000000000000..8188e06b701b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Temporal.Calendar.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/name.js new file mode 100644 index 000000000000..8b985c5d987e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Temporal.Calendar.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/not-a-constructor.js new file mode 100644 index 000000000000..486af144949b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Temporal.Calendar.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.from), false, + "isConstructor(Temporal.Calendar.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/prop-desc.js new file mode 100644 index 000000000000..2b624f425179 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: The "from" property of Temporal.Calendar +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.from, + "function", + "`typeof Calendar.from` is `function`" +); + +verifyProperty(Temporal.Calendar, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/subclassing-ignored.js new file mode 100644 index 000000000000..8166ac7da1a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/subclassing-ignored.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.Calendar, + "from", + ["iso8601"], + (result) => { + assert.sameValue(result.id, "iso8601", "id property of result"); + assert.sameValue(result.toString(), "iso8601", "toString() of result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/length.js new file mode 100644 index 000000000000..e8d3e8e41a24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: Temporal.Calendar.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/Calendar/missing-arguments.js new file mode 100644 index 000000000000..f9afe5f7d20d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/missing-arguments.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: RangeError thrown when constructor invoked with no argument +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.Calendar()); +assert.throws(RangeError, () => new Temporal.Calendar(undefined)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/name.js new file mode 100644 index 000000000000..7ceb7150937e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: Temporal.Calendar.name is "Calendar" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar, "name", { + value: "Calendar", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prop-desc.js new file mode 100644 index 000000000000..73e036f1cc4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: The "Calendar" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar, + "function", + "`typeof Calendar` is `function`" +); + +verifyProperty(Temporal, "Calendar", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-plaindatetime.js new file mode 100644 index 000000000000..26f3dca6e9d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-plaindatetime.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.calendar.prototype.dateadd step 4: + 4. Set _date_ to ? ToTemporalDate(_date_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(0, 1); + const result = calendar.dateAdd(datetime, duration); + TemporalHelpers.assertPlainDate(result, 2000, 6, "M06", 2); + assert.sameValue(result.hour, undefined, "instance of PlainDate returned, not PlainDateTime"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js new file mode 100644 index 000000000000..febd13f9b03d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dateAdd(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..2507334ac3d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateAdd(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..fa2b479ed7e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dateAdd(datetime, duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..e4fe54c34239 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.dateAdd(datetime, duration), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..dfe71d275c87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dateAdd(datetime, duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..9160e6ccee58 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.dateAdd(datetime, duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/balance-smaller-units.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/balance-smaller-units.js new file mode 100644 index 000000000000..c385b3ffecb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/balance-smaller-units.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Durations with units smaller than days are balanced before adding +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = new Temporal.Duration(0, 0, 0, 1, 24, 1440, 86400, 86400_000, 86400_000_000, 86400_000_000_000); + +const result = calendar.dateAdd(date, duration); +TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 9, "units smaller than days are balanced"); + +const resultString = calendar.dateAdd(date, "P1DT24H1440M86400S"); +TemporalHelpers.assertPlainDate(resultString, 2000, 5, "M05", 6, "units smaller than days are balanced"); + +const resultPropBag = calendar.dateAdd(date, { days: 1, hours: 24, minutes: 1440, seconds: 86400, milliseconds: 86400_000, microseconds: 86400_000_000, nanoseconds: 86400_000_000_000 }); +TemporalHelpers.assertPlainDate(resultPropBag, 2000, 5, "M05", 9, "units smaller than days are balanced"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/basic.js new file mode 100644 index 000000000000..a14facd181ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/basic.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Basic tests for dateAdd(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const date = Temporal.PlainDate.from("1994-11-06"); +const positiveDuration = Temporal.Duration.from({ months: 1, weeks: 1 }); +const negativeDuration = Temporal.Duration.from({ months: -1, weeks: -1 }); + +TemporalHelpers.assertPlainDate( + iso.dateAdd(Temporal.PlainDateTime.from("1994-11-06T08:15:30"), positiveDuration, {}), + 1994, 12, "M12", 13, "date: PlainDateTime"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd({ year: 1994, month: 11, day: 6 }, positiveDuration, {}), + 1994, 12, "M12", 13, "date: property bag"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd("1994-11-06", positiveDuration, {}), + 1994, 12, "M12", 13, "date: string"); + +assert.throws(TypeError, () => iso.dateAdd({ month: 11 }, positiveDuration, {}), "date: missing property"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd(date, { months: 1, weeks: 1 }, {}), + 1994, 12, "M12", 13, "duration: property bag"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd(date, "P1M1W", {}), + 1994, 12, "M12", 13, "duration: string"); + +assert.throws(TypeError, () => iso.dateAdd(date, { month: 1 }, {}), "duration: missing property"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd(Temporal.PlainDateTime.from("1994-11-06T08:15:30"), negativeDuration, {}), + 1994, 9, "M09", 29, "date: PlainDateTime, negative duration"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd({ year: 1994, month: 11, day: 6 }, negativeDuration, {}), + 1994, 9, "M09", 29, "date: property bag, negative duration"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd("1994-11-06", negativeDuration, {}), + 1994, 9, "M09", 29, "date: string, negative duration"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/branding.js index 244ae9e56881..646e2097aa8b 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/branding.js @@ -12,14 +12,16 @@ const dateAdd = Temporal.Calendar.prototype.dateAdd; assert.sameValue(typeof dateAdd, "function"); -assert.throws(TypeError, () => dateAdd.call(undefined), "undefined"); -assert.throws(TypeError, () => dateAdd.call(null), "null"); -assert.throws(TypeError, () => dateAdd.call(true), "true"); -assert.throws(TypeError, () => dateAdd.call(""), "empty string"); -assert.throws(TypeError, () => dateAdd.call(Symbol()), "symbol"); -assert.throws(TypeError, () => dateAdd.call(1), "1"); -assert.throws(TypeError, () => dateAdd.call({}), "plain object"); -assert.throws(TypeError, () => dateAdd.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => dateAdd.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1), new Temporal.Duration(1)]; + +assert.throws(TypeError, () => dateAdd.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dateAdd.apply(null, args), "null"); +assert.throws(TypeError, () => dateAdd.apply(true, args), "true"); +assert.throws(TypeError, () => dateAdd.apply("", args), "empty string"); +assert.throws(TypeError, () => dateAdd.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dateAdd.apply(1, args), "1"); +assert.throws(TypeError, () => dateAdd.apply({}, args), "plain object"); +assert.throws(TypeError, () => dateAdd.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dateAdd.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/builtin.js new file mode 100644 index 000000000000..c66f673ff70a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: > + Tests that Temporal.Calendar.prototype.dateAdd + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.dateAdd), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dateAdd), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dateAdd), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dateAdd.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..247a94528460 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.dateAdd({ year: 2000, month: 5, day: 2, calendar }, new Temporal.Duration(1)); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-fields-iterable.js new file mode 100644 index 000000000000..b297cd7bc3bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-fields-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.dateadd step 4: + 4. Set _date_ to ? ToTemporalDate(_date_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const duration = new Temporal.Duration(0, 1); +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.dateAdd({ year: 2000, month: 5, day: 2, calendar: calendar2 }, duration); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-temporal-object.js new file mode 100644 index 000000000000..6e5e719a37a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.dateadd step 4: + 4. Set _date_ to ? ToTemporalDate(_date_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(0, 1); + calendar.dateAdd({ year: 2000, month: 5, day: 2, calendar: temporalObject }, duration); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..e0ba54edfbd7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dateadd +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const duration = new Temporal.Duration(1); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.dateAdd({ ...base, [prop]: inf }, duration, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.dateAdd({ ...base, [prop]: obj }, duration, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/duration-argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/duration-argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..ee5bafa63fa3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/duration-argument-string-negative-fractional-units.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); + +const resultHours = calendar.dateAdd(instance, "-PT24.567890123H"); +TemporalHelpers.assertPlainDate(resultHours, 2000, 5, "M05", 1, "negative fractional hours"); + +const resultMinutes = calendar.dateAdd(instance, "-PT1440.567890123M"); +TemporalHelpers.assertPlainDate(resultMinutes, 2000, 5, "M05", 1, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/length.js new file mode 100644 index 000000000000..740d54d9ea3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dateAdd, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/name.js new file mode 100644 index 000000000000..13dfde8302fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd.name is "dateAdd". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dateAdd, "name", { + value: "dateAdd", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/not-a-constructor.js new file mode 100644 index 000000000000..772be400baa6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: > + Temporal.Calendar.prototype.dateAdd does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.dateAdd(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dateAdd), false, + "isConstructor(Temporal.Calendar.prototype.dateAdd)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js new file mode 100644 index 000000000000..d0e1c402d023 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). +features: [Temporal, arrow-function] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = new Temporal.Duration(3, 3, 0, 3); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.dateAdd(date, duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-undefined.js new file mode 100644 index 000000000000..12e0527f7f4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 31, calendar); +const duration = new Temporal.Duration(3, 1); + +const explicit = calendar.dateAdd(date, duration, { overflow: undefined }); +TemporalHelpers.assertPlainDate(explicit, 2003, 6, "M06", 30, "default overflow is constrain"); +const implicit = calendar.dateAdd(date, duration, {}); +TemporalHelpers.assertPlainDate(implicit, 2003, 6, "M06", 30, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-wrong-type.js new file mode 100644 index 000000000000..70768ce7b2d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = new Temporal.Duration(3, 3, 0, 3); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => calendar.dateAdd(date, duration, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDate(result, 2003, 8, "M08", 5, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/prop-desc.js new file mode 100644 index 000000000000..069b289a47a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: The "dateAdd" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dateAdd, + "function", + "`typeof Calendar.prototype.dateAdd` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dateAdd", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/shell.js index ab8cfa8454a9..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/shell.js @@ -1,4 +1,23 @@ // GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + // file: temporalHelpers.js // Copyright (C) 2021 Igalia, S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. @@ -30,6 +49,29 @@ var TemporalHelpers = { assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); }, + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + /* * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): * @@ -73,17 +115,32 @@ var TemporalHelpers = { }, /* - * assertPlainMonthDay(monthDay, monthCode, day[, description]): + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): * * Shorthand for asserting that each field of a Temporal.PlainMonthDay is * equal to an expected value. (Except the `calendar` property, since callers * may want to assert either object equality with an object they put in there, * or the result of monthDay.calendar.toString().) */ - assertPlainMonthDay(monthDay, monthCode, day, description = "") { + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); }, /* @@ -102,6 +159,18 @@ var TemporalHelpers = { assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); }, + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + /* * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): * @@ -118,6 +187,670 @@ var TemporalHelpers = { assert.sameValue(yearMonth.month, month, `${description} month result`); assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + /* * Check that any calendar-carrying Temporal object has its [[Calendar]] * internal slot read by ToTemporalCalendar, and does not fetch the calendar @@ -161,6 +894,506 @@ var TemporalHelpers = { }); }, + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + /* * specificOffsetTimeZone(): * @@ -189,4 +1422,96 @@ var TemporalHelpers = { } return new SpecificOffsetTimeZone(offsetValue); }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, }; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalOverflow.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalOverflow.js deleted file mode 100644 index 6f0d4526f18f..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalOverflow.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.calendar.prototype.dateadd -description: Temporal.Calendar.prototype.dateAdd should throw from ToTemporalOverflow. -info: | - 7. Let overflow be ? ToTemporalOverflow(options). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -assert.throws(RangeError, - () => cal.dateAdd("2020-02-29", "PT1M", {overflow: "bad value"}), - 'cal.dateAdd("2020-02-29", "PT1M", {overflow: "bad value"}) throws a RangeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-type-error-from-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-type-error-from-RequireInternalSlot.js deleted file mode 100644 index 5efe9016c3e1..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-type-error-from-RequireInternalSlot.js +++ /dev/null @@ -1,20 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.calendar.prototype.dateadd -description: Temporal.Calendar.prototype.dateAdd should throw if calendar does not have required internal slot -info: | - 1. Let calendar be the this value. - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { dateAdd: cal.dateAdd }; -assert.throws(TypeError, - () => badCal.dateAdd("2020-02-29", new Temporal.Duration(1)), - 'badCal.dateAdd("2020-02-29", new Temporal.Duration(1)) throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/year-zero.js new file mode 100644 index 000000000000..adb012979744 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.dateAdd(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/branding.js index c181f777d536..1e9bb1ee55d9 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/branding.js @@ -12,14 +12,16 @@ const dateFromFields = Temporal.Calendar.prototype.dateFromFields; assert.sameValue(typeof dateFromFields, "function"); -assert.throws(TypeError, () => dateFromFields.call(undefined), "undefined"); -assert.throws(TypeError, () => dateFromFields.call(null), "null"); -assert.throws(TypeError, () => dateFromFields.call(true), "true"); -assert.throws(TypeError, () => dateFromFields.call(""), "empty string"); -assert.throws(TypeError, () => dateFromFields.call(Symbol()), "symbol"); -assert.throws(TypeError, () => dateFromFields.call(1), "1"); -assert.throws(TypeError, () => dateFromFields.call({}), "plain object"); -assert.throws(TypeError, () => dateFromFields.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => dateFromFields.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [{ year: 2000, month: 1, day: 1 }]; + +assert.throws(TypeError, () => dateFromFields.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dateFromFields.apply(null, args), "null"); +assert.throws(TypeError, () => dateFromFields.apply(true, args), "true"); +assert.throws(TypeError, () => dateFromFields.apply("", args), "empty string"); +assert.throws(TypeError, () => dateFromFields.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dateFromFields.apply(1, args), "1"); +assert.throws(TypeError, () => dateFromFields.apply({}, args), "plain object"); +assert.throws(TypeError, () => dateFromFields.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dateFromFields.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/builtin.js new file mode 100644 index 000000000000..738e7514c153 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: > + Tests that Temporal.Calendar.prototype.dateFromFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.dateFromFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dateFromFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dateFromFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dateFromFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/fields-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/fields-not-object.js new file mode 100644 index 000000000000..83c1a5101c13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/fields-not-object.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Throw a TypeError if the fields is not an object +info: | + 4. If Type(_fields_) is not Object, throw a *TypeError* exception. +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +const tests = [undefined, null, true, false, "string", Symbol("sym"), Infinity, NaN, Math.PI, 42n]; +const iso = Temporal.Calendar.from("iso8601"); +for (const fields of tests) { + assert.throws( + TypeError, + () => iso.dateFromFields(fields, {}) + `dateFromFields(${typeof fields}) throws a TypeError exception` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..25e25c975c00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.datefromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.dateFromFields({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.dateFromFields({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/length.js new file mode 100644 index 000000000000..5673a5497ae9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dateFromFields, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/name.js new file mode 100644 index 000000000000..e01fa649207e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields.name is "dateFromFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dateFromFields, "name", { + value: "dateFromFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/not-a-constructor.js new file mode 100644 index 000000000000..4534e69625ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: > + Temporal.Calendar.prototype.dateFromFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.dateFromFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dateFromFields), false, + "isConstructor(Temporal.Calendar.prototype.dateFromFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js new file mode 100644 index 000000000000..833eb4390098 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.datefromfields step 6: + 6. Let _result_ be ? ISODateFromFields(_fields_, _options_). +features: [Temporal, arrow-function] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, + { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-undefined.js new file mode 100644 index 000000000000..eb82e945e53e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.datefromfields step 6: + 6. Let _result_ be ? ISODateFromFields(_fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +const explicit = calendar.dateFromFields({ year: 2000, month: 15, day: 2 }, { overflow: undefined }); +TemporalHelpers.assertPlainDate(explicit, 2000, 12, "M12", 2, "default overflow is constrain"); +const implicit = calendar.dateFromFields({ year: 2000, month: 15, day: 2 }, {}); +TemporalHelpers.assertPlainDate(implicit, 2000, 12, "M12", 2, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-wrong-type.js new file mode 100644 index 000000000000..0196a3cbce47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.datefromfields step 6: + 6. Let _result_ be ? ISODateFromFields(_fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/prop-desc.js new file mode 100644 index 000000000000..3b0e9b803cdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: The "dateFromFields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dateFromFields, + "function", + "`typeof Calendar.prototype.dateFromFields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dateFromFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/shell.js index ab8cfa8454a9..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/shell.js @@ -1,4 +1,23 @@ // GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + // file: temporalHelpers.js // Copyright (C) 2021 Igalia, S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. @@ -30,6 +49,29 @@ var TemporalHelpers = { assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); }, + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + /* * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): * @@ -73,17 +115,32 @@ var TemporalHelpers = { }, /* - * assertPlainMonthDay(monthDay, monthCode, day[, description]): + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): * * Shorthand for asserting that each field of a Temporal.PlainMonthDay is * equal to an expected value. (Except the `calendar` property, since callers * may want to assert either object equality with an object they put in there, * or the result of monthDay.calendar.toString().) */ - assertPlainMonthDay(monthDay, monthCode, day, description = "") { + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); }, /* @@ -102,6 +159,18 @@ var TemporalHelpers = { assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); }, + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + /* * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): * @@ -118,6 +187,670 @@ var TemporalHelpers = { assert.sameValue(yearMonth.month, month, `${description} month result`); assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + /* * Check that any calendar-carrying Temporal object has its [[Calendar]] * internal slot read by ToTemporalCalendar, and does not fetch the calendar @@ -161,6 +894,506 @@ var TemporalHelpers = { }); }, + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + /* * specificOffsetTimeZone(): * @@ -189,4 +1422,96 @@ var TemporalHelpers = { } return new SpecificOffsetTimeZone(offsetValue); }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, }; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-range-error-from-ISODateFromFields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-range-error-from-ISODateFromFields.js deleted file mode 100644 index 41cc0bfb9649..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-range-error-from-ISODateFromFields.js +++ /dev/null @@ -1,17 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.calendar.prototype.datefromfields -description: Temporal.Calendar.prototype.dateFromFields should throw Error from ISODateFromFields. -info: | - 6. Let result be ? ISODateFromFields(fields, options). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601") - -assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 7, day: 20}, - {overflow: "invalid garbage"}), - 'cal.dateFromFields({year: 2021, month: 7, day: 20}, {overflow: "invalid garbage"}) throws a RangeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-fields-is-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-fields-is-not-object.js deleted file mode 100644 index 9039e22dbcc8..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-fields-is-not-object.js +++ /dev/null @@ -1,22 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.calendar.prototype.datefromfields -description: Temporal.Calendar.prototype.dateFromFields should throw TypeError while fields is not object. -info: | - 4. If Type(fields) is not Object, throw a TypeError exception. -features: [BigInt, Symbol, Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar('iso8601'); -let notObjectList = [null, undefined, 'string', Symbol('efg'), true, false, Infinity, NaN, 123, 456n]; - -notObjectList.forEach(function(fields) { - assert.throws( - TypeError, - () => cal.dateFromFields(fields), - 'cal.dateFromFields(fields) throws a TypeError exception' - ); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-from-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-from-RequireInternalSlot.js deleted file mode 100644 index efc9252d44f1..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-from-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.calendar.prototype.datefromfields -description: Temporal.Calendar.prototype.dateFromFields should throw TypeError while calendar has no [[InitializedTemporalCalendar]] -info: | - 1. Let calendar be the this value. - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601") -let badCal = {dateFromFields: cal.dateFromFields}; - -assert.throws(TypeError, () => badCal.dateFromFields({}), - 'badCal.dateFromFields({}) throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-range-error.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-range-error.js index d5564ce1d816..1aae50a41e8a 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-range-error.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-range-error.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.datefromfields -description: Temporal.Calendar.prototype.dateFromFields should throw RangeError for +description: > + Temporal.Calendar.prototype.dateFromFields should throw RangeError for input not in valid range. info: | 1. Let calendar be the this value. diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..4ab7d417a359 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dateuntil +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const other = new Temporal.PlainDate(2001, 6, 3); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.dateUntil({ ...base, [prop]: inf }, other), `${prop} property cannot be ${inf}`); + + assert.throws(RangeError, () => instance.dateUntil(other, { ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, prop); + assert.throws(RangeError, () => instance.dateUntil({ ...base, [prop]: obj1 }, other)); + assert.compareArray(calls1, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, prop); + assert.throws(RangeError, () => instance.dateUntil(other, { ...base, [prop]: obj2 })); + assert.compareArray(calls2, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-plaindatetime.js new file mode 100644 index 000000000000..1c2b130d254f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-plaindatetime.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.calendar.prototype.dateuntil steps 4–5: + 4. Set _one_ to ? ToTemporalDate(_one_). + 5. Set _two_ to ? ToTemporalDate(_two_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const calendar = new Temporal.Calendar("iso8601"); + const result = calendar.dateUntil(datetime, date); + assert.sameValue(result.total({ unit: "nanoseconds" }), 0, "time part dropped"); +}); + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const calendar = new Temporal.Calendar("iso8601"); + const result = calendar.dateUntil(date, datetime); + assert.sameValue(result.total({ unit: "nanoseconds" }), 0, "time part dropped"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js new file mode 100644 index 000000000000..032de19a8161 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js @@ -0,0 +1,70 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a %%%conversion_target%%% +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +const other = new Temporal.PlainDate(2020, 1, 1, instance); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dateUntil(arg, other), + `"${arg}" should not be a valid ISO string for a PlainDate (first argument)` + ); + assert.throws( + RangeError, + () => instance.dateUntil(other, arg), + `"${arg}" should not be a valid ISO string for a PlainDate (second argument)` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..c7d2382e0c8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-with-utc-designator.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +const plainDate = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateUntil(arg, plainDate), + "String with UTC designator should not be valid as a PlainDate (first argument)" + ); + assert.throws( + RangeError, + () => instance.dateUntil(plainDate, arg), + "String with UTC designator should not be valid as a PlainDate (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..96abbb46e3c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, Infinity, -Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(RangeError, () => calendar.dateUntil(datetime, date)); + assert.throws(RangeError, () => calendar.dateUntil(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..18bb629148b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + + assert.throws( + TypeError, + () => calendar.dateUntil(datetime, date), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); + assert.throws( + TypeError, + () => calendar.dateUntil(date, datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..4fc613a10890 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(RangeError, () => calendar.dateUntil(datetime, date)); + assert.throws(RangeError, () => calendar.dateUntil(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..f865e6185ef5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(TypeError, () => calendar.dateUntil(datetime, date)); + assert.throws(TypeError, () => calendar.dateUntil(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/basic.js new file mode 100644 index 000000000000..578969af3918 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/basic.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Basic tests for dateUntil(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const date1 = Temporal.PlainDate.from("1999-09-03"); +const date2 = Temporal.PlainDate.from("2000-01-01"); + +TemporalHelpers.assertDuration( + iso.dateUntil(date1, date2, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "two PlainDates"); + +TemporalHelpers.assertDuration( + iso.dateUntil(Temporal.PlainDateTime.from("1999-09-03T08:15:30"), date2, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "first argument: PlainDateTime"); + +TemporalHelpers.assertDuration( + iso.dateUntil({ year: 1999, month: 9, day: 3 }, date2, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "first argument: property bag"); + +TemporalHelpers.assertDuration( + iso.dateUntil("1999-09-03", date2, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "first argument: string"); + +assert.throws(TypeError, () => iso.dateUntil({ month: 11 }, date2, {}), "first argument: missing property"); + +TemporalHelpers.assertDuration( + iso.dateUntil(date1, Temporal.PlainDateTime.from("2000-01-01T08:15:30"), {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "second argument: PlainDateTime"); + +TemporalHelpers.assertDuration( + iso.dateUntil(date1, { year: 2000, month: 1, day: 1 }, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "second argument: property bag"); + +TemporalHelpers.assertDuration( + iso.dateUntil(date1, "2000-01-01", {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "second argument: string"); + +assert.throws(TypeError, () => iso.dateUntil(date1, { month: 11 }, {}), "second argument: missing property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/branding.js index 02cb5d231d56..821019468d1b 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/branding.js @@ -12,14 +12,16 @@ const dateUntil = Temporal.Calendar.prototype.dateUntil; assert.sameValue(typeof dateUntil, "function"); -assert.throws(TypeError, () => dateUntil.call(undefined), "undefined"); -assert.throws(TypeError, () => dateUntil.call(null), "null"); -assert.throws(TypeError, () => dateUntil.call(true), "true"); -assert.throws(TypeError, () => dateUntil.call(""), "empty string"); -assert.throws(TypeError, () => dateUntil.call(Symbol()), "symbol"); -assert.throws(TypeError, () => dateUntil.call(1), "1"); -assert.throws(TypeError, () => dateUntil.call({}), "plain object"); -assert.throws(TypeError, () => dateUntil.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => dateUntil.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2021, 7, 16), new Temporal.PlainDate(2021, 7, 17)]; + +assert.throws(TypeError, () => dateUntil.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dateUntil.apply(null, args), "null"); +assert.throws(TypeError, () => dateUntil.apply(true, args), "true"); +assert.throws(TypeError, () => dateUntil.apply("", args), "empty string"); +assert.throws(TypeError, () => dateUntil.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dateUntil.apply(1, args), "1"); +assert.throws(TypeError, () => dateUntil.apply({}, args), "plain object"); +assert.throws(TypeError, () => dateUntil.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dateUntil.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/builtin.js new file mode 100644 index 000000000000..6d815bb5f5e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: > + Tests that Temporal.Calendar.prototype.dateUntil + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.dateUntil), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dateUntil), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dateUntil), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dateUntil.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..dd0bf1d426e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.dateUntil({ year: 2000, month: 5, day: 2, calendar }, { year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-fields-iterable.js new file mode 100644 index 000000000000..dbdb3f084006 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-fields-iterable.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.dateuntil steps 4–5: + 4. Set _one_ to ? ToTemporalDate(_one_). + 5. Set _two_ to ? ToTemporalDate(_two_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +const calendar3 = TemporalHelpers.calendarFieldsIterable(); +calendar1.dateUntil( + { year: 2000, month: 5, day: 2, calendar: calendar2 }, + { year: 2005, month: 6, day: 3, calendar: calendar3 }, +); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.sameValue(calendar3.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); +assert.compareArray(calendar3.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar3.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-temporal-object.js new file mode 100644 index 000000000000..999db10664d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-temporal-object.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.dateuntil steps 4–5: + 4. Set _one_ to ? ToTemporalDate(_one_). + 5. Set _two_ to ? ToTemporalDate(_two_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.dateUntil( + { year: 2000, month: 5, day: 2, calendar: temporalObject }, + { year: 2005, month: 6, day: 3, calendar: temporalObject }, + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..676306605039 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largestunit-plurals-accepted.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 12); +const calendar = new Temporal.Calendar("iso8601"); +const validUnits = [ + "year", + "month", + "week", + "day", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => calendar.dateUntil(earlier, later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/length.js new file mode 100644 index 000000000000..22d2b1063f9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dateUntil, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/name.js new file mode 100644 index 000000000000..7b3135ecc02a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil.name is "dateUntil". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dateUntil, "name", { + value: "dateUntil", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/not-a-constructor.js new file mode 100644 index 000000000000..c3b14a2f2813 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: > + Temporal.Calendar.prototype.dateUntil does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.dateUntil(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dateUntil), false, + "isConstructor(Temporal.Calendar.prototype.dateUntil)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/prop-desc.js new file mode 100644 index 000000000000..96f6e8f8df14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: The "dateUntil" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dateUntil, + "function", + "`typeof Calendar.prototype.dateUntil` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dateUntil", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/shell.js index ab8cfa8454a9..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/shell.js @@ -1,4 +1,23 @@ // GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + // file: temporalHelpers.js // Copyright (C) 2021 Igalia, S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. @@ -30,6 +49,29 @@ var TemporalHelpers = { assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); }, + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + /* * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): * @@ -73,17 +115,32 @@ var TemporalHelpers = { }, /* - * assertPlainMonthDay(monthDay, monthCode, day[, description]): + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): * * Shorthand for asserting that each field of a Temporal.PlainMonthDay is * equal to an expected value. (Except the `calendar` property, since callers * may want to assert either object equality with an object they put in there, * or the result of monthDay.calendar.toString().) */ - assertPlainMonthDay(monthDay, monthCode, day, description = "") { + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); }, /* @@ -102,6 +159,18 @@ var TemporalHelpers = { assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); }, + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + /* * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): * @@ -118,6 +187,670 @@ var TemporalHelpers = { assert.sameValue(yearMonth.month, month, `${description} month result`); assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + /* * Check that any calendar-carrying Temporal object has its [[Calendar]] * internal slot read by ToTemporalCalendar, and does not fetch the calendar @@ -161,6 +894,506 @@ var TemporalHelpers = { }); }, + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + /* * specificOffsetTimeZone(): * @@ -189,4 +1422,96 @@ var TemporalHelpers = { } return new SpecificOffsetTimeZone(offsetValue); }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, }; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToLargestTemporalUnit.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToLargestTemporalUnit.js index 71b8013e428b..257f3f1d965d 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToLargestTemporalUnit.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToLargestTemporalUnit.js @@ -15,6 +15,6 @@ let cal = new Temporal.Calendar("iso8601"); "nanosecond"].forEach(function(largestUnit) { assert.throws(RangeError, () => cal.dateUntil("2021-07-16", "2022-03-04", {largestUnit}), 'cal.dateUntil("2021-07-16", "2022-03-04", {largestUnit}) throws a RangeError exception'); -}) +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-type-error-RequireInternalSlot.js deleted file mode 100644 index d115be901286..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,19 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.calendar.prototype.dateuntil -description: Temporal.Calendar.prototype.dateUntil throw TypeError on RequireInternalSlot -info: | - 1. Let calendar be the this value. - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); -let badCal = { dateUntil: cal.dateUntil }; - -assert.throws(TypeError, () => badCal.dateUntil("2021-07-16", "2021-07-17"), - 'badCal.dateUntil("2021-07-16", "2021-07-17") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/year-zero.js new file mode 100644 index 000000000000..e21fbd049925 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/year-zero.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Negative zero, as extended year, is invalid +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 2); +const bad = "-000000-03-14"; + +assert.throws( + RangeError, + () => calendar.dateUntil(bad, date), + "cannot use minus zero as extended date (first argument)" +); + +assert.throws( + RangeError, + () => calendar.dateUntil(date, bad), + "cannot use minus zero as extended date (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js new file mode 100644 index 000000000000..38e12423ab80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.day(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..6771a5c5b4eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.day(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..f0416d816fd8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.day(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..dc5d032d27d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.day(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..f1f2a1aacd6b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.day(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..da2d674f18e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.day(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/basic.js new file mode 100644 index 000000000000..8824d7edd262 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/basic.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Basic tests for day(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 5; +assert.sameValue(iso.day(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.day(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.day(Temporal.PlainMonthDay.from("11-05")), res, "PlainMonthDay"); +assert.sameValue(iso.day({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.day("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.day({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/branding.js index ad85851748d1..2ed97c1d313a 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/branding.js @@ -12,14 +12,16 @@ const day = Temporal.Calendar.prototype.day; assert.sameValue(typeof day, "function"); -assert.throws(TypeError, () => day.call(undefined), "undefined"); -assert.throws(TypeError, () => day.call(null), "null"); -assert.throws(TypeError, () => day.call(true), "true"); -assert.throws(TypeError, () => day.call(""), "empty string"); -assert.throws(TypeError, () => day.call(Symbol()), "symbol"); -assert.throws(TypeError, () => day.call(1), "1"); -assert.throws(TypeError, () => day.call({}), "plain object"); -assert.throws(TypeError, () => day.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => day.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => day.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => day.apply(null, args), "null"); +assert.throws(TypeError, () => day.apply(true, args), "true"); +assert.throws(TypeError, () => day.apply("", args), "empty string"); +assert.throws(TypeError, () => day.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => day.apply(1, args), "1"); +assert.throws(TypeError, () => day.apply({}, args), "plain object"); +assert.throws(TypeError, () => day.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => day.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/builtin.js new file mode 100644 index 000000000000..f3a6ae8533cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + Tests that Temporal.Calendar.prototype.day + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.day), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.day), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.day), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.day.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..496d6af5ac09 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.day({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-fields-iterable.js new file mode 100644 index 000000000000..878618d19fd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.day step 4: + 4. Return ? ISODay(_dateOrDateTime_). + sec-temporal-isoday step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(calendar, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.day({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-temporal-object.js new file mode 100644 index 000000000000..2f6a3c682029 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.day step 4: + 4. Return ? ISODay(_dateOrDateTime_). + sec-temporal-isoday step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.day({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date-time.js index 87b6d9feef55..469b7baa5a03 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date-time.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date-time.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.day -description: Temporal.Calendar.prototype.day will take PlainDateTime and return +description: > + Temporal.Calendar.prototype.day will take PlainDateTime and return the value of the day. info: | 5. Return ! ISODay(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date.js index 3f789475a204..35840d9e5b9d 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.day -description: Temporal.Calendar.prototype.day will take PlainDate and return +description: > + Temporal.Calendar.prototype.day will take PlainDate and return the value of the day. info: | 5. Return ! ISODay(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..65411f306d87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.day +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.day({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.day({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/length.js new file mode 100644 index 000000000000..775613ee78d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Temporal.Calendar.prototype.day.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.day, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/month-day.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/month-day.js index 09e7f5dc7070..b39787e9317e 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/month-day.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/month-day.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.day -description: Temporal.Calendar.prototype.day will take PlainMonthDay and return +description: > + Temporal.Calendar.prototype.day will take PlainMonthDay and return the value of the day. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/name.js new file mode 100644 index 000000000000..0c8d62450573 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Temporal.Calendar.prototype.day.name is "day". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.day, "name", { + value: "day", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/not-a-constructor.js new file mode 100644 index 000000000000..fe3072332d89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + Temporal.Calendar.prototype.day does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.day(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.day), false, + "isConstructor(Temporal.Calendar.prototype.day)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/prop-desc.js new file mode 100644 index 000000000000..78410ff8f41e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: The "day" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.day, + "function", + "`typeof Calendar.prototype.day` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "day", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/string.js index 5ae929204b7a..9a958a8b9316 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/string.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.day -description: Temporal.Calendar.prototype.day will take ISO8601 string and return +description: > + Temporal.Calendar.prototype.day will take ISO8601 string and return the value of the day. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-range-error-ToTemporalDate.js index 8dbbd6e828a7..2a2d6fc025a5 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-range-error-ToTemporalDate.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.day -description: Temporal.Calendar.prototype.day throws RangeError on +description: > + Temporal.Calendar.prototype.day throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index d2abaecbadce..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.calendar.prototype.day -description: Temporal.Calendar.prototype.day throws TypeError on RequireInternalSlot if object has no internal slot. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { day: cal.day } -assert.throws(TypeError, () => badCal.day("2021-03-04"), - 'badCal.day("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/year-zero.js new file mode 100644 index 000000000000..5c8e46cd1499 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.day(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js new file mode 100644 index 000000000000..281f91171389 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..8a363399fe14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..8514f362e475 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dayOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..5a78f2fc9522 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.dayOfWeek(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..05d72ccd2c73 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dayOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..d60091403691 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.dayOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/basic.js new file mode 100644 index 000000000000..e74758fa0eb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Basic tests for dayOfWeek(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 6; +assert.sameValue(iso.dayOfWeek(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.dayOfWeek(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.dayOfWeek({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.dayOfWeek("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.dayOfWeek({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/branding.js index 4ecd420057fc..3eb3a92638ac 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/branding.js @@ -12,14 +12,16 @@ const dayOfWeek = Temporal.Calendar.prototype.dayOfWeek; assert.sameValue(typeof dayOfWeek, "function"); -assert.throws(TypeError, () => dayOfWeek.call(undefined), "undefined"); -assert.throws(TypeError, () => dayOfWeek.call(null), "null"); -assert.throws(TypeError, () => dayOfWeek.call(true), "true"); -assert.throws(TypeError, () => dayOfWeek.call(""), "empty string"); -assert.throws(TypeError, () => dayOfWeek.call(Symbol()), "symbol"); -assert.throws(TypeError, () => dayOfWeek.call(1), "1"); -assert.throws(TypeError, () => dayOfWeek.call({}), "plain object"); -assert.throws(TypeError, () => dayOfWeek.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => dayOfWeek.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => dayOfWeek.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dayOfWeek.apply(null, args), "null"); +assert.throws(TypeError, () => dayOfWeek.apply(true, args), "true"); +assert.throws(TypeError, () => dayOfWeek.apply("", args), "empty string"); +assert.throws(TypeError, () => dayOfWeek.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dayOfWeek.apply(1, args), "1"); +assert.throws(TypeError, () => dayOfWeek.apply({}, args), "plain object"); +assert.throws(TypeError, () => dayOfWeek.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dayOfWeek.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/builtin.js new file mode 100644 index 000000000000..bd31bbd7440f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + Tests that Temporal.Calendar.prototype.dayOfWeek + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.dayOfWeek), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dayOfWeek), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dayOfWeek), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dayOfWeek.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..e79f8f7c6891 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.dayOfWeek({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-fields-iterable.js new file mode 100644 index 000000000000..844511f85490 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.dayofweek step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.dayOfWeek({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-temporal-object.js new file mode 100644 index 000000000000..a9f12061eea9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.dayofweek step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.dayOfWeek({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..bf25784b40dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dayofweek +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.dayOfWeek({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.dayOfWeek({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/length.js new file mode 100644 index 000000000000..68bc41673eb6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Temporal.Calendar.prototype.dayOfWeek.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dayOfWeek, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/name.js new file mode 100644 index 000000000000..eefb875e818b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Temporal.Calendar.prototype.dayOfWeek.name is "dayOfWeek". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dayOfWeek, "name", { + value: "dayOfWeek", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/not-a-constructor.js new file mode 100644 index 000000000000..53f48cf4e28e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + Temporal.Calendar.prototype.dayOfWeek does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.dayOfWeek(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dayOfWeek), false, + "isConstructor(Temporal.Calendar.prototype.dayOfWeek)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date-time.js index 89814c3c07e8..06e9c5ebfa25 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date-time.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date-time.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.dayofweek -description: Temporal.Calendar.prototype.dayOfWeek will take Temporal.PlainDateTime objects +description: > + Temporal.Calendar.prototype.dayOfWeek will take Temporal.PlainDateTime objects and return the day of week. info: | 5. Return 𝔽(! ToISODayOfWeek(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date.js index f334763ca152..8375c0c362bf 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.dayofweek -description: Temporal.Calendar.prototype.dayOfWeek will take Temporal.PlainDate objects +description: > + Temporal.Calendar.prototype.dayOfWeek will take Temporal.PlainDate objects and return the day of week. info: | 5. Return 𝔽(! ToISODayOfWeek(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/prop-desc.js new file mode 100644 index 000000000000..3b8516bf3a1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: The "dayOfWeek" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dayOfWeek, + "function", + "`typeof Calendar.prototype.dayOfWeek` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dayOfWeek", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/string.js index d1d86c91ed8f..c4ea8da784d1 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/string.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.dayofweek -description: Temporal.Calendar.prototype.dayOfWeek will take ISO8601 string +description: > + Temporal.Calendar.prototype.dayOfWeek will take ISO8601 string and return the day of week. info: | 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-range-error-ToTemporalDate.js index d67ddd3c058e..5b67bc8256ce 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-range-error-ToTemporalDate.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.dayOfWeek -description: Temporal.Calendar.prototype.dayOfWeek throws RangeError on +description: > + Temporal.Calendar.prototype.dayOfWeek throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index 8744963cad3f..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.calendar.prototype.dayOfWeek -description: Temporal.Calendar.prototype.dayOfWeek throws TypeError - when the internal lot is not presented. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { dayOfWeek: cal.dayOfWeek } -assert.throws(TypeError, () => badCal.dayOfWeek("2021-03-04"), - 'badCal.dayOfWeek("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/year-zero.js new file mode 100644 index 000000000000..4813d393bc9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.dayOfWeek(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js new file mode 100644 index 000000000000..ffab72c98ef4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..8f0677f5f973 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..873c5f6c9965 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dayOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..e531f39ff18e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.dayOfYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..e07196275af1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dayOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..9887a5aee87f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.dayOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/basic.js new file mode 100644 index 000000000000..9af5dd2cfda7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Basic tests for dayOfYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 309; +assert.sameValue(iso.dayOfYear(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.dayOfYear(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.dayOfYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.dayOfYear("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.dayOfYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/branding.js index f10eb5435fa4..629ef89b1ae8 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/branding.js @@ -12,14 +12,16 @@ const dayOfYear = Temporal.Calendar.prototype.dayOfYear; assert.sameValue(typeof dayOfYear, "function"); -assert.throws(TypeError, () => dayOfYear.call(undefined), "undefined"); -assert.throws(TypeError, () => dayOfYear.call(null), "null"); -assert.throws(TypeError, () => dayOfYear.call(true), "true"); -assert.throws(TypeError, () => dayOfYear.call(""), "empty string"); -assert.throws(TypeError, () => dayOfYear.call(Symbol()), "symbol"); -assert.throws(TypeError, () => dayOfYear.call(1), "1"); -assert.throws(TypeError, () => dayOfYear.call({}), "plain object"); -assert.throws(TypeError, () => dayOfYear.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => dayOfYear.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => dayOfYear.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dayOfYear.apply(null, args), "null"); +assert.throws(TypeError, () => dayOfYear.apply(true, args), "true"); +assert.throws(TypeError, () => dayOfYear.apply("", args), "empty string"); +assert.throws(TypeError, () => dayOfYear.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dayOfYear.apply(1, args), "1"); +assert.throws(TypeError, () => dayOfYear.apply({}, args), "plain object"); +assert.throws(TypeError, () => dayOfYear.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dayOfYear.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/builtin.js new file mode 100644 index 000000000000..78d992e12519 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + Tests that Temporal.Calendar.prototype.dayOfYear + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.dayOfYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dayOfYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dayOfYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dayOfYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..a20cc4449e3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.dayOfYear({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-fields-iterable.js new file mode 100644 index 000000000000..fb91b200fef4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.dayofyear step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.dayOfYear({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-temporal-object.js new file mode 100644 index 000000000000..565c10a09d3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.dayofyear step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.dayOfYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..69b2375eab0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dayofyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.dayOfYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.dayOfYear({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/length.js new file mode 100644 index 000000000000..7453a909a9ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Temporal.Calendar.prototype.dayOfYear.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dayOfYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/name.js new file mode 100644 index 000000000000..4532e747a115 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Temporal.Calendar.prototype.dayOfYear.name is "dayOfYear". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dayOfYear, "name", { + value: "dayOfYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/not-a-constructor.js new file mode 100644 index 000000000000..14da7c69f044 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + Temporal.Calendar.prototype.dayOfYear does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.dayOfYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dayOfYear), false, + "isConstructor(Temporal.Calendar.prototype.dayOfYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date-time.js index 26708f0828ba..fdefe2b25fa5 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date-time.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date-time.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.dayofyear -description: Temporal.Calendar.prototype.dayOfYear will take PlainDateTime object and +description: > + Temporal.Calendar.prototype.dayOfYear will take PlainDateTime object and return the day of year. info: | 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date.js index 944300eb677e..6e7258b6424b 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.dayofyear -description: Temporal.Calendar.prototype.dayOfYear will take PlainDate object and +description: > + Temporal.Calendar.prototype.dayOfYear will take PlainDate object and return the day of year. info: | 5. Return 𝔽(! ToISODayOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/prop-desc.js new file mode 100644 index 000000000000..a63b783bd423 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: The "dayOfYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dayOfYear, + "function", + "`typeof Calendar.prototype.dayOfYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dayOfYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/string.js index 121c7f2ca4e5..043a9bd747a5 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/string.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.dayofyear -description: Temporal.Calendar.prototype.dayOfYear will take ISO8601 string and +description: > + Temporal.Calendar.prototype.dayOfYear will take ISO8601 string and return the day of year. info: | 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-range-error-ToTemporalDate.js index 7b84de7e52f5..e74f6e5ad2ce 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-range-error-ToTemporalDate.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.dayOfYear -description: Temporal.Calendar.prototype.dayOfYear throws RangeError on +description: > + Temporal.Calendar.prototype.dayOfYear throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index 4167c994ca4e..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.calendar.prototype.dayOfYear -description: Temporal.Calendar.prototype.dayOfYear throws TypeError - when the internal lot is not presented. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { dayOfYear: cal.dayOfYear } -assert.throws(TypeError, () => badCal.dayOfYear("2021-03-04"), - 'badCal.dayOfYear("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/year-zero.js new file mode 100644 index 000000000000..dd6c5564e7f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.dayOfYear(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js new file mode 100644 index 000000000000..77af97c445f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..a7d149894484 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..9b4622874c3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInMonth(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..94dfa4e8209a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.daysInMonth(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..d5ba63f6b62d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInMonth(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..081fd7065781 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.daysInMonth(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/basic.js new file mode 100644 index 000000000000..6a6a95db1a14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Basic tests for daysInMonth(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 30; +assert.sameValue(iso.daysInMonth(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.daysInMonth(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.daysInMonth({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.daysInMonth("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.daysInMonth({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/branding.js index 7fb17163ad7e..49cb03ffef17 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/branding.js @@ -12,14 +12,16 @@ const daysInMonth = Temporal.Calendar.prototype.daysInMonth; assert.sameValue(typeof daysInMonth, "function"); -assert.throws(TypeError, () => daysInMonth.call(undefined), "undefined"); -assert.throws(TypeError, () => daysInMonth.call(null), "null"); -assert.throws(TypeError, () => daysInMonth.call(true), "true"); -assert.throws(TypeError, () => daysInMonth.call(""), "empty string"); -assert.throws(TypeError, () => daysInMonth.call(Symbol()), "symbol"); -assert.throws(TypeError, () => daysInMonth.call(1), "1"); -assert.throws(TypeError, () => daysInMonth.call({}), "plain object"); -assert.throws(TypeError, () => daysInMonth.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => daysInMonth.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => daysInMonth.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => daysInMonth.apply(null, args), "null"); +assert.throws(TypeError, () => daysInMonth.apply(true, args), "true"); +assert.throws(TypeError, () => daysInMonth.apply("", args), "empty string"); +assert.throws(TypeError, () => daysInMonth.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => daysInMonth.apply(1, args), "1"); +assert.throws(TypeError, () => daysInMonth.apply({}, args), "plain object"); +assert.throws(TypeError, () => daysInMonth.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => daysInMonth.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/builtin.js new file mode 100644 index 000000000000..b13e45565958 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + Tests that Temporal.Calendar.prototype.daysInMonth + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.daysInMonth), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.daysInMonth), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.daysInMonth), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.daysInMonth.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..f11712fa6fe6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.daysInMonth({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-fields-iterable.js new file mode 100644 index 000000000000..14e3c8580f5b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.daysinmonth step 4.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.daysInMonth({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-temporal-object.js new file mode 100644 index 000000000000..5d510c28d271 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.daysinmonth step 4.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.daysInMonth({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..674c20907535 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.daysinmonth +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.daysInMonth({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.daysInMonth({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/length.js new file mode 100644 index 000000000000..8216ecf05529 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Temporal.Calendar.prototype.daysInMonth.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.daysInMonth, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/name.js new file mode 100644 index 000000000000..c2e238c75690 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Temporal.Calendar.prototype.daysInMonth.name is "daysInMonth". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.daysInMonth, "name", { + value: "daysInMonth", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/not-a-constructor.js new file mode 100644 index 000000000000..7e0029ff33fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + Temporal.Calendar.prototype.daysInMonth does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.daysInMonth(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.daysInMonth), false, + "isConstructor(Temporal.Calendar.prototype.daysInMonth)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date-time.js index 864a905572eb..a220cde06e11 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date-time.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date-time.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysinmonth -description: Temporal.Calendar.prototype.daysInMonth will take Temporal.PlainDateTime object +description: > + Temporal.Calendar.prototype.daysInMonth will take Temporal.PlainDateTime object and return the number of days in that month. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slots, then diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date.js index b3a66eea07ad..743b5f48d18f 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysinmonth -description: Temporal.Calendar.prototype.daysInMonth will take Temporal.PlainDate object +description: > + Temporal.Calendar.prototype.daysInMonth will take Temporal.PlainDate object and return the number of days in that month. info: | 5. Return 𝔽(! ISODaysInMonth(temporalDateLike.[[ISOYear]], temporalDateLike.[[ISOMonth]])). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/prop-desc.js new file mode 100644 index 000000000000..182387a01f2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: The "daysInMonth" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.daysInMonth, + "function", + "`typeof Calendar.prototype.daysInMonth` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "daysInMonth", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/string.js index 1ffb52ddff7d..e630334f5719 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/string.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysinmonth -description: Temporal.Calendar.prototype.daysInMonth will take ISO8601 string +description: > + Temporal.Calendar.prototype.daysInMonth will take ISO8601 string and return the number of days in that month. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-range-error-ToTemporalDate.js index d598fd3af50b..78211a0f83f0 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-range-error-ToTemporalDate.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysInMonth -description: Temporal.Calendar.prototype.daysInMonth throws RangeError on +description: > + Temporal.Calendar.prototype.daysInMonth throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index da76b3b1248d..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.calendar.prototype.daysInMonth -description: Temporal.Calendar.prototype.daysInMonth throws TypeError - when the internal lot is not presented. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { daysInMonth: cal.daysInMonth } -assert.throws(TypeError, () => badCal.daysInMonth("2021-03-04"), - 'badCal.daysInMonth("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/year-zero.js new file mode 100644 index 000000000000..72dad31bd3c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.daysInMonth(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js new file mode 100644 index 000000000000..209fcecb37a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..819baf1222b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..c16a6968884e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..9483b078d236 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.daysInWeek(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..238cea6ec6dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..d4219f3bad48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.daysInWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/basic.js new file mode 100644 index 000000000000..ab30cd5b02bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Basic tests for daysInWeek(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 7; +assert.sameValue(iso.daysInWeek(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.daysInWeek(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.daysInWeek({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.daysInWeek("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.daysInWeek({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/branding.js index 738805888b1c..ef16b220e68f 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/branding.js @@ -12,14 +12,16 @@ const daysInWeek = Temporal.Calendar.prototype.daysInWeek; assert.sameValue(typeof daysInWeek, "function"); -assert.throws(TypeError, () => daysInWeek.call(undefined), "undefined"); -assert.throws(TypeError, () => daysInWeek.call(null), "null"); -assert.throws(TypeError, () => daysInWeek.call(true), "true"); -assert.throws(TypeError, () => daysInWeek.call(""), "empty string"); -assert.throws(TypeError, () => daysInWeek.call(Symbol()), "symbol"); -assert.throws(TypeError, () => daysInWeek.call(1), "1"); -assert.throws(TypeError, () => daysInWeek.call({}), "plain object"); -assert.throws(TypeError, () => daysInWeek.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => daysInWeek.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => daysInWeek.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => daysInWeek.apply(null, args), "null"); +assert.throws(TypeError, () => daysInWeek.apply(true, args), "true"); +assert.throws(TypeError, () => daysInWeek.apply("", args), "empty string"); +assert.throws(TypeError, () => daysInWeek.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => daysInWeek.apply(1, args), "1"); +assert.throws(TypeError, () => daysInWeek.apply({}, args), "plain object"); +assert.throws(TypeError, () => daysInWeek.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => daysInWeek.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/builtin.js new file mode 100644 index 000000000000..2132e3beaf1f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: > + Tests that Temporal.Calendar.prototype.daysInWeek + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.daysInWeek), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.daysInWeek), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.daysInWeek), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.daysInWeek.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..1c6aa7072616 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.daysInWeek({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-fields-iterable.js new file mode 100644 index 000000000000..a3524e383eff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.daysinweek step 4: + 4. Perform ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.daysInWeek({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-temporal-object.js new file mode 100644 index 000000000000..5bf65e14c13e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.daysinweek step 4: + 4. Perform ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.daysInWeek({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..9725ae948dd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.daysinweek +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.daysInWeek({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.daysInWeek({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/length.js new file mode 100644 index 000000000000..34672365726f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Temporal.Calendar.prototype.daysInWeek.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.daysInWeek, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/name.js new file mode 100644 index 000000000000..404f287f0c8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Temporal.Calendar.prototype.daysInWeek.name is "daysInWeek". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.daysInWeek, "name", { + value: "daysInWeek", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/not-a-constructor.js new file mode 100644 index 000000000000..9b7a8fb3ea78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: > + Temporal.Calendar.prototype.daysInWeek does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.daysInWeek(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.daysInWeek), false, + "isConstructor(Temporal.Calendar.prototype.daysInWeek)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/prop-desc.js new file mode 100644 index 000000000000..1354d32a7b2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: The "daysInWeek" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.daysInWeek, + "function", + "`typeof Calendar.prototype.daysInWeek` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "daysInWeek", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/string.js index 76cbc9c07b09..1ad83b4e5742 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/string.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysinweeks -description: Temporal.Calendar.prototype.daysInWeek will take valid ISO8601 string +description: > + Temporal.Calendar.prototype.daysInWeek will take valid ISO8601 string and return 7. info: | 4. Perform ? ToTemporalDate(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-range-error-ToTemporalDate.js index 46ca76ef8825..def7d2aa74ff 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-range-error-ToTemporalDate.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysInWeek -description: Temporal.Calendar.prototype.daysInWeek throws RangeError on +description: > + Temporal.Calendar.prototype.daysInWeek throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index 915fe2c633da..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.calendar.prototype.daysInWeek -description: Temporal.Calendar.prototype.daysInWeek throws TypeError - when the internal lot is not presented. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { daysInWeek: cal.daysInWeek } -assert.throws(TypeError, () => badCal.daysInWeek("2021-03-04"), - 'badCal.daysInWeek("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/year-zero.js new file mode 100644 index 000000000000..faa2bf7d6959 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.daysInWeek(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js new file mode 100644 index 000000000000..99b391d43033 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..fb34d2818a40 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..fd6367a9812b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..009dd8890a0b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.daysInYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..8955fc294a1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..29ed0f857c5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.daysInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/basic.js new file mode 100644 index 000000000000..1513e88bdd80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/basic.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Basic tests for daysInYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 365; +assert.sameValue(iso.daysInYear(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.daysInYear(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.daysInYear(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +assert.sameValue(iso.daysInYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.daysInYear("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.daysInYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/branding.js index d4731d136e77..1a31ce8cc47e 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/branding.js @@ -12,14 +12,16 @@ const daysInYear = Temporal.Calendar.prototype.daysInYear; assert.sameValue(typeof daysInYear, "function"); -assert.throws(TypeError, () => daysInYear.call(undefined), "undefined"); -assert.throws(TypeError, () => daysInYear.call(null), "null"); -assert.throws(TypeError, () => daysInYear.call(true), "true"); -assert.throws(TypeError, () => daysInYear.call(""), "empty string"); -assert.throws(TypeError, () => daysInYear.call(Symbol()), "symbol"); -assert.throws(TypeError, () => daysInYear.call(1), "1"); -assert.throws(TypeError, () => daysInYear.call({}), "plain object"); -assert.throws(TypeError, () => daysInYear.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => daysInYear.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => daysInYear.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => daysInYear.apply(null, args), "null"); +assert.throws(TypeError, () => daysInYear.apply(true, args), "true"); +assert.throws(TypeError, () => daysInYear.apply("", args), "empty string"); +assert.throws(TypeError, () => daysInYear.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => daysInYear.apply(1, args), "1"); +assert.throws(TypeError, () => daysInYear.apply({}, args), "plain object"); +assert.throws(TypeError, () => daysInYear.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => daysInYear.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/builtin.js new file mode 100644 index 000000000000..868718c23581 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + Tests that Temporal.Calendar.prototype.daysInYear + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.daysInYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.daysInYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.daysInYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.daysInYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..0e827bd72a78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.daysInYear({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-fields-iterable.js new file mode 100644 index 000000000000..55ced1ad7fc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.daysinyear step 4: + 4. Let _year_ be ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.daysInYear({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-temporal-object.js new file mode 100644 index 000000000000..dc8e34d663d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.daysinyear step 4: + 4. Let _year_ be ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.daysInYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..3338d8dd6d01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.daysinyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.daysInYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.daysInYear({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/length.js new file mode 100644 index 000000000000..a201a6f09207 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Temporal.Calendar.prototype.daysInYear.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.daysInYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/name.js new file mode 100644 index 000000000000..228cb0695116 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Temporal.Calendar.prototype.daysInYear.name is "daysInYear". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.daysInYear, "name", { + value: "daysInYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/not-a-constructor.js new file mode 100644 index 000000000000..c6137982b62d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + Temporal.Calendar.prototype.daysInYear does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.daysInYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.daysInYear), false, + "isConstructor(Temporal.Calendar.prototype.daysInYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date-time.js index feb7fd73024f..d5392a82e1bb 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date-time.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date-time.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysinyear -description: Temporal.Calendar.prototype.daysInYear will take PlainDateTime and return +description: > + Temporal.Calendar.prototype.daysInYear will take PlainDateTime and return the number of days in a year. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date.js index b62772a4bc19..ce27f5436265 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysinyear -description: Temporal.Calendar.prototype.daysInYear will take PlainDate and return +description: > + Temporal.Calendar.prototype.daysInYear will take PlainDate and return the number of days in a year. info: | 5. Return 𝔽(! ISODaysInYear(temporalDateLike.[[ISOYear]])). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/prop-desc.js new file mode 100644 index 000000000000..0d6402f3f567 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: The "daysInYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.daysInYear, + "function", + "`typeof Calendar.prototype.daysInYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "daysInYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/string.js index d78d6a941ece..28dd13f9f2c9 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/string.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysinyear -description: Temporal.Calendar.prototype.daysInYear will take PlainDate and return +description: > + Temporal.Calendar.prototype.daysInYear will take PlainDate and return the number of days in a year. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-range-error-ToTemporalDate.js index f5960f9a7b2c..4d9287696944 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-range-error-ToTemporalDate.js @@ -3,7 +3,8 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.calendar.prototype.daysInYear -description: Temporal.Calendar.prototype.daysInYear throws RangeError on +description: > + Temporal.Calendar.prototype.daysInYear throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike does diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index da4da845dac9..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.calendar.prototype.daysInYear -description: Temporal.Calendar.prototype.daysInYear throws TypeError - when the internal lot is not presented. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { daysInYear: cal.daysInYear } -assert.throws(TypeError, () => badCal.daysInYear("2021-03-04"), - 'badCal.daysInYear("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/year-zero.js new file mode 100644 index 000000000000..a5a1616412b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.daysInYear(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-iterable-not-array.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-iterable-not-array.js new file mode 100644 index 000000000000..069ea56dfa48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-iterable-not-array.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: A non-Array iterable passed as the argument is exhausted +info: | + sec-temporal.calendar.prototype.fields step 4: + 4. Let _fieldNames_ be ? IterableToList(_fields_). +includes: [compareArray.js] +features: [Temporal] +---*/ + +const fieldNames = ["day", "month", "monthCode", "year"]; +const iterable = { + iteratorExhausted: false, + *[Symbol.iterator]() { + yield* fieldNames; + this.iteratorExhausted = true; + }, +}; + +const calendar = new Temporal.Calendar("iso8601"); +const result = calendar.fields(iterable); + +assert.compareArray(result, fieldNames); +assert(iterable.iteratorExhausted); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-duplicate-keys.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-duplicate-keys.js new file mode 100644 index 000000000000..9f9df6d105ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-duplicate-keys.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: Duplicate fields are not allowed in the argument to Calendar.prototype.fields +info: | + sec-temporal.calendar.prototype.fields step 7.b.iii: + iii. If _fieldNames_ contains _nextValue_, then + 1. Let _completion_ be ThrowCompletion(a newly created *RangeError* object). + 2. Return ? IteratorClose(_iteratorRecord_, _completion_). +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +assert.throws(RangeError, () => calendar.fields(["day", "month", "day"])); +assert.throws(RangeError, () => calendar.fields(["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", "year"])); + +const manyFields = { + count: 0 +}; + +manyFields[Symbol.iterator] = function*() { + while (this.count++ < 100) yield "year"; +}; + +assert.throws(RangeError, () => calendar.fields(manyFields), "Rejected duplicate values"); +assert.sameValue(manyFields.count, 2, "Rejected first duplicate value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-invalid-keys.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-invalid-keys.js new file mode 100644 index 000000000000..96ff63c8b706 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-invalid-keys.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: Calendar.prototype.fields rejects input field names that are not singular names of temporal units +info: | + sec-temporal.calendar.prototype.fields step 7.b.ii: + 7. Repeat, while next is not false, + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + ii. If Type(nextValue) is not String, then + 1. Let completion be ThrowCompletion(a newly created TypeError object). + 2. Return ? IteratorClose(iteratorRecord, completion). + sec-temporal.calendar.prototype.fields step 7.b.iv: + iv. If _nextValue_ is not one of *"year"*, *"month"*, *"monthCode"*, *"day"*, *"hour"*, *"minute"*, *"second"*, *"millisecond"*, *"microsecond"*, *"nanosecond"*, then + 1. Let _completion_ be ThrowCompletion(a newly created *RangeError* object). + 2. Return ? IteratorClose(_iteratorRecord_, _completion_). + +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +assert.throws(TypeError, () => calendar.fields([1])); +assert.throws(TypeError, () => calendar.fields([1n])); +assert.throws(TypeError, () => calendar.fields([Symbol('foo')])); +assert.throws(TypeError, () => calendar.fields([true])); +assert.throws(TypeError, () => calendar.fields([null])); +assert.throws(TypeError, () => calendar.fields([{}])); +assert.throws(TypeError, () => calendar.fields([undefined])); +assert.throws(TypeError, () => calendar.fields(["day", 1])); +assert.throws(RangeError, () => calendar.fields(["month", "days"])); +assert.throws(RangeError, () => calendar.fields(["days"])); +assert.throws(RangeError, () => calendar.fields(["people"])); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/builtin.js new file mode 100644 index 000000000000..1f9afa6b205a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: > + Tests that Temporal.Calendar.prototype.fields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.fields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.fields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.fields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.fields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/length.js new file mode 100644 index 000000000000..5c91ef06399b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: Temporal.Calendar.prototype.fields.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.fields, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/long-input.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/long-input.js index 88ce6518215c..34567efc8c9e 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/long-input.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/long-input.js @@ -5,30 +5,46 @@ /*--- esid: sec-temporal.calendar.prototype.fields description: > - Temporal.Calendar.prototype.fields will take iterable of any size and any string - and return Array of the same content. + Temporal.Calendar.prototype.fields will throw when its input iterable yields an + invalid field. info: | ## 12.4.21 Temporal.Calendar.prototype.fields ( fields ) 1. Let calendar be the this value. 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - 3. Assert: calendar.[[Identifier]] is "iso8601". - 4. Let fieldNames be ? IterableToListOfType(fields, « String »). - 5. Return ! CreateArrayFromList(fieldNames). + 4. Let iteratorRecord be ? Getiterator(fields, sync). + 5. Let fieldNames be a new empty List. + 6. Let next be true. + 7. Repeat, while next is not false, + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + iv. If nextValue is not one of "year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", then + 1. Let completion be ThrowCompletion(a newly created RangeError object). + 2. Return ? IteratorClose(iteratorRecord, completion). features: [Symbol, Symbol.iterator, Temporal, computed-property-names, generators] -includes: [compareArray.js] ---*/ let cal = new Temporal.Calendar("iso8601") +let i = 0; const fields = { *[Symbol.iterator]() { - let i = 0; - while (i++ < 1000001) { - yield "garbage " + i; - } + // The first three are valid values + yield "year"; + i++; + yield "month"; + i++; + yield "monthCode"; + i++; + // The fourth one is wrong and should throw after the next line. + yield "garbage"; + // The following three lines should not be reached if the implemention + // correctly check the previous line. + i++; + yield "hour"; + i++; } } -assert( - compareArray(cal.fields(fields), Array.from(fields)), - 'compareArray(cal.fields(fields), Array.from(fields)) must return true' -); +assert.throws(RangeError, () => cal.fields(fields), "Garbage content"); +// stop after the third one. +assert.sameValue(i, 3); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/name.js new file mode 100644 index 000000000000..241eafa9dea8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: Temporal.Calendar.prototype.fields.name is "fields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.fields, "name", { + value: "fields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/non-string-element-throws.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/non-string-element-throws.js new file mode 100644 index 000000000000..2ebacd53dc91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/non-string-element-throws.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: TypeError thrown if the input iterable yields a non-String value +info: | + sec-temporal.calendar.prototype.fields step 5: + 5. For each element _fieldName_ of _fieldNames_, do + a. If Type(_fieldName_) is not String, throw a *TypeError* exception. +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +[true, 3, 3n, {}, () => {}, Symbol(), undefined, null].forEach((element) => { + assert.throws(TypeError, () => calendar.fields([element]), "bad input to calendar.fields()"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/not-a-constructor.js new file mode 100644 index 000000000000..12bb2629fa04 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: > + Temporal.Calendar.prototype.fields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.fields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.fields), false, + "isConstructor(Temporal.Calendar.prototype.fields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/prop-desc.js new file mode 100644 index 000000000000..6f370b544ef5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: The "fields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.fields, + "function", + "`typeof Calendar.prototype.fields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "fields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/repeated-throw.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/repeated-throw.js new file mode 100644 index 000000000000..015ce35d5a7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/repeated-throw.js @@ -0,0 +1,59 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: > + Temporal.Calendar.prototype.fields will throw if its input iterable yields + the same value twice. +info: | + ## 12.4.21 Temporal.Calendar.prototype.fields ( fields ) + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 4. Let iteratorRecord be ? Getiterator(fields, sync). + 5. Let fieldNames be a new empty List. + 6. Let next be true. + 7. Repeat, while next is not false, + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + iii. If fieldNames contains nextValue, then + 1. Let completion be ThrowCompletion(a newly created RangeError object). + 2. Return ? IteratorClose(iteratorRecord, completion). +features: [Symbol, Symbol.iterator, Temporal, computed-property-names, generators] +---*/ +let cal = new Temporal.Calendar("iso8601") +let i = 0; +const fields = { + *[Symbol.iterator]() { + yield "month"; + i++; + yield "year"; + i++; + yield "year"; + i++; + } +} +assert.throws( + RangeError, () => cal.fields(fields), "repeated valid value should throw"); +assert.sameValue(i, 2, "Should stop at 2"); + +// Test all valid value will throw while repeate +[ "nanosecond", "microsecond", "millisecond", "second", + "minute", "hour", "day", "monthCode", "month", "year" ].forEach((f) => { + i = 0; + const fields2 = { + *[Symbol.iterator]() { + yield f; + i++; + yield f; + i++; + } + } + assert.throws( + RangeError, () => cal.fields(fields2), "repeated valid value should throw"); + assert.sameValue(i, 1, "Should stop at 1"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/reverse.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/reverse.js new file mode 100644 index 000000000000..4e2b1bbb8333 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/reverse.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: > + Temporal.Calendar.prototype.fields will return the iterable in array if all + input are valid regardless of it's order. +info: | + ## 12.4.21 Temporal.Calendar.prototype.fields ( fields ) + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 4. Let iteratorRecord be ? Getiterator(fields, sync). + 5. Let fieldNames be a new empty List. + 6. Let next be true. + 7. Repeat, while next is not false, + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + iv. If nextValue is not one of "year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", then + 1. Let completion be ThrowCompletion(a newly created RangeError object). + 2. Return ? IteratorClose(iteratorRecord, completion). +features: [Symbol, Symbol.iterator, Temporal, computed-property-names, generators] +includes: [compareArray.js] +---*/ +let cal = new Temporal.Calendar("iso8601") +const fields = { + *[Symbol.iterator]() { + yield "nanosecond"; + yield "microsecond"; + yield "millisecond"; + yield "second"; + yield "minute"; + yield "hour"; + yield "day"; + yield "monthCode"; + yield "month"; + yield "year"; + } +} +assert.compareArray(cal.fields(fields), Array.from(fields), + 'valid fields should be supported even if they are in reversed order of the spec'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js new file mode 100644 index 000000000000..b07659dee460 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..0e221b58ac99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js new file mode 100644 index 000000000000..c16195115837 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: An ISO 8601 date string should be converted as input +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return ! IsISOLeapYear(temporalDateLike.[[ISOYear]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.inLeapYear("2019-03-18"), false); +assert.sameValue(cal.inLeapYear("2020-03-18"), true); + +assert.sameValue(cal.inLeapYear("+002023-03-18"), false); +assert.sameValue(cal.inLeapYear("+002024-03-18"), true); + +assert.sameValue(cal.inLeapYear("2019-03-18T13:00:00+00:00[UTC]"), false); +assert.sameValue(cal.inLeapYear("2020-12-31T23:59:59+00:00[UTC]"), true); + +assert.sameValue(cal.inLeapYear("+002023-03-18T13:00:00+00:00[UTC]"), false); +assert.sameValue(cal.inLeapYear("+002024-03-18T13:00:00+00:00[UTC]"), true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..cb35c7857a80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.inLeapYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..2fc9efa39951 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.inLeapYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..4c49112a6ef9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.inLeapYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..93ef2a19de0b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.inLeapYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js new file mode 100644 index 000000000000..00537280465b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Basic tests for inLeapYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +let res = false; + +assert.sameValue(iso.inLeapYear(new Temporal.PlainDate(1994, 11, 5)), res, "PlainDate"); +assert.sameValue(iso.inLeapYear(new Temporal.PlainDateTime(1994, 11, 5, 8, 15, 30)), res, "PlainDateTime"); +assert.sameValue(iso.inLeapYear(new Temporal.PlainYearMonth(1994, 11)), res, "PlainYearMonth"); +assert.sameValue(iso.inLeapYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.inLeapYear("1994-11-05"), res, "string"); + +res = true; +assert.sameValue(iso.inLeapYear(new Temporal.PlainDate(1996, 7, 15)), res, "PlainDate in leap year"); +assert.sameValue(iso.inLeapYear(new Temporal.PlainDateTime(1996, 7, 15, 5, 30, 13)), res, "PlainDateTime in leap year"); +assert.sameValue(iso.inLeapYear(new Temporal.PlainYearMonth(1996, 7)), res, "PlainYearMonth in leap year"); +assert.sameValue(iso.inLeapYear({ year: 1996, month: 7, day: 15 }), res, "property bag in leap year"); +assert.sameValue(iso.inLeapYear("1996-07-15"), res, "string in leap year"); + +assert.throws(TypeError, () => iso.inLeapYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js index 51ff4491f63a..d35fccd40d2a 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js @@ -12,14 +12,16 @@ const inLeapYear = Temporal.Calendar.prototype.inLeapYear; assert.sameValue(typeof inLeapYear, "function"); -assert.throws(TypeError, () => inLeapYear.call(undefined), "undefined"); -assert.throws(TypeError, () => inLeapYear.call(null), "null"); -assert.throws(TypeError, () => inLeapYear.call(true), "true"); -assert.throws(TypeError, () => inLeapYear.call(""), "empty string"); -assert.throws(TypeError, () => inLeapYear.call(Symbol()), "symbol"); -assert.throws(TypeError, () => inLeapYear.call(1), "1"); -assert.throws(TypeError, () => inLeapYear.call({}), "plain object"); -assert.throws(TypeError, () => inLeapYear.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => inLeapYear.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = new Temporal.PlainDate(2021, 3, 4); + +assert.throws(TypeError, () => inLeapYear.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => inLeapYear.call(null, arg), "null"); +assert.throws(TypeError, () => inLeapYear.call(true, arg), "true"); +assert.throws(TypeError, () => inLeapYear.call("", arg), "empty string"); +assert.throws(TypeError, () => inLeapYear.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => inLeapYear.call(1, arg), "1"); +assert.throws(TypeError, () => inLeapYear.call({}, arg), "plain object"); +assert.throws(TypeError, () => inLeapYear.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => inLeapYear.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/builtin.js new file mode 100644 index 000000000000..3c47c3413f6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: > + Tests that Temporal.Calendar.prototype.inLeapYear + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.inLeapYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.inLeapYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.inLeapYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.inLeapYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..e88db6758fd6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.inLeapYear({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-fields-iterable.js new file mode 100644 index 000000000000..fba76ddb5a00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.inleapyear step 4: + 4. Let _year_ be ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.inLeapYear({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-temporal-object.js new file mode 100644 index 000000000000..926ff100798a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.inleapyear step 4: + 4. Let _year_ be ? ISOYear(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.inLeapYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f208b176b0b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.inleapyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.inLeapYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.inLeapYear({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/length.js new file mode 100644 index 000000000000..9ce01a8d9c03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Temporal.Calendar.prototype.inLeapYear.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.inLeapYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/name.js new file mode 100644 index 000000000000..c2ea4e64435d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Temporal.Calendar.prototype.inLeapYear.name is "inLeapYear". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.inLeapYear, "name", { + value: "inLeapYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/not-a-constructor.js new file mode 100644 index 000000000000..df370ec207e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: > + Temporal.Calendar.prototype.inLeapYear does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.inLeapYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.inLeapYear), false, + "isConstructor(Temporal.Calendar.prototype.inLeapYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/prop-desc.js new file mode 100644 index 000000000000..471fc0bf64be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: The "inLeapYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.inLeapYear, + "function", + "`typeof Calendar.prototype.inLeapYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "inLeapYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/year-zero.js new file mode 100644 index 000000000000..bf7c4d923a70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.inLeapYear(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-empty-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-empty-object.js new file mode 100644 index 000000000000..1e1f99c5ba32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-empty-object.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Either argument being an empty object should result in a copy of the other object +includes: [compareArray.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +let calls = 0; +const yearObserver = { + get year() { + calls++; + return 2021; + } +}; + +const result1 = calendar.mergeFields(yearObserver, {}); +assert.sameValue(calls, 1, "property copied"); +assert.compareArray(Object.keys(result1), ["year"]); +assert.sameValue(result1.year, 2021); +assert.sameValue(calls, 1, "result has a data property"); + +calls = 0; +const result2 = calendar.mergeFields({}, yearObserver); +assert.sameValue(calls, 1, "property copied"); +assert.compareArray(Object.keys(result2), ["year"]); +assert.sameValue(result2.year, 2021); +assert.sameValue(calls, 1, "result has a data property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-not-object.js new file mode 100644 index 000000000000..0afda975fc86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-not-object.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Non-object arguments are converted with ToObject and merge their [[OwnPropertyKeys]] +includes: [compareArray.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +assert.throws(TypeError, () => calendar.mergeFields(undefined, {})); +assert.throws(TypeError, () => calendar.mergeFields({}, undefined)); + +assert.throws(TypeError, () => calendar.mergeFields(null, {})); +assert.throws(TypeError, () => calendar.mergeFields({}, null)); + +const boolResult = calendar.mergeFields(true, false); +assert.compareArray(Object.keys(boolResult), [], "Boolean objects have no own property keys"); +assert.sameValue(Object.getPrototypeOf(boolResult), Object.prototype, "plain object returned"); + +const numResult = calendar.mergeFields(3, 4); +assert.compareArray(Object.keys(numResult), [], "Number objects have no own property keys"); +assert.sameValue(Object.getPrototypeOf(boolResult), Object.prototype, "plain object returned"); + +const strResult = calendar.mergeFields("abc", "de"); +assert.compareArray(Object.keys(strResult), ["0", "1", "2"], "String objects have integer indices as own property keys"); +assert.sameValue(strResult["0"], "d"); +assert.sameValue(strResult["1"], "e"); +assert.sameValue(strResult["2"], "c"); +assert.sameValue(Object.getPrototypeOf(boolResult), Object.prototype, "plain object returned"); + +const symResult = calendar.mergeFields(Symbol("foo"), Symbol("bar")); +assert.compareArray(Object.keys(symResult), [], "Symbol objects have no own property keys"); +assert.sameValue(Object.getPrototypeOf(symResult), Object.prototype, "plain object returned"); + +const bigintResult = calendar.mergeFields(3n, 4n); +assert.compareArray(Object.keys(bigintResult), [], "BigInt objects have no own property keys"); +assert.sameValue(Object.getPrototypeOf(bigintResult), Object.prototype, "plain object returned"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js new file mode 100644 index 000000000000..8ef4a061c5a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: > + Temporal.Calendar.prototype.mergeFields will merge own data properties on its + arguments +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set fields to ? ToObject(fields). + 5. Set additionalFields to ? ToObject(additionalFields). + 6. Return ? DefaultMergeFields(fields, additionalFields). +features: [Temporal] +includes: [deepEqual.js] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { c: 3, d: 4 }), + { a: 1, b: 2, c: 3, d: 4 }, + "properties are merged" +); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { b: 3, c: 4 }), + { a: 1, b: 3, c: 4 }, + "property in additionalFields should overwrite one in fields" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/builtin.js new file mode 100644 index 000000000000..06eaef9d4f68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: > + Tests that Temporal.Calendar.prototype.mergeFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.mergeFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.mergeFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.mergeFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.mergeFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js new file mode 100644 index 000000000000..2c6a1ac6fc72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js @@ -0,0 +1,102 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: > + The default mergeFields algorithm from the ISO 8601 calendar should correctly + merge the month and monthCode properties +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set fields to ? ToObject(fields). + 5. Set additionalFields to ? ToObject(additionalFields). + 6. Return ? DefaultMergeFields(fields, additionalFields). +features: [Temporal] +includes: [deepEqual.js] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7 }, { b: 3, c: 4 }), + { a: 1, b: 3, c: 4, month: 7 }, + "month is copied from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, monthCode: "M08" }, { b: 3, c: 4 }), + { a: 1, b: 3, c: 4, monthCode: "M08" }, + "monthCode is copied from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7, monthCode: "M08" }, { b: 3, c: 4 }), + { a: 1, b: 3, c: 4, month: 7, monthCode: "M08" }, + "both month and monthCode are copied from fields, no validation is performed" +); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { b: 3, c: 4, month: 5 }), + { a: 1, b: 3, c: 4, month: 5 }, + "month is copied from additionalFields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { b: 3, c: 4, monthCode: "M06" }), + { a: 1, b: 3, c: 4, monthCode: "M06" }, + "monthCode is copied from additionalFields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { b: 3, c: 4, month: 5, monthCode: "M06" }), + { a: 1, b: 3, c: 4, month: 5, monthCode: "M06" }, + "both month and monthCode are copied from additionalFields, no validation is performed" +); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7 }, { b: 3, c: 4, month: 5 }), + { a: 1, b: 3, c: 4, month: 5 }, + "month from additionalFields overrides month from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, monthCode: "M07" }, { b: 3, c: 4, monthCode: "M05" }), + { a: 1, b: 3, c: 4, monthCode: "M05" }, + "monthCode from additionalFields overrides monthCode from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, monthCode: "M07" }, { b: 3, c: 4, month: 6 }), + { a: 1, b: 3, c: 4, month: 6 }, + "month's presence on additionalFields blocks monthCode from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7 }, { b: 3, c: 4, monthCode: "M06" }), + { a: 1, b: 3, c: 4, monthCode: "M06"}, + "monthCode's presence on additionalFields blocks month from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7, monthCode: "M08" },{ b: 3, c: 4, month: 5 }), + { a: 1, b: 3, c: 4, month: 5 }, + "month's presence on additionalFields blocks both month and monthCode from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7, monthCode: "M08" }, { b: 3, c: 4, monthCode: "M06" }), + { a: 1, b: 3, c: 4, monthCode: "M06" }, + "monthCode's presence on additionalFields blocks both month and monthCode from fields" +); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7 }, { b: 3, c: 4, month: 5, monthCode: "M06" }), + { a: 1, b: 3, c: 4, month: 5, monthCode: "M06" }, + "both month and monthCode are copied from additionalFields even when fields has month" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, monthCode: "M07" }, { b: 3, c: 4, month: 5, monthCode: "M06" }), + { a: 1, b: 3, c: 4, month: 5, monthCode: "M06" }, + "both month and monthCode are copied from additionalFields even when fields has monthCode" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7, monthCode: "M08" }, { b: 3, c: 4, month: 5, monthCode: "M06" }), + { a: 1, b: 3, c: 4, month: 5, monthCode: "M06" }, + "both month and monthCode are copied from additionalFields even when fields has both month and monthCode" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/length.js new file mode 100644 index 000000000000..5745e5707e81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Temporal.Calendar.prototype.mergeFields.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.mergeFields, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/name.js new file mode 100644 index 000000000000..72aa903d84f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Temporal.Calendar.prototype.mergeFields.name is "mergeFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.mergeFields, "name", { + value: "mergeFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js new file mode 100644 index 000000000000..4ade39821074 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Only string keys from the arguments are merged +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set fields to ? ToObject(fields). + 5. Set additionalFields to ? ToObject(additionalFields). + 6. Return ? DefaultMergeFields(fields, additionalFields). +features: [Temporal] +includes: [deepEqual.js] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +assert.deepEqual( + cal.mergeFields({ 1: 2 }, { 3: 4 }), + { "1": 2, "3": 4 }, + "number keys are actually string keys and are merged as such" +); +assert.deepEqual( + cal.mergeFields({ 1n: 2 }, { 2n: 4 }), + { "1": 2, "2": 4 }, + "bigint keys are actually string keys and are merged as such" +); + +const foo = Symbol("foo"); +const bar = Symbol("bar"); +assert.deepEqual(cal.mergeFields({ [foo]: 1 }, { [bar]: 2 }), {}, "symbol keys are not merged"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/not-a-constructor.js new file mode 100644 index 000000000000..278131dcebd8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: > + Temporal.Calendar.prototype.mergeFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.mergeFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.mergeFields), false, + "isConstructor(Temporal.Calendar.prototype.mergeFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/prop-desc.js new file mode 100644 index 000000000000..dc0ec20df389 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: The "mergeFields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.mergeFields, + "function", + "`typeof Calendar.prototype.mergeFields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "mergeFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/shell.js index e69de29bb2d1..b36293881a43 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/shell.js @@ -0,0 +1,348 @@ +// GENERATED, DO NOT EDIT +// file: deepEqual.js +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Compare two values structurally +defines: [assert.deepEqual] +---*/ + +assert.deepEqual = function(actual, expected, message) { + var format = assert.deepEqual.format; + assert( + assert.deepEqual._compare(actual, expected), + `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}` + ); +}; + +assert.deepEqual.format = function(value, seen) { + switch (typeof value) { + case 'string': + return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`; + case 'number': + case 'boolean': + case 'symbol': + case 'bigint': + return value.toString(); + case 'undefined': + return 'undefined'; + case 'function': + return `[Function${value.name ? `: ${value.name}` : ''}]`; + case 'object': + if (value === null) return 'null'; + if (value instanceof Date) return `Date "${value.toISOString()}"`; + if (value instanceof RegExp) return value.toString(); + if (!seen) { + seen = { + counter: 0, + map: new Map() + }; + } + + let usage = seen.map.get(value); + if (usage) { + usage.used = true; + return `[Ref: #${usage.id}]`; + } + + usage = { id: ++seen.counter, used: false }; + seen.map.set(value, usage); + + if (typeof Set !== "undefined" && value instanceof Set) { + return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (typeof Map !== "undefined" && value instanceof Map) { + return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (Array.isArray ? Array.isArray(value) : value instanceof Array) { + return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`; + } + let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object'; + if (tag === 'Object' && Object.getPrototypeOf(value) === null) { + tag = '[Object: null prototype]'; + } + return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`; + default: + return typeof value; + } +}; + +assert.deepEqual._compare = (function () { + var EQUAL = 1; + var NOT_EQUAL = -1; + var UNKNOWN = 0; + + function deepEqual(a, b) { + return compareEquality(a, b) === EQUAL; + } + + function compareEquality(a, b, cache) { + return compareIf(a, b, isOptional, compareOptionality) + || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality) + || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache) + || NOT_EQUAL; + } + + function compareIf(a, b, test, compare, cache) { + return !test(a) + ? !test(b) ? UNKNOWN : NOT_EQUAL + : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache); + } + + function tryCompareStrictEquality(a, b) { + return a === b ? EQUAL : UNKNOWN; + } + + function tryCompareTypeOfEquality(a, b) { + return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN; + } + + function tryCompareToStringTagEquality(a, b) { + var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined; + var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined; + return aTag !== bTag ? NOT_EQUAL : UNKNOWN; + } + + function isOptional(value) { + return value === undefined + || value === null; + } + + function compareOptionality(a, b) { + return tryCompareStrictEquality(a, b) + || NOT_EQUAL; + } + + function isPrimitiveEquatable(value) { + switch (typeof value) { + case 'string': + case 'number': + case 'bigint': + case 'boolean': + case 'symbol': + return true; + default: + return isBoxed(value); + } + } + + function comparePrimitiveEquality(a, b) { + if (isBoxed(a)) a = a.valueOf(); + if (isBoxed(b)) b = b.valueOf(); + return tryCompareStrictEquality(a, b) + || tryCompareTypeOfEquality(a, b) + || compareIf(a, b, isNaNEquatable, compareNaNEquality) + || NOT_EQUAL; + } + + function isNaNEquatable(value) { + return typeof value === 'number'; + } + + function compareNaNEquality(a, b) { + return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL; + } + + function isObjectEquatable(value) { + return typeof value === 'object'; + } + + function compareObjectEquality(a, b, cache) { + if (!cache) cache = new Map(); + return getCache(cache, a, b) + || setCache(cache, a, b, EQUAL) // consider equal for now + || cacheComparison(a, b, tryCompareStrictEquality, cache) + || cacheComparison(a, b, tryCompareToStringTagEquality, cache) + || compareIf(a, b, isValueOfEquatable, compareValueOfEquality) + || compareIf(a, b, isToStringEquatable, compareToStringEquality) + || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache) + || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache) + || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || cacheComparison(a, b, fail, cache); + } + + function isBoxed(value) { + return value instanceof String + || value instanceof Number + || value instanceof Boolean + || typeof Symbol === 'function' && value instanceof Symbol + || typeof BigInt === 'function' && value instanceof BigInt; + } + + function isValueOfEquatable(value) { + return value instanceof Date; + } + + function compareValueOfEquality(a, b) { + return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isToStringEquatable(value) { + return value instanceof RegExp; + } + + function compareToStringEquality(a, b) { + return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isArrayLikeEquatable(value) { + return (Array.isArray ? Array.isArray(value) : value instanceof Array) + || (typeof Uint8Array === 'function' && value instanceof Uint8Array) + || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray) + || (typeof Uint16Array === 'function' && value instanceof Uint16Array) + || (typeof Uint32Array === 'function' && value instanceof Uint32Array) + || (typeof Int8Array === 'function' && value instanceof Int8Array) + || (typeof Int16Array === 'function' && value instanceof Int16Array) + || (typeof Int32Array === 'function' && value instanceof Int32Array) + || (typeof Float32Array === 'function' && value instanceof Float32Array) + || (typeof Float64Array === 'function' && value instanceof Float64Array) + || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array) + || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array); + } + + function compareArrayLikeEquality(a, b, cache) { + if (a.length !== b.length) return NOT_EQUAL; + for (var i = 0; i < a.length; i++) { + if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + return EQUAL; + } + + function isStructurallyEquatable(value) { + return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference + || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference + || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference + || typeof Map === 'function' && value instanceof Map // comparable via @@iterator + || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator + } + + function compareStructuralEquality(a, b, cache) { + var aKeys = []; + for (var key in a) aKeys.push(key); + + var bKeys = []; + for (var key in b) bKeys.push(key); + + if (aKeys.length !== bKeys.length) { + return NOT_EQUAL; + } + + aKeys.sort(); + bKeys.sort(); + + for (var i = 0; i < aKeys.length; i++) { + var aKey = aKeys[i]; + var bKey = bKeys[i]; + if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + + return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || EQUAL; + } + + function isIterableEquatable(value) { + return typeof Symbol === 'function' + && typeof value[Symbol.iterator] === 'function'; + } + + function compareIteratorEquality(a, b, cache) { + if (typeof Map === 'function' && a instanceof Map && b instanceof Map || + typeof Set === 'function' && a instanceof Set && b instanceof Set) { + if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size + } + + var ar, br; + while (true) { + ar = a.next(); + br = b.next(); + if (ar.done) { + if (br.done) return EQUAL; + if (b.return) b.return(); + return NOT_EQUAL; + } + if (br.done) { + if (a.return) a.return(); + return NOT_EQUAL; + } + if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) { + if (a.return) a.return(); + if (b.return) b.return(); + return NOT_EQUAL; + } + } + } + + function compareIterableEquality(a, b, cache) { + return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache); + } + + function cacheComparison(a, b, compare, cache) { + var result = compare(a, b, cache); + if (cache && (result === EQUAL || result === NOT_EQUAL)) { + setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result)); + } + return result; + } + + function fail() { + return NOT_EQUAL; + } + + function setCache(cache, left, right, result) { + var otherCache; + + otherCache = cache.get(left); + if (!otherCache) cache.set(left, otherCache = new Map()); + otherCache.set(right, result); + + otherCache = cache.get(right); + if (!otherCache) cache.set(right, otherCache = new Map()); + otherCache.set(left, result); + } + + function getCache(cache, left, right) { + var otherCache; + var result; + + otherCache = cache.get(left); + result = otherCache && otherCache.get(right); + if (result) return result; + + otherCache = cache.get(right); + result = otherCache && otherCache.get(left); + if (result) return result; + + return UNKNOWN; + } + + return deepEqual; +})(); + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js new file mode 100644 index 000000000000..c6fd9cd2a289 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.month(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..8e1458706cab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.month(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..27660266a25a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.month(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..da3ae3d28b0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.month(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..209c5030898e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.month(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..dee10750c470 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.month(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/basic.js new file mode 100644 index 000000000000..36580f5c8241 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/basic.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Basic tests for month(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 11; +assert.sameValue(iso.month(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.month(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.month(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +assert.sameValue(iso.month({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.month("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.month({ year: 2000 }), "property bag with missing properties"); +assert.throws(TypeError, () => iso.month(Temporal.PlainMonthDay.from("11-05")), "PlainMonthDay"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/branding.js index a3fd955c1809..45b529d18ea3 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/branding.js @@ -12,14 +12,16 @@ const month = Temporal.Calendar.prototype.month; assert.sameValue(typeof month, "function"); -assert.throws(TypeError, () => month.call(undefined), "undefined"); -assert.throws(TypeError, () => month.call(null), "null"); -assert.throws(TypeError, () => month.call(true), "true"); -assert.throws(TypeError, () => month.call(""), "empty string"); -assert.throws(TypeError, () => month.call(Symbol()), "symbol"); -assert.throws(TypeError, () => month.call(1), "1"); -assert.throws(TypeError, () => month.call({}), "plain object"); -assert.throws(TypeError, () => month.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => month.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => month.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => month.apply(null, args), "null"); +assert.throws(TypeError, () => month.apply(true, args), "true"); +assert.throws(TypeError, () => month.apply("", args), "empty string"); +assert.throws(TypeError, () => month.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => month.apply(1, args), "1"); +assert.throws(TypeError, () => month.apply({}, args), "plain object"); +assert.throws(TypeError, () => month.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => month.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/builtin.js new file mode 100644 index 000000000000..b99d76febdfb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Tests that Temporal.Calendar.prototype.month + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.month), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.month), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.month), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.month.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..7921f038fba3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.month({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-fields-iterable.js new file mode 100644 index 000000000000..f6d983a50ee7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.month step 4: + 4. Return ? ISOMonth(_dateOrDateTime_). + sec-temporal-isomonth step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.month({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-temporal-object.js new file mode 100644 index 000000000000..a2b6b1e4a742 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.month step 4: + 4. Return ? ISOMonth(_dateOrDateTime_). + sec-temporal-isomonth step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.month({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date-time.js index 02ba56186e1f..f4f6589547df 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date-time.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date-time.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.month -description: Temporal.Calendar.prototype.month will take PlainDateTime and return +description: > + Temporal.Calendar.prototype.month will take PlainDateTime and return the value of the month. info: | 5. If Type(temporalDateLike) is not Object or temporalDateLike does not have diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date.js index 9f9fcf366cc5..a2a7ece2b936 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.month -description: Temporal.Calendar.prototype.month will take PlainDate and return +description: > + Temporal.Calendar.prototype.month will take PlainDate and return the value of the month. info: | 1. Let calendar be the this value. diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..c6af471ade62 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.month +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.month({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.month({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/length.js new file mode 100644 index 000000000000..899dd6d07435 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Temporal.Calendar.prototype.month.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.month, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/month-day-throw-type-error.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/month-day-throw-type-error.js index b7da095c2da5..2c118fd786fa 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/month-day-throw-type-error.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/month-day-throw-type-error.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.month -description: Temporal.Calendar.prototype.month throws TypeError if temporalDateLike +description: > + Temporal.Calendar.prototype.month throws TypeError if temporalDateLike is a PlainMonthDay object. ToTemporalDate when temporalDateLike is invalid string. info: | diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/name.js new file mode 100644 index 000000000000..6d53b382ec86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Temporal.Calendar.prototype.month.name is "month". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.month, "name", { + value: "month", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/not-a-constructor.js new file mode 100644 index 000000000000..a22c3e0e42ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Temporal.Calendar.prototype.month does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.month(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.month), false, + "isConstructor(Temporal.Calendar.prototype.month)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/prop-desc.js new file mode 100644 index 000000000000..0c9d7c4c94a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: The "month" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.month, + "function", + "`typeof Calendar.prototype.month` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "month", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/string.js index 04e3e7b89565..16ee97a8e176 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/string.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.month -description: Temporal.Calendar.prototype.month will take ISO8601 string and return +description: > + Temporal.Calendar.prototype.month will take ISO8601 string and return the value of the month. info: | 5. If Type(temporalDateLike) is not Object or temporalDateLike does not have diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-range-error-ToTemporalDate.js index 22ac2f7f0581..195dabce0aa8 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-range-error-ToTemporalDate.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.month -description: Temporal.Calendar.prototype.month throws RangeError on +description: > + Temporal.Calendar.prototype.month throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 5. If Type(temporalDateLike) is not Object or temporalDateLike diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index b1ed2ee3da81..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.calendar.prototype.month -description: Temporal.Calendar.prototype.month throws TypeError on RequireInternalSlot if object has no internal slot. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { month: cal.month } -assert.throws(TypeError, () => badCal.month("2021-03-04"), - 'badCal.month("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-month.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-month.js index 7878d9b10dc4..1083b6de992e 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-month.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-month.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.month -description: Temporal.Calendar.prototype.month will take PlainYearMonth and return +description: > + Temporal.Calendar.prototype.month will take PlainYearMonth and return the value of the month. info: | 6. Return ! ISOMonth(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-zero.js new file mode 100644 index 000000000000..ca88a7a03f8a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.month(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js new file mode 100644 index 000000000000..8f7dc62a4f28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.monthCode(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..0eef9fc638c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthCode(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..dd9c5f20d249 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.monthCode(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..5c8f7322e4ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.monthCode(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..10c1a693f2b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.monthCode(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..863a82875c69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.monthCode(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/basic.js new file mode 100644 index 000000000000..720f375fce02 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/basic.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Basic tests for monthCode(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = "M11"; +assert.sameValue(iso.monthCode(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.monthCode(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.monthCode(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +assert.sameValue(iso.monthCode(Temporal.PlainMonthDay.from("11-05")), res, "PlainMonthDay"); +assert.sameValue(iso.monthCode({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.monthCode("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.monthCode({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/branding.js index deb5541f4b14..c2b182215578 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/branding.js @@ -12,14 +12,16 @@ const monthCode = Temporal.Calendar.prototype.monthCode; assert.sameValue(typeof monthCode, "function"); -assert.throws(TypeError, () => monthCode.call(undefined), "undefined"); -assert.throws(TypeError, () => monthCode.call(null), "null"); -assert.throws(TypeError, () => monthCode.call(true), "true"); -assert.throws(TypeError, () => monthCode.call(""), "empty string"); -assert.throws(TypeError, () => monthCode.call(Symbol()), "symbol"); -assert.throws(TypeError, () => monthCode.call(1), "1"); -assert.throws(TypeError, () => monthCode.call({}), "plain object"); -assert.throws(TypeError, () => monthCode.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => monthCode.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => monthCode.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => monthCode.apply(null, args), "null"); +assert.throws(TypeError, () => monthCode.apply(true, args), "true"); +assert.throws(TypeError, () => monthCode.apply("", args), "empty string"); +assert.throws(TypeError, () => monthCode.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => monthCode.apply(1, args), "1"); +assert.throws(TypeError, () => monthCode.apply({}, args), "plain object"); +assert.throws(TypeError, () => monthCode.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => monthCode.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/builtin.js new file mode 100644 index 000000000000..17ff14fe996a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: > + Tests that Temporal.Calendar.prototype.monthCode + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.monthCode), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.monthCode), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.monthCode), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.monthCode.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..c4a0e003d03b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.monthCode({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-fields-iterable.js new file mode 100644 index 000000000000..e35c2dc02b1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.monthcode step 4: + 4. Return ? ISOMonthCode(_dateOrDateTime_). + sec-temporal-isomonthcode step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.monthCode({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-temporal-object.js new file mode 100644 index 000000000000..46d93110e988 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.monthcode step 4: + 4. Return ? ISOMonthCode(_dateOrDateTime_). + sec-temporal-isomonthcode step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.monthCode({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date-time.js index b08b6a873fc5..4ebe8409d4ed 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date-time.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date-time.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.monthCode -description: Temporal.Calendar.prototype.month will take PlainDateTime and return +description: > + Temporal.Calendar.prototype.month will take PlainDateTime and return the value of the monthCode. info: | 6. Return ! ISOMonthCode(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date.js index daaae5e6f13f..77c613549507 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.monthCode -description: Temporal.Calendar.prototype.monthCode will take PlainDate and return +description: > + Temporal.Calendar.prototype.monthCode will take PlainDate and return the value of the monthCode. info: | 5. Return ! ISOMonthCode(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..10ad2754edab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.monthcode +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.monthCode({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.monthCode({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/length.js new file mode 100644 index 000000000000..d3604d8d8dc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Temporal.Calendar.prototype.monthCode.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.monthCode, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/month-day.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/month-day.js index 030a346cae28..4ec5588002df 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/month-day.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/month-day.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.monthCode -description: Temporal.Calendar.prototype.monthCode will take PlainMonthDay and return +description: > + Temporal.Calendar.prototype.monthCode will take PlainMonthDay and return the value of the monthCode. info: | 6. Return ! ISOMonthCode(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/name.js new file mode 100644 index 000000000000..90bcd956d00a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Temporal.Calendar.prototype.monthCode.name is "monthCode". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.monthCode, "name", { + value: "monthCode", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/not-a-constructor.js new file mode 100644 index 000000000000..726c6fff07cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: > + Temporal.Calendar.prototype.monthCode does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.monthCode(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.monthCode), false, + "isConstructor(Temporal.Calendar.prototype.monthCode)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/prop-desc.js new file mode 100644 index 000000000000..b172e55645d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: The "monthCode" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.monthCode, + "function", + "`typeof Calendar.prototype.monthCode` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "monthCode", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/string.js index 133745c2fc71..3d7945be8ad7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/string.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.monthCode -description: Temporal.Calendar.prototype.monthCode will take ISO8601 string and return +description: > + Temporal.Calendar.prototype.monthCode will take ISO8601 string and return the value of the monthCode. info: | 5. If Type(temporalDateLike) is not Object or temporalDateLike does not have diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-range-error-ToTemporalDate.js index 4bac505bdc18..8fc5af5eedfa 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-range-error-ToTemporalDate.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.monthCode -description: Temporal.Calendar.prototype.monthCode throws RangeError on +description: > + Temporal.Calendar.prototype.monthCode throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index 54f2f341c6cb..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,18 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.calendar.prototype.monthCode -description: Temporal.Calendar.prototype.monthCode throws TypeError on RequireInternalSlot if object has no internal slot. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { monthCode: cal.monthCode} -assert.throws(TypeError, () => badCal.monthCode("2021-03-04"), - 'badCal.monthCode("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-month.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-month.js index 15c874bba78c..8c70484e068f 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-month.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-month.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.monthCode -description: Temporal.Calendar.prototype.monthCode will take PlainYearMonth and return +description: > + Temporal.Calendar.prototype.monthCode will take PlainYearMonth and return the value of the monthCode. info: | 6. Return ! ISOMonthCode(temporalDateLike). diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-zero.js new file mode 100644 index 000000000000..f7d565add63c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.monthCode(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js new file mode 100644 index 000000000000..dfbe948d82ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields will return correctly with valid data. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +let result = cal.monthDayFromFields({ year: 2021, month: 7, day: 3 }); +TemporalHelpers.assertPlainMonthDay(result, "M07", 3, "month 7, day 3, with year"); +result = cal.monthDayFromFields({ year: 2021, month: 12, day: 31 }); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "month 12, day 31, with year"); +result = cal.monthDayFromFields({ monthCode: "M07", day: 3 }); +TemporalHelpers.assertPlainMonthDay(result, "M07", 3, "monthCode M07, day 3"); +result = cal.monthDayFromFields({ monthCode: "M12", day: 31 }); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "monthCode M12, day 31"); + +["constrain", "reject"].forEach(function (overflow) { + const opt = { overflow }; + result = cal.monthDayFromFields({ year: 2021, month: 7, day: 3 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M07", 3, "month 7, day 3, with year"); + result = cal.monthDayFromFields({ year: 2021, month: 12, day: 31 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "month 12, day 31, with year"); + result = cal.monthDayFromFields({ monthCode: "M07", day: 3 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M07", 3, "monthCode M07, day 3"); + result = cal.monthDayFromFields({ monthCode: "M12", day: 31 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "monthCode M12, day 31"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/builtin.js new file mode 100644 index 000000000000..62f83b700891 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: > + Tests that Temporal.Calendar.prototype.monthDayFromFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.monthDayFromFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.monthDayFromFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.monthDayFromFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.monthDayFromFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js new file mode 100644 index 000000000000..da738aafec42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields will throw TypeError with incorrect input data type. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +features: [Temporal] +---*/ + +let cal = new Temporal.Calendar("iso8601") + +assert.throws(TypeError, () => cal.monthDayFromFields({}), "at least one correctly spelled property is required"); +assert.throws(TypeError, () => cal.monthDayFromFields({ monthCode: "M12" }), "day is required with monthCode"); +assert.throws(TypeError, () => cal.monthDayFromFields({ year: 2021, month: 12 }), "day is required with year and month"); +assert.throws(TypeError, () => cal.monthDayFromFields({ month: 1, day: 17 }), "year is required if month is present"); +assert.throws(TypeError, () => cal.monthDayFromFields({ year: 2021, day: 17 }), "either month or monthCode is required"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js new file mode 100644 index 000000000000..578f783e3a2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Throw a TypeError if the fields is not an object +features: [Symbol, Temporal] +---*/ + +const tests = [undefined, null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; +const iso = Temporal.Calendar.from("iso8601"); +for (const fields of tests) { + assert.throws(TypeError, () => iso.monthDayFromFields(fields, {})); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..0f4b2b89deb7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.monthdayfromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.monthDayFromFields({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.monthDayFromFields({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/length.js new file mode 100644 index 000000000000..4c2bea0540fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.monthDayFromFields, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js new file mode 100644 index 000000000000..0d299f33b32f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Throw RangeError for an out-of-range, conflicting, or ill-formed monthCode +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +["m1", "M1", "m01"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.monthDayFromFields({ monthCode, day: 17 }), + `monthCode '${monthCode}' is not well-formed`); +}); + +assert.throws(RangeError, () => cal.monthDayFromFields({ year: 2021, month: 12, monthCode: "M11", day: 17 }), + "monthCode and month conflict"); + +["M00", "M19", "M99", "M13"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.monthDayFromFields({ monthCode, day: 17 }), + `monthCode '${monthCode}' is not valid for ISO 8601 calendar`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/name.js new file mode 100644 index 000000000000..cf8618040ea2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields.name is "monthDayFromFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.monthDayFromFields, "name", { + value: "monthDayFromFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/not-a-constructor.js new file mode 100644 index 000000000000..db01622073b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: > + Temporal.Calendar.prototype.monthDayFromFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.monthDayFromFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.monthDayFromFields), false, + "isConstructor(Temporal.Calendar.prototype.monthDayFromFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js new file mode 100644 index 000000000000..31d1142817cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js @@ -0,0 +1,94 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields will return correctly with data and overflow set to 'constrain'. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); +const opt = { overflow: "constrain" }; + +let result = cal.monthDayFromFields({ year: 2021, month: 1, day: 133 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M01", 31, "day is constrained to 31 in month 1"); +result = cal.monthDayFromFields({ year: 2021, month: 2, day: 133 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M02", 28, "day is constrained to 28 in month 2 (year 2021)"); +result = cal.monthDayFromFields({ year: 2021, month: 3, day: 9033 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M03", 31, "day is constrained to 31 in month 3"); +result = cal.monthDayFromFields({ year: 2021, month: 4, day: 50 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M04", 30, "day is constrained to 30 in month 4"); +result = cal.monthDayFromFields({ year: 2021, month: 5, day: 77 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M05", 31, "day is constrained to 31 in month 5"); +result = cal.monthDayFromFields({ year: 2021, month: 6, day: 33 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M06", 30, "day is constrained to 30 in month 6"); +result = cal.monthDayFromFields({ year: 2021, month: 7, day: 33 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M07", 31, "day is constrained to 31 in month 7"); +result = cal.monthDayFromFields({ year: 2021, month: 8, day: 300 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M08", 31, "day is constrained to 31 in month 8"); +result = cal.monthDayFromFields({ year: 2021, month: 9, day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M09", 30, "day is constrained to 30 in month 9"); +result = cal.monthDayFromFields({ year: 2021, month: 10, day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M10", 31, "day is constrained to 31 in month 10"); +result = cal.monthDayFromFields({ year: 2021, month: 11, day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M11", 30, "day is constrained to 30 in month 11"); +result = cal.monthDayFromFields({ year: 2021, month: 12, day: 500 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "day is constrained to 31 in month 12"); + +assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month: -99999, day: 1 }, opt), + "negative month -99999 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month: -1, day: 1 }, opt), + "negative month -1 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month: 0, day: 1 }, opt), + "month zero is out of range even with overflow constrain" +) + +result = cal.monthDayFromFields({ year: 2021, month: 13, day: 1 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M12", 1, "month 13 is constrained to 12"); +result = cal.monthDayFromFields({ year: 2021, month: 999999, day: 500 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "month 999999 is constrained to 12 and day constrained to 31"); + +result = cal.monthDayFromFields({ monthCode: "M01", day: 133 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M01", 31, "day is constrained to 31 in monthCode M01"); +result = cal.monthDayFromFields({ monthCode: "M02", day: 133 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M02", 29, "day is constrained to 29 in monthCode M02"); +result = cal.monthDayFromFields({ monthCode: "M03", day: 9033 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M03", 31, "day is constrained to 31 in monthCode M03"); +result = cal.monthDayFromFields({ monthCode: "M04", day: 50 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M04", 30, "day is constrained to 30 in monthCode M04"); +result = cal.monthDayFromFields({ monthCode: "M05", day: 77 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M05", 31, "day is constrained to 31 in monthCode M05"); +result = cal.monthDayFromFields({ monthCode: "M06", day: 33 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M06", 30, "day is constrained to 30 in monthCode M06"); +result = cal.monthDayFromFields({ monthCode: "M07", day: 33 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M07", 31, "day is constrained to 31 in monthCode M07"); +result = cal.monthDayFromFields({ monthCode: "M08", day: 300 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M08", 31, "day is constrained to 31 in monthCode M08"); +result = cal.monthDayFromFields({ monthCode: "M09", day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M09", 30, "day is constrained to 30 in monthCode M09"); +result = cal.monthDayFromFields({ monthCode: "M10", day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M10", 31, "day is constrained to 31 in monthCode M10"); +result = cal.monthDayFromFields({ monthCode: "M11", day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M11", 30, "day is constrained to 30 in monthCode M11"); +result = cal.monthDayFromFields({ monthCode: "M12", day: 500 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "day is constrained to 31 in monthCode M12"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js new file mode 100644 index 000000000000..27761ca46b39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.monthdayfromfields step 6: + 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_). +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js new file mode 100644 index 000000000000..bf7f13174b5d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js @@ -0,0 +1,67 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Throw RangeError for input data out of range with overflow reject +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +[-1, 0, 13, 9995].forEach((month) => { + assert.throws( + RangeError, + () => cal.monthDayFromFields({year: 2021, month, day: 5}, { overflow: "reject" }), + `Month ${month} is out of range for 2021 with overflow: reject` + ); +}); + +[-1, 0, 32, 999].forEach((day) => { + assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month: 12, day }, { overflow: "reject" }), + `Day ${day} is out of range for 2021-12 with overflow: reject` + ); + assert.throws( + RangeError, + () => cal.monthDayFromFields({ monthCode: "M12", day }, { overflow: "reject" }), + `Day ${day} is out of range for 2021-M12 with overflow: reject` + ); +}); + +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M01", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M01"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M02", day: 30 }, { overflow: "reject" }), "Day 30 is out of range for monthCode M02"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M03", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M03"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M04", day: 31 }, { overflow: "reject" }), "Day 31 is out of range for monthCode M04"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M05", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M05"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M06", day: 31 }, { overflow: "reject" }), "Day 31 is out of range for monthCode M06"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M07", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M07"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M08", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M08"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M09", day: 31 }, { overflow: "reject" }), "Day 31 is out of range for monthCode M09"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M10", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M10"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M11", day: 31 }, { overflow: "reject" }), "Day 31 is out of range for monthCode M11"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M12", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M12"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-undefined.js new file mode 100644 index 000000000000..d96e3dd20563 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.monthdayfromfields step 6: + 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +const explicit = calendar.monthDayFromFields({ year: 2000, month: 15, day: 2 }, { overflow: undefined }); +TemporalHelpers.assertPlainMonthDay(explicit, "M12", 2, "default overflow is constrain"); +const implicit = calendar.monthDayFromFields({ year: 2000, month: 15, day: 2 }, {}); +TemporalHelpers.assertPlainMonthDay(implicit, "M12", 2, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js new file mode 100644 index 000000000000..e0d5789c4ec1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.monthdayfromfields step 6: + 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainMonthDay(result, "M05", 2, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/prop-desc.js new file mode 100644 index 000000000000..09e13e425dea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: The "monthDayFromFields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.monthDayFromFields, + "function", + "`typeof Calendar.prototype.monthDayFromFields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "monthDayFromFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972.js new file mode 100644 index 000000000000..7694c31beaea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Use a leap year as the reference year if monthCode is given +info: | + sec-temporal-isomonthdayfromfields: + 12. If _monthCode_ is *undefined*, then + a. Let _result_ be ? RegulateISODate(_year_, _month_, _day_, _overflow_). + 13. Else, + a. Let _result_ be ? RegulateISODate(_referenceISOYear_, _month_, _day_, _overflow_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +let result = cal.monthDayFromFields({ year: 2021, monthCode: "M02", day: 29 }); +TemporalHelpers.assertPlainMonthDay(result, "M02", 29, "year is ignored and reference year should be a leap year if monthCode is given"); + +result = cal.monthDayFromFields({ year: 2021, month: 2, day: 29 }, { overflow: "constrain" }); +TemporalHelpers.assertPlainMonthDay(result, "M02", 28, "year should not be ignored if monthCode is not given"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js new file mode 100644 index 000000000000..a4ab4dbccf0f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..c6daca543158 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js new file mode 100644 index 000000000000..a2bc15e1eac4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: An ISO 8601 date string should be converted as input +info: | + a. Perform ? ToTemporalDate(temporalDateLike). + 5. Return 12𝔽. +features: [Temporal] +---*/ + +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.monthsInYear("3456-12-20"), 12); +assert.sameValue(cal.monthsInYear("+000998-01-28"), 12); +assert.sameValue(cal.monthsInYear("3456-12-20T03:04:05+00:00[UTC]"), 12); +assert.sameValue(cal.monthsInYear("+000998-01-28T03:04:05+00:00[UTC]"), 12); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..1089a769ffd3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.monthsInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..331787633c9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.monthsInYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..28fdcbcbab4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.monthsInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..8f97a60854d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.monthsInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js new file mode 100644 index 000000000000..f651a88f4ea7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Basic tests for monthsInYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 12; +assert.sameValue(iso.monthsInYear(new Temporal.PlainDate(1994, 11, 5)), res, "PlainDate"); +assert.sameValue(iso.monthsInYear(new Temporal.PlainDateTime(1994, 11, 5, 8, 15, 30)), res, "PlainDateTime"); +assert.sameValue(iso.monthsInYear(new Temporal.PlainYearMonth(1994, 11)), res, "PlainYearMonth"); +assert.sameValue(iso.monthsInYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.monthsInYear("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.monthsInYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js index 2d4aa8a90ca1..d62c78f369be 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js @@ -12,14 +12,16 @@ const monthsInYear = Temporal.Calendar.prototype.monthsInYear; assert.sameValue(typeof monthsInYear, "function"); -assert.throws(TypeError, () => monthsInYear.call(undefined), "undefined"); -assert.throws(TypeError, () => monthsInYear.call(null), "null"); -assert.throws(TypeError, () => monthsInYear.call(true), "true"); -assert.throws(TypeError, () => monthsInYear.call(""), "empty string"); -assert.throws(TypeError, () => monthsInYear.call(Symbol()), "symbol"); -assert.throws(TypeError, () => monthsInYear.call(1), "1"); -assert.throws(TypeError, () => monthsInYear.call({}), "plain object"); -assert.throws(TypeError, () => monthsInYear.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => monthsInYear.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = new Temporal.PlainDate(2021, 3, 4); + +assert.throws(TypeError, () => monthsInYear.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => monthsInYear.call(null, arg), "null"); +assert.throws(TypeError, () => monthsInYear.call(true, arg), "true"); +assert.throws(TypeError, () => monthsInYear.call("", arg), "empty string"); +assert.throws(TypeError, () => monthsInYear.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => monthsInYear.call(1, arg), "1"); +assert.throws(TypeError, () => monthsInYear.call({}, arg), "plain object"); +assert.throws(TypeError, () => monthsInYear.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => monthsInYear.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/builtin.js new file mode 100644 index 000000000000..ea88fbde660e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: > + Tests that Temporal.Calendar.prototype.monthsInYear + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.monthsInYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.monthsInYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.monthsInYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.monthsInYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..72dc32cd3f64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.monthsInYear({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-fields-iterable.js new file mode 100644 index 000000000000..4e7fb97e73fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.monthsinyear step 4: + 4. Perform ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.monthsInYear({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-temporal-object.js new file mode 100644 index 000000000000..9fe1a5c778e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.monthsinyear step 4: + 4. Perform ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.monthsInYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..2e3797081b6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.monthsinyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.monthsInYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.monthsInYear({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/length.js new file mode 100644 index 000000000000..411d74035f13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Temporal.Calendar.prototype.monthsInYear.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.monthsInYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/name.js new file mode 100644 index 000000000000..7857d6cdac72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Temporal.Calendar.prototype.monthsInYear.name is "monthsInYear". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.monthsInYear, "name", { + value: "monthsInYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/not-a-constructor.js new file mode 100644 index 000000000000..03a4b10911c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: > + Temporal.Calendar.prototype.monthsInYear does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.monthsInYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.monthsInYear), false, + "isConstructor(Temporal.Calendar.prototype.monthsInYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/prop-desc.js new file mode 100644 index 000000000000..f11b20134758 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: The "monthsInYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.monthsInYear, + "function", + "`typeof Calendar.prototype.monthsInYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "monthsInYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/year-zero.js new file mode 100644 index 000000000000..1a55a1837c0b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.monthsInYear(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/prop-desc.js new file mode 100644 index 000000000000..cde159f79b2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-calendar-prototype +description: The "prototype" property of Temporal.Calendar +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Calendar.prototype, "object"); +assert.notSameValue(Temporal.Calendar.prototype, null); + +verifyProperty(Temporal.Calendar, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/branding.js new file mode 100644 index 000000000000..c5522bb91a0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toJSON = Temporal.Calendar.prototype.toJSON; + +assert.sameValue(typeof toJSON, "function"); + +assert.throws(TypeError, () => toJSON.call(undefined), "undefined"); +assert.throws(TypeError, () => toJSON.call(null), "null"); +assert.throws(TypeError, () => toJSON.call(true), "true"); +assert.throws(TypeError, () => toJSON.call(""), "empty string"); +assert.throws(TypeError, () => toJSON.call(Symbol()), "symbol"); +assert.throws(TypeError, () => toJSON.call(1), "1"); +assert.throws(TypeError, () => toJSON.call({}), "plain object"); +assert.throws(TypeError, () => toJSON.call(Temporal.Calendar), "Temporal.Calendar"); +assert.throws(TypeError, () => toJSON.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/eraYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/eraYear/browser.js rename to js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..19d4c36ad9d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: > + Tests that Temporal.Calendar.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/length.js new file mode 100644 index 000000000000..87d2890b989a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: Temporal.Calendar.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/name.js new file mode 100644 index 000000000000..1b10275bef72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: Temporal.Calendar.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..47e4fef393f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: > + Temporal.Calendar.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.toJSON), false, + "isConstructor(Temporal.Calendar.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..39622ea14779 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: The "toJSON" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.toJSON, + "function", + "`typeof Calendar.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/builtin.js new file mode 100644 index 000000000000..09e3e93920a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: > + Tests that Temporal.Calendar.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/length.js new file mode 100644 index 000000000000..a20bb48c4af3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: Temporal.Calendar.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/name.js new file mode 100644 index 000000000000..1321b9dc6bdb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: Temporal.Calendar.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..78eb201cd3e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: > + Temporal.Calendar.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.toString), false, + "isConstructor(Temporal.Calendar.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..1b22dcb68322 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: The "toString" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.toString, + "function", + "`typeof Calendar.prototype.toString` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js new file mode 100644 index 000000000000..0a31552e4be1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js @@ -0,0 +1,79 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Temporal.Calendar.prototype.weekOfYear will take Temporal.PlainDate object + and return the week of year of that date. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +// The following week numbers are taken from the table "Examples of contemporary +// dates around New Year's Day" from +// https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar + +let d = new Temporal.PlainDate(1977, 1, 1); +assert.sameValue(cal.weekOfYear(d), 53, "1977-01-01 is in w53"); + +d = new Temporal.PlainDate(1977, 1, 2); +assert.sameValue(cal.weekOfYear(d), 53, "1977-01-02 is in w53"); + +d = new Temporal.PlainDate(1977, 12, 31); +assert.sameValue(cal.weekOfYear(d), 52, "1977-12-31 is in w52"); + +d = new Temporal.PlainDate(1978, 1, 1); +assert.sameValue(cal.weekOfYear(d), 52, "1978-01-01 is in w52"); + +d = new Temporal.PlainDate(1978, 1, 2); +assert.sameValue(cal.weekOfYear(d), 1, "1978-01-02 is in w01"); + +d = new Temporal.PlainDate(1978, 12, 31); +assert.sameValue(cal.weekOfYear(d), 52, "1978-12-31 is in w52"); + +d = new Temporal.PlainDate(1979, 1, 1); +assert.sameValue(cal.weekOfYear(d), 1, "1979-01-01 is in w01"); + +d = new Temporal.PlainDate(1979, 12, 30); +assert.sameValue(cal.weekOfYear(d), 52, "1979-12-30 is in w52"); + +d = new Temporal.PlainDate(1979, 12, 31); +assert.sameValue(cal.weekOfYear(d), 1, "1979-12-31 is in w01"); + +d = new Temporal.PlainDate(1980, 1, 1); +assert.sameValue(cal.weekOfYear(d), 1, "1980-01-01 is in w01"); + +d = new Temporal.PlainDate(1980, 12, 28); +assert.sameValue(cal.weekOfYear(d), 52, "1980-12-28 is in w52"); + +d = new Temporal.PlainDate(1980, 12, 29); +assert.sameValue(cal.weekOfYear(d), 1, "1980-12-29 is in w01"); + +d = new Temporal.PlainDate(1980, 12, 30); +assert.sameValue(cal.weekOfYear(d), 1, "1980-12-30 is in w01"); + +d = new Temporal.PlainDate(1980, 12, 31); +assert.sameValue(cal.weekOfYear(d), 1, "1980-12-31 is in w01"); + +d = new Temporal.PlainDate(1981, 1, 1); +assert.sameValue(cal.weekOfYear(d), 1, "1981-01-01 is in w01"); + +d = new Temporal.PlainDate(1981, 12, 31); +assert.sameValue(cal.weekOfYear(d), 53, "1981-12-31 is in w53"); + +d = new Temporal.PlainDate(1982, 1, 1); +assert.sameValue(cal.weekOfYear(d), 53, "1982-01-01 is in w53"); + +d = new Temporal.PlainDate(1982, 1, 2); +assert.sameValue(cal.weekOfYear(d), 53, "1982-01-02 is in w53"); + +d = new Temporal.PlainDate(1982, 1, 3); +assert.sameValue(cal.weekOfYear(d), 53, "1982-01-03 is in w53"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js new file mode 100644 index 000000000000..34a58428d628 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js @@ -0,0 +1,79 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Temporal.Calendar.prototype.weekOfYear will take Temporal.PlainDateTime object + and return the week of year of that date. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +// The following week numbers are taken from the table "Examples of contemporary +// dates around New Year's Day" from +// https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar + +let dt = new Temporal.PlainDateTime(1977, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1977-01-01 is in w53"); + +dt = new Temporal.PlainDateTime(1977, 1, 2, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1977-01-02 is in w53"); + +dt = new Temporal.PlainDateTime(1977, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1977-12-31 is in w52"); + +dt = new Temporal.PlainDateTime(1978, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1978-01-01 is in w52"); + +dt = new Temporal.PlainDateTime(1978, 1, 2, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1978-01-02 is in w01"); + +dt = new Temporal.PlainDateTime(1978, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1978-12-31 is in w52"); + +dt = new Temporal.PlainDateTime(1979, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1979-01-01 is in w01"); + +dt = new Temporal.PlainDateTime(1979, 12, 30, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1979-12-30 is in w52"); + +dt = new Temporal.PlainDateTime(1979, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1979-12-31 is in w01"); + +dt = new Temporal.PlainDateTime(1980, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1980-01-01 is in w01"); + +dt = new Temporal.PlainDateTime(1980, 12, 28, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1980-12-28 is in w52"); + +dt = new Temporal.PlainDateTime(1980, 12, 29, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1980-12-29 is in w01"); + +dt = new Temporal.PlainDateTime(1980, 12, 30, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1980-12-30 is in w01"); + +dt = new Temporal.PlainDateTime(1980, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1980-12-31 is in w01"); + +dt = new Temporal.PlainDateTime(1981, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1981-01-01 is in w01"); + +dt = new Temporal.PlainDateTime(1981, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1981-12-31 is in w53"); + +dt = new Temporal.PlainDateTime(1982, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1982-01-01 is in w53"); + +dt = new Temporal.PlainDateTime(1982, 1, 2, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1982-01-02 is in w53"); + +dt = new Temporal.PlainDateTime(1982, 1, 3, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1982-01-03 is in w53"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js new file mode 100644 index 000000000000..b5a920f80cec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..8506ffbebdc4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js new file mode 100644 index 000000000000..e3ef1cf9fbbf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Temporal.Calendar.prototype.weekOfYear will take an ISO 8601 date string and + return the week of year of that date. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +// The following week numbers are taken from the table "Examples of contemporary +// dates around New Year's Day" from +// https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar + +assert.sameValue(cal.weekOfYear("1977-01-01"), 53, "1977-01-01 is in w53"); +assert.sameValue(cal.weekOfYear("1977-01-02"), 53, "1977-01-02 is in w53"); +assert.sameValue(cal.weekOfYear("1977-12-31"), 52, "1977-12-31 is in w52"); +assert.sameValue(cal.weekOfYear("1978-01-01"), 52, "1978-01-01 is in w52"); +assert.sameValue(cal.weekOfYear("1978-01-02"), 1, "1978-01-02 is in w01"); +assert.sameValue(cal.weekOfYear("1978-12-31"), 52, "1978-12-31 is in w52"); +assert.sameValue(cal.weekOfYear("1979-01-01"), 1, "1979-01-01 is in w01"); +assert.sameValue(cal.weekOfYear("1979-12-30"), 52, "1979-12-30 is in w52"); +assert.sameValue(cal.weekOfYear("1979-12-31"), 1, "1979-12-31 is in w01"); +assert.sameValue(cal.weekOfYear("1980-01-01"), 1, "1980-01-01 is in w01"); +assert.sameValue(cal.weekOfYear("1980-12-28"), 52, "1980-12-28 is in w52"); +assert.sameValue(cal.weekOfYear("1980-12-29"), 1, "1980-12-29 is in w01"); +assert.sameValue(cal.weekOfYear("1980-12-30"), 1, "1980-12-30 is in w01"); +assert.sameValue(cal.weekOfYear("1980-12-31"), 1, "1980-12-31 is in w01"); +assert.sameValue(cal.weekOfYear("1981-01-01"), 1, "1981-01-01 is in w01"); +assert.sameValue(cal.weekOfYear("1981-12-31"), 53, "1981-12-31 is in w53"); +assert.sameValue(cal.weekOfYear("1982-01-01"), 53, "1982-01-01 is in w53"); +assert.sameValue(cal.weekOfYear("1982-01-02"), 53, "1982-01-02 is in w53"); +assert.sameValue(cal.weekOfYear("1982-01-03"), 53, "1982-01-03 is in w53"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..99482299fabf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.weekOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..81a165f10756 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.weekOfYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..698532003e1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.weekOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..29962e7b7a2c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.weekOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/basic.js new file mode 100644 index 000000000000..2249b2200b56 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Basic tests for weekOfYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 44; +assert.sameValue(iso.weekOfYear(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.weekOfYear(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.weekOfYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.weekOfYear("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.weekOfYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js index cda790cee422..feb0c7824589 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js @@ -12,14 +12,16 @@ const weekOfYear = Temporal.Calendar.prototype.weekOfYear; assert.sameValue(typeof weekOfYear, "function"); -assert.throws(TypeError, () => weekOfYear.call(undefined), "undefined"); -assert.throws(TypeError, () => weekOfYear.call(null), "null"); -assert.throws(TypeError, () => weekOfYear.call(true), "true"); -assert.throws(TypeError, () => weekOfYear.call(""), "empty string"); -assert.throws(TypeError, () => weekOfYear.call(Symbol()), "symbol"); -assert.throws(TypeError, () => weekOfYear.call(1), "1"); -assert.throws(TypeError, () => weekOfYear.call({}), "plain object"); -assert.throws(TypeError, () => weekOfYear.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => weekOfYear.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = new Temporal.PlainDate(2021, 7, 20); + +assert.throws(TypeError, () => weekOfYear.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => weekOfYear.call(null, arg), "null"); +assert.throws(TypeError, () => weekOfYear.call(true, arg), "true"); +assert.throws(TypeError, () => weekOfYear.call("", arg), "empty string"); +assert.throws(TypeError, () => weekOfYear.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => weekOfYear.call(1, arg), "1"); +assert.throws(TypeError, () => weekOfYear.call({}, arg), "plain object"); +assert.throws(TypeError, () => weekOfYear.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => weekOfYear.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/builtin.js new file mode 100644 index 000000000000..bad917970669 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Tests that Temporal.Calendar.prototype.weekOfYear + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.weekOfYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.weekOfYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.weekOfYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.weekOfYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..ec8530b8a036 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.weekOfYear({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-fields-iterable.js new file mode 100644 index 000000000000..1d22e37f685e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.weekofyear step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.weekOfYear({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-temporal-object.js new file mode 100644 index 000000000000..1149907743aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.weekofyear step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.weekOfYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/cross-year.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/cross-year.js new file mode 100644 index 000000000000..e32e6377d888 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/cross-year.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: weekOfYear() crossing year boundaries. +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +assert.sameValue(iso.weekOfYear(Temporal.PlainDate.from("2019-12-31")), 1, "week 1 from next year"); +assert.sameValue(iso.weekOfYear(Temporal.PlainDate.from("2021-01-01")), 53, "week 1 from next year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..6a5c4582183e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.weekofyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.weekOfYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.weekOfYear({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/length.js new file mode 100644 index 000000000000..0dea48edaa30 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Temporal.Calendar.prototype.weekOfYear.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.weekOfYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/name.js new file mode 100644 index 000000000000..155077ed42cf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Temporal.Calendar.prototype.weekOfYear.name is "weekOfYear". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.weekOfYear, "name", { + value: "weekOfYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/not-a-constructor.js new file mode 100644 index 000000000000..fcb6898f30cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Temporal.Calendar.prototype.weekOfYear does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.weekOfYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.weekOfYear), false, + "isConstructor(Temporal.Calendar.prototype.weekOfYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/prop-desc.js new file mode 100644 index 000000000000..d64279f5fb4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: The "weekOfYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.weekOfYear, + "function", + "`typeof Calendar.prototype.weekOfYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "weekOfYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/year-zero.js new file mode 100644 index 000000000000..ee65a5a7b30f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.weekOfYear(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js new file mode 100644 index 000000000000..bea6611e78ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.year(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..696add2c5b10 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.year(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..c4b7cffc1f0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.year(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..656af7e14022 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.year(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..be659d038776 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.year(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..8fd76aac1694 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.year(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/basic.js new file mode 100644 index 000000000000..e8f878fdbc52 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/basic.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Basic tests for year(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 1994; +assert.sameValue(iso.year(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.year(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.year(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +assert.sameValue(iso.year({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.year("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.year({ month: 5 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/branding.js index b10c4e5cc091..1c36c604d42c 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/branding.js @@ -12,14 +12,16 @@ const year = Temporal.Calendar.prototype.year; assert.sameValue(typeof year, "function"); -assert.throws(TypeError, () => year.call(undefined), "undefined"); -assert.throws(TypeError, () => year.call(null), "null"); -assert.throws(TypeError, () => year.call(true), "true"); -assert.throws(TypeError, () => year.call(""), "empty string"); -assert.throws(TypeError, () => year.call(Symbol()), "symbol"); -assert.throws(TypeError, () => year.call(1), "1"); -assert.throws(TypeError, () => year.call({}), "plain object"); -assert.throws(TypeError, () => year.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => year.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => year.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => year.apply(null, args), "null"); +assert.throws(TypeError, () => year.apply(true, args), "true"); +assert.throws(TypeError, () => year.apply("", args), "empty string"); +assert.throws(TypeError, () => year.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => year.apply(1, args), "1"); +assert.throws(TypeError, () => year.apply({}, args), "plain object"); +assert.throws(TypeError, () => year.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => year.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/builtin.js new file mode 100644 index 000000000000..5ac001b48880 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + Tests that Temporal.Calendar.prototype.year + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.year), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.year), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.year), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.year.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..a050453a3191 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.year({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-fields-iterable.js new file mode 100644 index 000000000000..d95e15afcd5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.year step 4: + 4. Return ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.year({ year: 2000, month: 5, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-temporal-object.js new file mode 100644 index 000000000000..4f223f06acff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.year step 4: + 4. Return ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const calendar = new Temporal.Calendar("iso8601"); + calendar.year({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date-time.js index 1e7efe44a18c..ce4b9090e79a 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date-time.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date-time.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.year -description: Temporal.Calendar.prototype.year will take PlainDateTime and return +description: > + Temporal.Calendar.prototype.year will take PlainDateTime and return the value of the year. info: | 1. Let calendar be the this value. diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date.js index d60d2641e5cc..cfe9eb744932 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.year -description: Temporal.Calendar.prototype.year will take PlainDate and return +description: > + Temporal.Calendar.prototype.year will take PlainDate and return the value of the year. info: | 1. Let calendar be the this value. diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..e81bc6f48895 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.year +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.year({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.year({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/length.js new file mode 100644 index 000000000000..ffcb847b7d92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Temporal.Calendar.prototype.year.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.year, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/name.js new file mode 100644 index 000000000000..107397ad9494 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Temporal.Calendar.prototype.year.name is "year". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.year, "name", { + value: "year", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/not-a-constructor.js new file mode 100644 index 000000000000..bc6a631dc240 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + Temporal.Calendar.prototype.year does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.year(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.year), false, + "isConstructor(Temporal.Calendar.prototype.year)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/prop-desc.js new file mode 100644 index 000000000000..963969da91b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: The "year" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.year, + "function", + "`typeof Calendar.prototype.year` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "year", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/string.js index ab64a1fb270c..98198babcb21 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/string.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/string.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.year -description: Temporal.Calendar.prototype.year will take ISO8601 string and return +description: > + Temporal.Calendar.prototype.year will take ISO8601 string and return the value of the year. info: | 1. Let calendar be the this value. diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-range-error-ToTemporalDate.js index f71d9c4b7a88..9fd959681b2e 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-range-error-ToTemporalDate.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-range-error-ToTemporalDate.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.year -description: Temporal.Calendar.prototype.year throws RangeError on +description: > + Temporal.Calendar.prototype.year throws RangeError on ToTemporalDate when temporalDateLike is invalid string. info: | 4. If Type(temporalDateLike) is not Object or temporalDateLike diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-type-error-RequireInternalSlot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-type-error-RequireInternalSlot.js deleted file mode 100644 index dc2fd40ec954..000000000000 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-type-error-RequireInternalSlot.js +++ /dev/null @@ -1,19 +0,0 @@ -// |reftest| skip -- Temporal is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.calendar.prototype.year -description: Temporal.Calendar.prototype.year throws TypeError on - RequireInternalSlot if object has no internal slot. -info: | - 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). -features: [Temporal, arrow-function] ----*/ -let cal = new Temporal.Calendar("iso8601"); - -let badCal = { year: cal.year } -assert.throws(TypeError, () => badCal.year("2021-03-04"), - 'badCal.year("2021-03-04") throws a TypeError exception'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-month.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-month.js index b7dde054f6ee..8e41f681fc14 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-month.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-month.js @@ -4,7 +4,8 @@ /*--- esid: sec-temporal.calendar.prototype.year -description: Temporal.Calendar.prototype.year will take PlainYearMonth and return +description: > + Temporal.Calendar.prototype.year will take PlainYearMonth and return the value of the year. info: | 1. Let calendar be the this value. diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-zero.js new file mode 100644 index 000000000000..9ce68d325a4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.year(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js new file mode 100644 index 000000000000..9785663d2bcb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields return correctly with valid data. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") + +let result = cal.yearMonthFromFields({ year: 2021, month: 7 }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "year 2021, month 7"); +result = cal.yearMonthFromFields({ year: 2021, month: 12 }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "year 2021, month 12"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "year 2021, monthCode M07"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "year 2021, monthCode M12"); + +["constrain", "reject"].forEach((overflow) => { + const opt = { overflow }; + result = cal.yearMonthFromFields({ year: 2021, month: 7 }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", `year 2021, month 7, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, month: 12 }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", `year 2021, month 12, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", `year 2021, monthCode M07, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", `year 2021, monthCode M12, overflow ${overflow}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js index 04610b19709e..dc74d069f5a1 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js @@ -12,14 +12,16 @@ const yearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; assert.sameValue(typeof yearMonthFromFields, "function"); -assert.throws(TypeError, () => yearMonthFromFields.call(undefined), "undefined"); -assert.throws(TypeError, () => yearMonthFromFields.call(null), "null"); -assert.throws(TypeError, () => yearMonthFromFields.call(true), "true"); -assert.throws(TypeError, () => yearMonthFromFields.call(""), "empty string"); -assert.throws(TypeError, () => yearMonthFromFields.call(Symbol()), "symbol"); -assert.throws(TypeError, () => yearMonthFromFields.call(1), "1"); -assert.throws(TypeError, () => yearMonthFromFields.call({}), "plain object"); -assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = { year: 2021, month: 1 }; + +assert.throws(TypeError, () => yearMonthFromFields.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => yearMonthFromFields.call(null, arg), "null"); +assert.throws(TypeError, () => yearMonthFromFields.call(true, arg), "true"); +assert.throws(TypeError, () => yearMonthFromFields.call("", arg), "empty string"); +assert.throws(TypeError, () => yearMonthFromFields.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => yearMonthFromFields.call(1, arg), "1"); +assert.throws(TypeError, () => yearMonthFromFields.call({}, arg), "plain object"); +assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/builtin.js new file mode 100644 index 000000000000..0fdda4247fc9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: > + Tests that Temporal.Calendar.prototype.yearMonthFromFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.yearMonthFromFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.yearMonthFromFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.yearMonthFromFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.yearMonthFromFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js new file mode 100644 index 000000000000..4e751f5ce915 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields will throw TypeError with incorrect input data type. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") + +assert.throws(TypeError, () => cal.yearMonthFromFields({}), "at least one correctly spelled property is required"); +assert.throws(TypeError, () => cal.yearMonthFromFields({ month: 1 }), "year is required"); +assert.throws(TypeError, () => cal.yearMonthFromFields({ year: 2021 }), "month or monthCode is required"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js new file mode 100644 index 000000000000..4c14ec0d194c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw a TypeError if the fields is not an object +features: [Symbol, Temporal] +---*/ + +const tests = [undefined, null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; +const iso = Temporal.Calendar.from("iso8601"); +for (const fields of tests) { + assert.throws(TypeError, () => iso.yearMonthFromFields(fields, {})); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..062586439500 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.yearmonthfromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.yearMonthFromFields({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.yearMonthFromFields({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/length.js new file mode 100644 index 000000000000..db596e5599ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.yearMonthFromFields, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js new file mode 100644 index 000000000000..a57a16ffc2ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw RangeError for an out-of-range, conflicting, or ill-formed monthCode +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +["m1", "M1", "m01"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, monthCode }), + `monthCode '${monthCode}' is not well-formed`); +}); + +assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, month: 12, monthCode: "M11" }), + "monthCode and month conflict"); + +["M00", "M19", "M99", "M13"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, monthCode }), + `monthCode '${monthCode}' is not valid for year 2021`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/name.js new file mode 100644 index 000000000000..2d8b990950a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields.name is "yearMonthFromFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.yearMonthFromFields, "name", { + value: "yearMonthFromFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/not-a-constructor.js new file mode 100644 index 000000000000..b505f3068f5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: > + Temporal.Calendar.prototype.yearMonthFromFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.yearMonthFromFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.yearMonthFromFields), false, + "isConstructor(Temporal.Calendar.prototype.yearMonthFromFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js new file mode 100644 index 000000000000..77a9e9e8a0c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw a TypeError if options is not an object or undefined +info: | + 5. Set options to ? GetOptionsObject(options). +features: [Symbol, Temporal] +---*/ + +const tests = [null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; +const iso = new Temporal.Calendar("iso8601"); +for (const options of tests) { + assert.throws(TypeError, () => iso.yearMonthFromFields({ year: 2021, month: 7 }, options), + "options is not object"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js new file mode 100644 index 000000000000..0c3accf759ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js @@ -0,0 +1,94 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields will return correctly with data and overflow set to 'constrain'. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") +const opt = { overflow: "constrain" }; + +let result = cal.yearMonthFromFields({ year: 2021, month: 1 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 1, "M01", "month 1 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 2 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 2, "M02", "month 2 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 3 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 3, "M03", "month 3 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 4 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 4, "M04", "month 4 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 5 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 5, "M05", "month 5 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 6 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 6, "M06", "month 6 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 7 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "month 7 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 8 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 8, "M08", "month 8 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 9 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 9, "M09", "month 9 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 10 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 10, "M10", "month 10 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 11 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 11, "M11", "month 11 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 12 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 12 with overflow constrain"); + +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: -99999 }, opt), + "negative month -99999 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: -1 }, opt), + "negative month -1 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: 0 }, opt), + "month zero is out of range even with overflow constrain" +) + +result = cal.yearMonthFromFields({ year: 2021, month: 13 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 13 is constrained to 12"); +result = cal.yearMonthFromFields({ year: 2021, month: 99999 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 99999 is constrained to 12"); + +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M01" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 1, "M01", "monthCode M01 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M02" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 2, "M02", "monthCode M02 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M03" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 3, "M03", "monthCode M03 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M04" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 4, "M04", "monthCode M04 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M05" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 5, "M05", "monthCode M05 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M06" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 6, "M06", "monthCode M06 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "monthCode M07 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M08" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 8, "M08", "monthCode M08 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M09" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 9, "M09", "monthCode M09 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M10" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 10, "M10", "monthCode M10 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M11" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 11, "M11", "monthCode M11 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "monthCode M12 with overflow constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js new file mode 100644 index 000000000000..126567df648b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.yearmonthfromfields step 6: + 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_). +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js new file mode 100644 index 000000000000..579c4969e42c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw RangeError for input data out of range with overflow reject +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +[-1, 0, 13, 9995].forEach((month) => { + assert.throws( + RangeError, + () => cal.yearMonthFromFields({year: 2021, month, day: 5}, { overflow: "reject" }), + `Month ${month} is out of range for 2021 with overflow: reject` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-undefined.js new file mode 100644 index 000000000000..fa60c3db4b05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.yearmonthfromfields step 6: + 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +const explicit = calendar.yearMonthFromFields({ year: 2000, month: 15 }, { overflow: undefined }); +TemporalHelpers.assertPlainYearMonth(explicit, 2000, 12, "M12", "default overflow is constrain"); +const implicit = calendar.yearMonthFromFields({ year: 2000, month: 15 }, {}); +TemporalHelpers.assertPlainYearMonth(implicit, 2000, 12, "M12", "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js new file mode 100644 index 000000000000..5cdf0b1c552c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.yearmonthfromfields step 6: + 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/prop-desc.js new file mode 100644 index 000000000000..95d5bca68c14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: The "yearMonthFromFields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.yearMonthFromFields, + "function", + "`typeof Calendar.prototype.yearMonthFromFields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "yearMonthFromFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/basic.js b/js/src/tests/test262/built-ins/Temporal/Duration/basic.js new file mode 100644 index 000000000000..7ef099c7030b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Basic constructor tests. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertDuration(new Temporal.Duration(5, 5, 5, 5, 5, 5, 5, 5, 5, 0), + 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, "positive"); +TemporalHelpers.assertDuration(new Temporal.Duration(-5, -5, -5, -5, -5, -5, -5, -5, -5, 0), + -5, -5, -5, -5, -5, -5, -5, -5, -5, 0, "negative"); +TemporalHelpers.assertDuration(new Temporal.Duration(-0, -0, -0, -0, -0, -0, -0, -0, -0, -0), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "negative zero"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/builtin.js new file mode 100644 index 000000000000..360eb1771864 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Tests that Temporal.Duration meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.Duration.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/call-builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/call-builtin.js new file mode 100644 index 000000000000..135a7a996a9b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/call-builtin.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Constructor should not call built-in functions. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +Number.isFinite = () => { throw new Test262Error("should not call Number.isFinite") }; +Math.sign = () => { throw new Test262Error("should not call Math.sign") }; + +const duration = new Temporal.Duration(1, 1); +TemporalHelpers.assertDuration(duration, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..ce1b172fc648 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Strings with fractional duration units are rounded with the correct rounding mode +features: [Temporal] +---*/ + +const expectedPos = new Temporal.Duration(0, 0, 0, 0, 1, 1, 52, 500); +const expectedNeg = new Temporal.Duration(0, 0, 0, 0, -1, -1, -52, -500); + +assert.sameValue(Temporal.Duration.compare("PT1.03125H", expectedPos), 0, + "positive fractional units rounded with correct rounding mode (first argument)"); +assert.sameValue(Temporal.Duration.compare("-PT1.03125H", expectedNeg), 0, + "negative fractional units rounded with correct rounding mode (first argument)"); +assert.sameValue(Temporal.Duration.compare(expectedPos, "PT1.03125H"), 0, + "positive fractional units rounded with correct rounding mode (second argument)"); +assert.sameValue(Temporal.Duration.compare(expectedNeg, "-PT1.03125H"), 0, + "negative fractional units rounded with correct rounding mode (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..e193eefb47ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/argument-string-negative-fractional-units.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Strings with fractional duration units are treated with the correct sign +features: [Temporal] +---*/ + +const expectedHours = new Temporal.Duration(0, 0, 0, 0, -24, -34, -4, -404, -442, -799); +const resultHours1 = Temporal.Duration.compare("-PT24.567890123H", expectedHours); +assert.sameValue(resultHours1, 0, "negative fractional hours (first argument)"); +const resultHours2 = Temporal.Duration.compare(expectedHours, "-PT24.567890123H"); +assert.sameValue(resultHours2, 0, "negative fractional hours (second argument)"); + +const expectedMinutes = new Temporal.Duration(0, 0, 0, 0, 0, -1440, -34, -73, -407, -379); +const resultMinutes1 = Temporal.Duration.compare("-PT1440.567890123M", expectedMinutes); +assert.sameValue(resultMinutes1, 0, "negative fractional minutes (first argument)"); +const resultMinutes2 = Temporal.Duration.compare("-PT1440.567890123M", expectedMinutes); +assert.sameValue(resultMinutes2, 0, "negative fractional minutes (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/era/browser.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/era/browser.js rename to js/src/tests/test262/built-ins/Temporal/Duration/compare/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/builtin.js new file mode 100644 index 000000000000..b7563288a450 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Tests that Temporal.Duration.compare meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.compare), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.compare), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.compare), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.compare.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..1e1127233c2a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +const duration1 = new Temporal.Duration(0, 0, 1); +const duration2 = new Temporal.Duration(0, 0, 1); +Temporal.Duration.compare(duration1, duration2, { relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 4); +// one call in CalculateOffsetShift for each duration argument, plus one in +// UnbalanceDurationRelative for each duration argument + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..5757d639f318 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const relativeTo = new Temporal.PlainDate(2000, 1, 1, calendar); +calendar.specificPlainDate = relativeTo; +Temporal.Duration.compare(new Temporal.Duration(1, 1, 1, 1), new Temporal.Duration(1, 1, 1), { relativeTo }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-fields-iterable.js new file mode 100644 index 000000000000..91184fe4bd72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-fields-iterable.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.duration.compare step 4: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-possibly-required.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-possibly-required.js new file mode 100644 index 000000000000..2931cdbdfc57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-possibly-required.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: relativeTo argument needed if days = 0 but years/months/weeks non-zero +features: [Temporal] +---*/ +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +const duration3 = new Temporal.Duration(0, 0, 5); +const duration4 = new Temporal.Duration(0, 0, 0, 42); +const relativeTo = new Temporal.PlainDate(2021, 12, 15); +assert.throws( + RangeError, + () => { Temporal.Duration.compare(duration1, duration1); }, + "cannot compare Duration values without relativeTo if year is non-zero" +); +assert.sameValue(0, + Temporal.Duration.compare(duration1, duration1, { relativeTo }), + "compare succeeds for year-only Duration provided relativeTo is supplied"); +assert.throws( + RangeError, + () => { Temporal.Duration.compare(duration2, duration2); }, + "cannot compare Duration values without relativeTo if month is non-zero" +); +assert.sameValue(0, + Temporal.Duration.compare(duration2, duration2, { relativeTo }), + "compare succeeds for year-and-month Duration provided relativeTo is supplied"); +assert.throws( + RangeError, + () => { Temporal.Duration.compare(duration3, duration3); }, + "cannot compare Duration values without relativeTo if week is non-zero" +); +assert.sameValue(0, + Temporal.Duration.compare(duration3, duration3, { relativeTo }), + "compare succeeds for year-and-month-and-week Duration provided relativeTo is supplied" +); + +assert.sameValue(0, + Temporal.Duration.compare(duration4, duration4), + "compare succeeds for zero year-month-week non-zero day Duration even without relativeTo"); + +// Double-check that the comparison also works with a relative-to argument +assert.sameValue(0, + Temporal.Duration.compare(duration4, duration4, { relativeTo }), + "compare succeeds for zero year-month-week non-zero day Duration with relativeTo" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-temporal-object.js new file mode 100644 index 000000000000..1a3fec843153 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.duration.compare step 4: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 12); + Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar: temporalObject } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/length.js new file mode 100644 index 000000000000..c803a55f4344 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Temporal.Duration.compare.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.compare, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/name.js new file mode 100644 index 000000000000..7d192b02febc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Temporal.Duration.compare.name is "compare". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.compare, "name", { + value: "compare", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/not-a-constructor.js new file mode 100644 index 000000000000..59fc9cd6d9a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Temporal.Duration.compare does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.compare(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.compare), false, + "isConstructor(Temporal.Duration.compare)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/options-undefined.js new file mode 100644 index 000000000000..2a611c16020d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/options-undefined.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2), "default relativeTo is undefined"); +assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, undefined), "default relativeTo is undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/prop-desc.js new file mode 100644 index 000000000000..1d547f6592f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: The "compare" property of Temporal.Duration +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.compare, + "function", + "`typeof Duration.compare` is `function`" +); + +verifyProperty(Temporal.Duration, "compare", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..e4572a64067f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/read-time-fields-before-datefromfields.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.duration.compare step 4: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.g: + g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInvalidGettersTime(); +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..a069fd2587ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the relativeTo property bag is Infinity or -Infinity +esid: sec-temporal.duration.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(0, 0, 0, 1); +const duration2 = new Temporal.Duration(0, 0, 0, 0, 24); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..d9f57ab52774 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(1, 1); + assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..d13dce4000bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.duration.compare +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(1, 1); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..b6956fd4d343 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(1, 1); + assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..98b7bbd6e9ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(1, 1); + assert.throws(TypeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-invalid.js new file mode 100644 index 000000000000..884ca217e9dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-invalid.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: RangeError thrown if relativeTo is a string with the wrong format +features: [Temporal] +---*/ + +['bad string', '15:30:45.123456', 'iso8601', 'UTC', 'P1YT1H'].forEach((relativeTo) => { + const duration1 = new Temporal.Duration(0, 0, 0, 31); + const duration2 = new Temporal.Duration(0, 1); + assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-plaindatetime.js new file mode 100644 index 000000000000..db3a52adf5d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-plaindatetime.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: The relativeTo option accepts a PlainDateTime-like ISO 8601 string +features: [Temporal] +---*/ + +['2000-01-01', '2000-01-01T00:00', '2000-01-01T00:00[u-ca=iso8601]'].forEach((relativeTo) => { + const duration1 = new Temporal.Duration(0, 0, 0, 31); + const duration2 = new Temporal.Duration(0, 1); + const result = Temporal.Duration.compare(duration1, duration2, { relativeTo }); + assert.sameValue(result, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-zoneddatetime-wrong-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-zoneddatetime-wrong-offset.js new file mode 100644 index 000000000000..c3115d77a8da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-zoneddatetime-wrong-offset.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Throws if a ZonedDateTime-like relativeTo string has the wrong UTC offset +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(0, 0, 0, 31); +const duration2 = new Temporal.Duration(0, 1); +const relativeTo = "2000-01-01T00:00+05:30[UTC]"; +assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-zoneddatetime.js new file mode 100644 index 000000000000..e99eec53994a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-string-zoneddatetime.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: The relativeTo option accepts a ZonedDateTime-like ISO 8601 string +features: [Temporal] +---*/ + +[ + '2000-01-01[UTC]', + '2000-01-01T00:00[UTC]', + '2000-01-01T00:00+00:00[UTC]', + '2000-01-01T00:00+00:00[UTC][u-ca=iso8601]', +].forEach((relativeTo) => { + const duration1 = new Temporal.Duration(0, 0, 0, 31); + const duration2 = new Temporal.Duration(0, 1); + const result = Temporal.Duration.compare(duration1, duration2, { relativeTo }); + assert.sameValue(result, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-sub-minute-offset.js new file mode 100644 index 000000000000..1b9ba351998f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-sub-minute-offset.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: relativeTo string accepts an inexact UTC offset rounded to hours and minutes +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(0, 0, 0, 31); +const duration2 = new Temporal.Duration(0, 1); + +let relativeTo = "2000-01-01T00:00+00:45[+00:44:30.123456789]"; +assert.sameValue(Temporal.Duration.compare(duration1, duration2, { relativeTo }), 0, "rounded HH:MM is accepted in string"); + +relativeTo = "2000-01-01T00:00+00:44:30[+00:44:30.123456789]"; +assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo }), "no other rounding is accepted for offset"); + +const timeZone = new Temporal.TimeZone("+00:44:30.123456789"); +relativeTo = { year: 2000, month: 1, day: 1, offset: "+00:45", timeZone }; +assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo }), "rounded HH:MM not accepted as offset in property bag"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-undefined-throw-on-calendar-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-undefined-throw-on-calendar-units.js new file mode 100644 index 000000000000..74639412b177 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-undefined-throw-on-calendar-units.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: > + The relativeTo option is required when either Duration contains years, + months, or weeks +features: [Temporal] +---*/ + +const oneYear = new Temporal.Duration(1); +const oneMonth = new Temporal.Duration(0, 1); +const oneWeek = new Temporal.Duration(0, 0, 1); +const oneDay = new Temporal.Duration(0, 0, 0, 1); + +assert.sameValue(Temporal.Duration.compare(oneDay, oneDay), 0, "days do not require relativeTo"); + +assert.throws(RangeError, () => Temporal.Duration.compare(oneWeek, oneDay), "weeks in left operand require relativeTo"); +assert.throws(RangeError, () => Temporal.Duration.compare(oneDay, oneWeek), "weeks in right operand require relativeTo"); + +assert.throws(RangeError, () => Temporal.Duration.compare(oneMonth, oneDay), "months in left operand require relativeTo"); +assert.throws(RangeError, () => Temporal.Duration.compare(oneDay, oneMonth), "months in right operand require relativeTo"); + +assert.throws(RangeError, () => Temporal.Duration.compare(oneYear, oneDay), "years in left operand require relativeTo"); +assert.throws(RangeError, () => Temporal.Duration.compare(oneDay, oneYear), "years in right operand require relativeTo"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..ab1f81f9c5d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const relativeTo = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time; in this +// case via relativeTo. + +const result = Temporal.Duration.compare(duration, duration, { relativeTo }); +assert.sameValue(result, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..36b4ca3c038b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(1, 1); + assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..ba9b4661395b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.duration.compare +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(1, 1); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.Duration.compare(duration1, duration2, { relativeTo }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..29d19a093066 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(1, 1); + assert.throws(RangeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..93ebc4a5b387 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(1, 1); + assert.throws(TypeError, () => Temporal.Duration.compare(duration1, duration2, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..625c034b3b88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.duration.compare steps 4–6: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 5. Let _shift1_ be ! CalculateOffsetShift(_relativeTo_, _one_.[[Years]], [...], _one_.[[Nanoseconds]]). + 6. Let _shift2_ be ! CalculateOffsetShift(_relativeTo_, _two_.[[Years]], [...], _two_.[[Nanoseconds]]). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-calculateoffsetshift step 4: + 4. Let _after_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], _y_, [...], _ns_). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "2000-01-01T00:00:00", // called once on the input relativeTo object + "2001-01-01T00:00:00", // called once on relativeTo plus the first operand + "2001-02-01T00:00:00", // called once on relativeTo plus the second operand +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 13); + Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 1, day: 1, timeZone } }); +}, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/timezone-string-datetime.js new file mode 100644 index 000000000000..cd16bed20038 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/timezone-string-datetime.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Duration.compare(new Temporal.Duration(), new Temporal.Duration(), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Duration.compare(new Temporal.Duration(), new Temporal.Duration(), { relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + Temporal.Duration.compare(new Temporal.Duration(), new Temporal.Duration(), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }); + Temporal.Duration.compare(new Temporal.Duration(), new Temporal.Duration(), { relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js new file mode 100644 index 000000000000..3017565091f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Unbalancing handles DST days with more than 24 hours +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tz = TemporalHelpers.springForwardFallBackTimeZone(); + +// 2000-10-29 is a 25-hour day according to this time zone... + +const relativeTo = new Temporal.ZonedDateTime(941187600_000_000_000n, tz); + +// confirm that we have rewound one year and one day: +assert.sameValue('1999-10-29T01:00:00-08:00[Custom/Spring_Fall]', relativeTo.toString()); + +const d1 = new Temporal.Duration(1, 0, 0, 1); +const d2 = new Temporal.Duration(1, 0, 0, 0, 25); + +// ...so the durations should be equal relative to relativeTo: + +assert.sameValue(0, + Temporal.Duration.compare(d1, d2, { relativeTo }), + "2000-10-29 is a 25-hour day" +); + +assert.sameValue(1, + Temporal.Duration.compare(d1, { years: 1, hours: 24 }, { relativeTo }), + "2020-10-29 has more than 24 hours" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/compare/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Duration/compare/year-zero.js new file mode 100644 index 000000000000..23f05d0bba94 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/compare/year-zero.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Negative zero, as an extended year, fails +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(2); +const bad = "-000000-11-01"; + +assert.throws( + RangeError, + () => Temporal.Duration.compare(duration1, duration2, { relativeTo: bad }), + "Cannot use negative zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/constructor.js new file mode 100644 index 000000000000..a478692f8217 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Temporal.Duration constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.Duration()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/days-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/days-undefined.js new file mode 100644 index 000000000000..022d52e3a152 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/days-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1, 1, 1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/fractional-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/fractional-throws-rangeerror.js new file mode 100644 index 000000000000..bd34d56d720a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/fractional-throws-rangeerror.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration throws a RangeError if any value is fractional +esid: sec-temporal.duration +features: [Temporal] +---*/ + +const descriptions = [ + 'years', + 'months', + 'weeks', + 'days', + 'hours', + 'minutes', + 'seconds', + 'milliseconds', + 'microseconds', + 'nanoseconds' +].map((time) => `Duration constructor throws RangeError with fractional value in the ${time} position`); + +assert.throws(RangeError, () => new Temporal.Duration(1.1), descriptions[0]); +assert.throws(RangeError, () => new Temporal.Duration(0, 1.1), descriptions[1]); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 1.1), descriptions[2]); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 1.1), descriptions[3]); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 1.1), descriptions[4]); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 1.1), descriptions[5]); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 1.1), descriptions[6]); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 1.1), descriptions[7]); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 1.1), descriptions[8]); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1.1), descriptions[9]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-existing-object.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-existing-object.js new file mode 100644 index 000000000000..bdbbba4276d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-existing-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Property bag is converted to Duration; Duration is copied +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const d1 = Temporal.Duration.from({ milliseconds: 1000, month: 1 }); +TemporalHelpers.assertDuration(d1, 0, 0, 0, 0, 0, 0, 0, 1000, 0, 0); + +const d2 = Temporal.Duration.from(d1); +assert.notSameValue(d1, d2); +TemporalHelpers.assertDuration(d1, 0, 0, 0, 0, 0, 0, 0, 1000, 0, 0); +TemporalHelpers.assertDuration(d2, 0, 0, 0, 0, 0, 0, 0, 1000, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-non-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-non-string.js new file mode 100644 index 000000000000..c70979456e76 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-non-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Appropriate error thrown if primitive input cannot convert to a valid string +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.Duration.from(undefined), "undefined"); +assert.throws(RangeError, () => Temporal.Duration.from(null), "null"); +assert.throws(RangeError, () => Temporal.Duration.from(true), "boolean"); +assert.throws(TypeError, () => Temporal.Duration.from(Symbol()), "Symbol"); +assert.throws(RangeError, () => Temporal.Duration.from(5), "number"); +assert.throws(RangeError, () => Temporal.Duration.from(5n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-object-invalid.js new file mode 100644 index 000000000000..8977be7ffe47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-object-invalid.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Invalid object arguments. +features: [Temporal] +---*/ + +const tests = [ + { years: 0.5 }, + { months: 0.5 }, + { weeks: 0.5 }, + { days: 0.5 }, + { hours: 0.5, minutes: 20 }, + { hours: 0.5, seconds: 15 }, + { minutes: 10.7, nanoseconds: 400 }, + { hours: 1, minutes: -30 }, +]; + +for (const input of tests) { + assert.throws(RangeError, () => Temporal.Duration.from(input)); +} + +assert.throws(TypeError, () => Temporal.Duration.from({})); +assert.throws(TypeError, () => Temporal.Duration.from({ month: 12 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..92a58c77dcce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const resultPosHours = Temporal.Duration.from("PT1.03125H"); +TemporalHelpers.assertDuration(resultPosHours, 0, 0, 0, 0, 1, 1, 52, 500, 0, 0, + "positive fractional hours rounded with correct rounding mode"); + +const resultNegHours = Temporal.Duration.from("-PT1.03125H"); +TemporalHelpers.assertDuration(resultNegHours, 0, 0, 0, 0, -1, -1, -52, -500, 0, 0, + "negative fractional hours rounded with correct rounding mode"); + +// The following input should not round, but may fail if an implementation does +// floating point arithmetic too early: + +const resultPosSeconds = Temporal.Duration.from("PT46H66M71.50040904S"); +TemporalHelpers.assertDuration(resultPosSeconds, 0, 0, 0, 0, 46, 66, 71, 500, 409, 40, + "positive fractional seconds not rounded"); + +const resultNegSeconds = Temporal.Duration.from("-PT46H66M71.50040904S"); +TemporalHelpers.assertDuration(resultNegSeconds, 0, 0, 0, 0, -46, -66, -71, -500, -409, -40, + "negative fractional seconds not rounded"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-invalid.js new file mode 100644 index 000000000000..413c38697182 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-invalid.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Invalid string arguments. +features: [Temporal] +---*/ + +const tests = [ + "P1Y1M1W1DT1H1M1.123456789123S", + "P0.5Y", + "P1Y0,5M", + "P1Y1M0.5W", + "P1Y1M1W0,5D", + "P1Y1M1W1DT0.5H5S", + "P1Y1M1W1DT1.5H0,5M", + "P1Y1M1W1DT1H0.5M0.5S", + "P", + "PT", + "-P", + "-PT", + "+P", + "+PT", + "P1Y1M1W1DT1H1M1.01Sjunk", + "P-1Y1M", + "P1Y-1M" +]; + +for (const input of tests) { + assert.throws(RangeError, () => Temporal.Duration.from(input)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..970ff7cb873f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string-negative-fractional-units.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const resultHours = Temporal.Duration.from("-PT24.567890123H"); +TemporalHelpers.assertDuration(resultHours, 0, 0, 0, 0, -24, -34, -4, -404, -442, -799, "negative fractional hours"); + +const resultMinutes = Temporal.Duration.from("-PT1440.567890123M"); +TemporalHelpers.assertDuration(resultMinutes, 0, 0, 0, 0, 0, -1440, -34, -73, -407, -379, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string.js new file mode 100644 index 000000000000..6d6b1d198a8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/argument-string.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Basic string arguments. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertDuration(Temporal.Duration.from("P1D"), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("p1y1m1dt1h1m1s"), + 1, 1, 0, 1, 1, 1, 1, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.1S"), + 1, 1, 1, 1, 1, 1, 1, 100, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.12S"), + 1, 1, 1, 1, 1, 1, 1, 120, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.123S"), + 1, 1, 1, 1, 1, 1, 1, 123, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.1234S"), + 1, 1, 1, 1, 1, 1, 1, 123, 400, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.12345S"), + 1, 1, 1, 1, 1, 1, 1, 123, 450, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.123456S"), + 1, 1, 1, 1, 1, 1, 1, 123, 456, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.1234567S"), + 1, 1, 1, 1, 1, 1, 1, 123, 456, 700); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.12345678S"), + 1, 1, 1, 1, 1, 1, 1, 123, 456, 780); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.123456789S"), + 1, 1, 1, 1, 1, 1, 1, 123, 456, 789); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1,12S"), + 1, 1, 1, 1, 1, 1, 1, 120, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1DT0.5M"), + 0, 0, 0, 1, 0, 0, 30, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1DT0,5H"), + 0, 0, 0, 1, 0, 30, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("+P1D"), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("-P1D"), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("\u2212P1D"), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("-P1Y1M1W1DT1H1M1.123456789S"), + -1, -1, -1, -1, -1, -1, -1, -123, -456, -789); +TemporalHelpers.assertDuration(Temporal.Duration.from("PT100M"), + 0, 0, 0, 0, 0, 100, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/eraYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/eraYear/browser.js rename to js/src/tests/test262/built-ins/Temporal/Duration/from/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/builtin.js new file mode 100644 index 000000000000..acec25b5b836 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Tests that Temporal.Duration.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f34e2dcc8f80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/infinity-throws-rangeerror.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration.from handles a property bag if any value is Infinity +esid: sec-temporal.duration.from +features: [Temporal] +---*/ + +const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds']; + +fields.forEach((field) => { + assert.throws(RangeError, () => Temporal.Duration.from({ [field]: Infinity })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => Temporal.Duration.from({ [field]: obj })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/length.js new file mode 100644 index 000000000000..12c629055c6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Temporal.Duration.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/name.js new file mode 100644 index 000000000000..1c0450948e50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Temporal.Duration.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/negative-inifinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/negative-inifinity-throws-rangeerror.js new file mode 100644 index 000000000000..9a922515965b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/negative-inifinity-throws-rangeerror.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration.from handles a property bag if any value is -Infinity +esid: sec-temporal.duration.from +features: [Temporal] +---*/ + +const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds']; + +fields.forEach((field) => { + assert.throws(RangeError, () => Temporal.Duration.from({ [field]: -Infinity })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => Temporal.Duration.from({ [field]: obj })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..0c7c5d3d7074 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/non-integer-throws-rangeerror.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => Temporal.Duration.from({ [field]: 1.5 })); + assert.throws(RangeError, () => Temporal.Duration.from({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/not-a-constructor.js new file mode 100644 index 000000000000..9c63d7c25c0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Temporal.Duration.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.from), false, + "isConstructor(Temporal.Duration.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/order-of-operations.js new file mode 100644 index 000000000000..c667c1ec1330 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/order-of-operations.js @@ -0,0 +1,72 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Properties on an object passed to from() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = Temporal.Duration.from(argument); +TemporalHelpers.assertDuration(result, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/prop-desc.js new file mode 100644 index 000000000000..37979083e088 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: The "from" property of Temporal.Duration +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.from, + "function", + "`typeof Duration.from` is `function`" +); + +verifyProperty(Temporal.Duration, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/string-with-skipped-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/string-with-skipped-units.js new file mode 100644 index 000000000000..b26bb30fbd9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/string-with-skipped-units.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: | + Creating a Duration from an ISO 8601 string with an absent designator between + two other designators +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// Date designators: years-weeks (months missing) + +const d1 = Temporal.Duration.from("P3Y4W"); +TemporalHelpers.assertDuration(d1, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, "years-weeks string"); + +// Date designators: years-days (months and weeks missing) + +const d2 = Temporal.Duration.from("P3Y4D"); +TemporalHelpers.assertDuration(d2, 3, 0, 0, 4, 0, 0, 0, 0, 0, 0, "years-days string"); + +// Date designators: months-days (weeks missing) + +const d3 = Temporal.Duration.from("P3M4D"); +TemporalHelpers.assertDuration(d3, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, "months-days string"); + +// Time designators: hours-seconds (minutes missing) + +const d4 = Temporal.Duration.from("PT3H4.123456789S"); +TemporalHelpers.assertDuration(d4, 0, 0, 0, 0, 3, 0, 4, 123, 456, 789, "hours-seconds string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Duration/from/subclassing-ignored.js new file mode 100644 index 000000000000..dee881c8991a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/from/subclassing-ignored.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.Duration, + "from", + ["P1Y2M3W4DT5H6M7.987654321S"], + (result) => TemporalHelpers.assertDuration(result, 1, 2, 3, 4, 5, 6, 7, 987, 654, 321), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/hours-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/hours-undefined.js new file mode 100644 index 000000000000..60772a85674c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/hours-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1, 1, 1, 1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..d838026d2503 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/infinity-throws-rangeerror.js @@ -0,0 +1,84 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration throws a RangeError if any value is Infinity +esid: sec-temporal.duration +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.Duration(Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite years", + [O(Infinity, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf"] + ], + [ + "infinite months", + [O(0, "years"), O(Infinity, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf"] + ], + [ + "infinite weeks", + [O(0, "years"), O(0, "months"), O(Infinity, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf"] + ], + [ + "infinite days", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(Infinity, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf"] + ], + [ + "infinite hours", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(Infinity, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf"] + ], + [ + "infinite minutes", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(Infinity, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf"] + ], + [ + "infinite seconds", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(Infinity, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf", "get seconds.valueOf", "call seconds.valueOf"] + ], + [ + "infinite milliseconds", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(Infinity, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf", "get seconds.valueOf", "call seconds.valueOf", "get milliseconds.valueOf", "call milliseconds.valueOf"] + ], + [ + "infinite microseconds", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(Infinity, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf", "get seconds.valueOf", "call seconds.valueOf", "get milliseconds.valueOf", "call milliseconds.valueOf", "get microseconds.valueOf", "call microseconds.valueOf"] + ], + [ + "infinite nanoseconds", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(Infinity, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf", "get seconds.valueOf", "call seconds.valueOf", "get milliseconds.valueOf", "call milliseconds.valueOf", "get microseconds.valueOf", "call microseconds.valueOf", "get nanoseconds.valueOf", "call nanoseconds.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.Duration(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/length.js new file mode 100644 index 000000000000..19855096747c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Temporal.Duration.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/microseconds-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/microseconds-undefined.js new file mode 100644 index 000000000000..83a5b1303c8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/microseconds-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1, 1, 1, 1, 1, 1, 1, 1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/milliseconds-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/milliseconds-undefined.js new file mode 100644 index 000000000000..d56a793a9338 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/milliseconds-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1, 1, 1, 1, 1, 1, 1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/minutes-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/minutes-undefined.js new file mode 100644 index 000000000000..615666ee30be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/minutes-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1, 1, 1, 1, 1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/mixed.js b/js/src/tests/test262/built-ins/Temporal/Duration/mixed.js new file mode 100644 index 000000000000..e1754ccd2da1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/mixed.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Constructor with mixed signs. +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.Duration(-1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, -1, 1, 1, 1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, -1, 1, 1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, -1, 1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, -1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, -1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, 1, -1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, 1, 1, -1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, 1, 1, 1, -1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, 1, 1, 1, 1, -1)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/months-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/months-undefined.js new file mode 100644 index 000000000000..1dbf28a4ca01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/months-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/name.js new file mode 100644 index 000000000000..f4ddc96580ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Temporal.Duration.name is "Duration" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration, "name", { + value: "Duration", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/nanoseconds-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/nanoseconds-undefined.js new file mode 100644 index 000000000000..381053d83da6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/nanoseconds-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1, 1, 1, 1, 1, 1, 1, 1, 1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..ccf3a24a8a57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/negative-infinity-throws-rangeerror.js @@ -0,0 +1,84 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration throws a RangeError if any value is -Infinity +esid: sec-temporal.duration +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.Duration(-Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, -Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite years", + [O(-Infinity, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf"] + ], + [ + "infinite months", + [O(0, "years"), O(-Infinity, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf"] + ], + [ + "infinite weeks", + [O(0, "years"), O(0, "months"), O(-Infinity, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf"] + ], + [ + "infinite days", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(-Infinity, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf"] + ], + [ + "infinite hours", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(-Infinity, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf"] + ], + [ + "infinite minutes", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(-Infinity, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf"] + ], + [ + "infinite seconds", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(-Infinity, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf", "get seconds.valueOf", "call seconds.valueOf"] + ], + [ + "infinite milliseconds", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(-Infinity, "milliseconds"), O(0, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf", "get seconds.valueOf", "call seconds.valueOf", "get milliseconds.valueOf", "call milliseconds.valueOf"] + ], + [ + "infinite microseconds", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(-Infinity, "microseconds"), O(0, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf", "get seconds.valueOf", "call seconds.valueOf", "get milliseconds.valueOf", "call milliseconds.valueOf", "get microseconds.valueOf", "call microseconds.valueOf"] + ], + [ + "infinite nanoseconds", + [O(0, "years"), O(0, "months"), O(0, "weeks"), O(0, "days"), O(0, "hours"), O(0, "minutes"), O(0, "seconds"), O(0, "milliseconds"), O(0, "microseconds"), O(-Infinity, "nanoseconds")], + ["get years.valueOf", "call years.valueOf", "get months.valueOf", "call months.valueOf", "get weeks.valueOf", "call weeks.valueOf", "get days.valueOf", "call days.valueOf", "get hours.valueOf", "call hours.valueOf", "get minutes.valueOf", "call minutes.valueOf", "get seconds.valueOf", "call seconds.valueOf", "get milliseconds.valueOf", "call milliseconds.valueOf", "get microseconds.valueOf", "call microseconds.valueOf", "get nanoseconds.valueOf", "call nanoseconds.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.Duration(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prop-desc.js new file mode 100644 index 000000000000..bc99900a4dda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: The "Duration" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration, + "function", + "`typeof Duration` is `function`" +); + +verifyProperty(Temporal, "Duration", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/basic.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/basic.js new file mode 100644 index 000000000000..d0ca50416fff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/basic.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: Temporal.Duration.prototype.abs will return absolute value of the input duration. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Return ? CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]), abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])). + +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +let d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.abs(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "empty"); + +let d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.abs(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "positive"); + +let d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.abs(), 1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5, "large positive"); + +let d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.abs(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "negative"); + +// Test with some zeros +let d5 = new Temporal.Duration(1, 0, 3, 0, 5, 0, 7, 0, 9, 0); +TemporalHelpers.assertDuration( + d5.abs(), 1, 0, 3, 0, 5, 0, 7, 0, 9, 0, "some zeros"); + +let d6 = new Temporal.Duration(0, 2, 0, 4, 0, 6, 0, 8, 0, 10); +TemporalHelpers.assertDuration( + d6.abs(), 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, "other zeros"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/builtin.js new file mode 100644 index 000000000000..a04fcfc7f1b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: > + Tests that Temporal.Duration.prototype.abs + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.abs), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.abs), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.abs), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.abs.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/length.js new file mode 100644 index 000000000000..3258db321c06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: Temporal.Duration.prototype.abs.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.abs, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/name.js new file mode 100644 index 000000000000..3828c26727fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: Temporal.Duration.prototype.abs.name is "abs". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.abs, "name", { + value: "abs", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/not-a-constructor.js new file mode 100644 index 000000000000..ccf9dfd8a9e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: > + Temporal.Duration.prototype.abs does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.abs(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.abs), false, + "isConstructor(Temporal.Duration.prototype.abs)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/prop-desc.js new file mode 100644 index 000000000000..a27f0453817b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: The "abs" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.abs, + "function", + "`typeof Duration.prototype.abs` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "abs", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/subclassing-ignored.js new file mode 100644 index 000000000000..c72ff6d9e294 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/abs/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Duration, + [0, 0, 0, -4, -5, -6, -7, -987, -654, -321], + "abs", + [], + (result) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 5, 6, 7, 987, 654, 321), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..f4be11548441 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const blank = new Temporal.Duration(); + +TemporalHelpers.assertDuration(blank.add("PT1.03125H"), 0, 0, 0, 0, 1, 1, 52, 500, 0, 0, + "positive fractional units rounded with correct rounding mode"); +TemporalHelpers.assertDuration(blank.add("-PT1.03125H"), 0, 0, 0, 0, -1, -1, -52, -500, 0, 0, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..e092b1155087 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(); + +const resultHours = instance.add("-PT24.567890123H"); +TemporalHelpers.assertDuration(resultHours, 0, 0, 0, 0, -24, -34, -4, -404, -442, -799, "negative fractional hours"); + +const resultMinutes = instance.add("-PT1440.567890123M"); +TemporalHelpers.assertDuration(resultMinutes, 0, 0, 0, 0, 0, -1440, -34, -73, -407, -379, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/balance-negative-result.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/balance-negative-result.js new file mode 100644 index 000000000000..37253e952de7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/balance-negative-result.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: A negative duration result is balanced correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-balanceduration step 4: + 4. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + sec-temporal-addduration steps 5–6: + 5. If _relativeTo_ is *undefined*, then + ... + b. Let _result_ be ! BalanceDuration(_d1_ + _d2_, _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_). + ... + 6. Else if _relativeTo_ has an [[InitializedTemporalPlainDateTime]] internal slot, then + ... + n. Let _result_ be ! BalanceDuration(_dateDifference_.[[Days]], _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_). + sec-temporal.duration.prototype.add step 6: + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _other_.[[Years]], _other_.[[Months]], _other_.[[Weeks]], _other_.[[Days]], _other_.[[Hours]], _other_.[[Minutes]], _other_.[[Seconds]], _other_.[[Milliseconds]], _other_.[[Microseconds]], _other_.[[Nanoseconds]], _relativeTo_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(0, 0, 0, 0, -60); +const duration2 = new Temporal.Duration(0, 0, 0, -1); + +const resultNotRelative = duration1.add(duration2); +TemporalHelpers.assertDuration(resultNotRelative, 0, 0, 0, -3, -12, 0, 0, 0, 0, 0); + +const relativeTo = new Temporal.PlainDateTime(2000, 1, 1); +const resultRelative = duration1.add(duration2, { relativeTo }); +TemporalHelpers.assertDuration(resultRelative, 0, 0, 0, -3, -12, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/balance-negative-time-units.js new file mode 100644 index 000000000000..674ddc71c6ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/balance-negative-time-units.js @@ -0,0 +1,63 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Negative time fields in relativeTo are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-differenceisodatetime step 2: + 2. Let _timeDifference_ be ? DifferenceTime(_h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_). + sec-temporal-differencezoneddatetime step 7: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + sec-temporal-addduration step 7.g.i: + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal.duration.prototype.add step 6: + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _other_.[[Years]], _other_.[[Months]], _other_.[[Weeks]], _other_.[[Days]], _other_.[[Hours]], _other_.[[Minutes]], _other_.[[Seconds]], _other_.[[Milliseconds]], _other_.[[Microseconds]], _other_.[[Nanoseconds]], _relativeTo_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 1, 1, 1, 1, 1, 1); + +const timeZone = new Temporal.TimeZone("UTC"); +const relativeTo = new Temporal.ZonedDateTime(830998861_000_000_000n, timeZone); +// This code path is encountered if largestUnit is years, months, weeks, or days +// and relativeTo is a ZonedDateTime +const options = { largestUnit: "days", relativeTo }; + +const result1 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -2), options); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -2), options); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -2), options); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, -2), options); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, -2), options); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = duration.add(new Temporal.Duration(0, 0, 0, 0, -2), options); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/builtin.js new file mode 100644 index 000000000000..44de286bfa0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: > + Tests that Temporal.Duration.prototype.add + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.add), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.add), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.add), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.add.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..68b83ce2587a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.Duration(1, 1, 1, 1); +instance.add(instance, { relativeTo: new Temporal.ZonedDateTime(0n, timeZone, calendar) }); +assert.sameValue(calendar.dateAddCallCount, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..673f3cef8445 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.Duration(1, 1, 1, 1); +const relativeTo = new Temporal.PlainDate(2000, 1, 1, calendar); +calendar.specificPlainDate = relativeTo; +instance.add(instance, { relativeTo }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..44d2e160c26f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,81 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.duration.prototype.add step 6: + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _other_.[[Years]], _other_.[[Months]], _other_.[[Weeks]], _other_.[[Days]], _other_.[[Hours]], _other_.[[Minutes]], _other_.[[Seconds]], _other_.[[Milliseconds]], _other_.[[Microseconds]], _other_.[[Nanoseconds]], _relativeTo_). + sec-temporal-addduration steps 6-7: + 6. If _relativeTo_ has an [[InitializedTemporalPlainDateTime]] internal slot, then + ... + j. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + k. Let _differenceOptions_ be ! OrdinaryObjectCreate(*null*). + l. Perform ! CreateDataPropertyOrThrow(_differenceOptions_, *"largestUnit"*, _dateLargestUnit_). + m. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _datePart_, _end_, _differenceOptions_). + ... + 7. Else, + a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot. + ... + f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + g. Else, + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-differencezoneddatetime steps 7 and 11: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + 11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_). + sec-temporal-nanosecondstodays step 11: + 11. 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*). + sec-temporal-differenceisodatetime steps 9–11: + 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). + 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit, index) => { + const one = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(1)]); + const two = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(2)]); + const relativeTo = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + one.add(two, { relativeTo, largestUnit }); + }, + { + years: ["year"], + months: ["month"], + weeks: ["week"], + days: ["day"], + hours: ["day"], + minutes: ["day"], + seconds: ["day"], + milliseconds: ["day"], + microseconds: ["day"], + nanoseconds: ["day"] + } +); + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit, index) => { + const one = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(1)]); + const two = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(2)]); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); + one.add(two, { relativeTo, largestUnit }); + }, + { + years: ["year", "day"], + months: ["month", "day"], + weeks: ["week", "day"], + days: ["day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-fields-iterable.js new file mode 100644 index 000000000000..82fa2a519f31 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-fields-iterable.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.duration.prototype.add step 5: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-temporal-object.js new file mode 100644 index 000000000000..5a4757860065 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.duration.prototype.add step 5: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2b + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 12); + duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar: temporalObject } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..be90f77c6902 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/infinity-throws-rangeerror.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration.prototype.add throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.duration.prototype.add +features: [Temporal] +---*/ + +const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds']; + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDateTime(2000, 1, 1); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: Infinity }, { relativeTo })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { relativeTo })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/length.js new file mode 100644 index 000000000000..4f3dda7c0bde --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Temporal.Duration.prototype.add.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.add, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/name.js new file mode 100644 index 000000000000..ffb2252c4963 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Temporal.Duration.prototype.add.name is "add". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.add, "name", { + value: "add", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f21efe9b0202 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/negative-infinity-throws-rangeerror.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration.prototype.add throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.duration.prototype.add +features: [Temporal] +---*/ + +const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds']; + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDateTime(2000, 1, 1); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: -Infinity }, { relativeTo })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { relativeTo })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..660ada22c0c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.add({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/not-a-constructor.js new file mode 100644 index 000000000000..6ffce9bca4c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: > + Temporal.Duration.prototype.add does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.add(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.add), false, + "isConstructor(Temporal.Duration.prototype.add)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/options-undefined.js new file mode 100644 index 000000000000..bba8cdc04a34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/options-undefined.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +assert.throws(RangeError, () => duration1.add(duration2), "default relativeTo is undefined"); +assert.throws(RangeError, () => duration1.add(duration2, undefined), "default relativeTo is undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/order-of-operations.js new file mode 100644 index 000000000000..e7bf21067de1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Properties on an object passed to add() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 0, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDateTime(2000, 1, 1); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.add(argument, { relativeTo }); +TemporalHelpers.assertDuration(result, 2, 3, 0, 12, 6, 7, 8, 988, 655, 322); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/prop-desc.js new file mode 100644 index 000000000000..5fab787d47cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: The "add" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.add, + "function", + "`typeof Duration.prototype.add` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "add", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..ee1abfc2e99b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/read-time-fields-before-datefromfields.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.duration.prototype.add step 5: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.g: + g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInvalidGettersTime(); +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..0be7e08edb7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.duration.prototype.add +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.add(instance, { relativeTo: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.add(instance, { relativeTo: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-no-time-units.js new file mode 100644 index 000000000000..e4bed52a0f78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-no-time-units.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Missing time units in relativeTo property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = { year: 2000, month: 1, day: 1 }; +const result = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..a9925c68d61a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(2); + assert.throws(RangeError, () => duration.add(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..2cf033caa32c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(2); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => duration.add(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..4895657be20d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(2); + assert.throws(RangeError, () => duration.add(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..1e45b733b96e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(2); + assert.throws(TypeError, () => duration.add(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-datetime.js new file mode 100644 index 000000000000..51dc83ed7efa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-datetime.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: > + Conversion of ISO date-time strings as relativeTo option to + Temporal.ZonedDateTime or Temporal.PlainDateTime instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = "2019-11-01T00:00"; +const result1 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bare date-time string is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00Z"; +const result2 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00-07:00"; +const result3 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + offset is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00[-07:00]"; +const result4 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00Z[-07:00]"; +const result5 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+00:00[UTC]"; +const result6 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+04:15[UTC]"; +assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-invalid.js new file mode 100644 index 000000000000..4a913cf3cd8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: RangeError thrown if relativeTo is a string with the wrong format +features: [Temporal] +---*/ + +['bad string', '15:30:45.123456', 'iso8601', 'UTC', 'P1YT1H'].forEach((relativeTo) => { + const duration = new Temporal.Duration(1, 0, 0, 15); + assert.throws(RangeError, () => duration.add(new Temporal.Duration(0, 0, 0, 16), { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-plaindatetime.js new file mode 100644 index 000000000000..f73d87524018 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-plaindatetime.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: The relativeTo option accepts a PlainDateTime-like ISO 8601 string +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +['2000-01-01', '2000-01-01T00:00', '2000-01-01T00:00[u-ca=iso8601]'].forEach((relativeTo) => { + const duration = new Temporal.Duration(1, 0, 0, 15); + const result = duration.add(new Temporal.Duration(0, 0, 0, 16), { relativeTo }); + TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-zoneddatetime-wrong-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-zoneddatetime-wrong-offset.js new file mode 100644 index 000000000000..b938483e5fe8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-zoneddatetime-wrong-offset.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Throws if a ZonedDateTime-like relativeTo string has the wrong UTC offset +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); +const relativeTo = "2000-01-01T00:00+05:30[UTC]"; +assert.throws( + RangeError, + () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), + "add should throw RangeError on a string with UTC offset mismatch" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-zoneddatetime.js new file mode 100644 index 000000000000..2513a6cc5dea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-string-zoneddatetime.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: The relativeTo option accepts a ZonedDateTime-like ISO 8601 string +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + '2000-01-01[UTC]', + '2000-01-01T00:00[UTC]', + '2000-01-01T00:00+00:00[UTC]', + '2000-01-01T00:00+00:00[UTC][u-ca=iso8601]', +].forEach((relativeTo) => { + const duration = new Temporal.Duration(1, 0, 0, 15); + const result = duration.add(new Temporal.Duration(0, 0, 0, 16), { relativeTo }); + TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-sub-minute-offset.js new file mode 100644 index 000000000000..fce5c9da4d75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-sub-minute-offset.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: relativeTo string accepts an inexact UTC offset rounded to hours and minutes +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = "2000-01-01T00:00+00:45[+00:44:30.123456789]"; +const result = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rounded HH:MM is accepted in string"); + +relativeTo = "2000-01-01T00:00+00:44:30[+00:44:30.123456789]"; +assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), "no other rounding is accepted for offset"); + +const timeZone = new Temporal.TimeZone("+00:44:30.123456789"); +relativeTo = { year: 2000, month: 1, day: 1, offset: "+00:45", timeZone }; +assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), "rounded HH:MM not accepted as offset in property bag"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..8b5ed47cabf3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const relativeTo = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time; in this +// case via relativeTo. + +const result = duration.add(duration, { relativeTo }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..11c47e07bb47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(2); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => duration.add(other, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..2c442c15724c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(2); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => duration.add(other, { relativeTo }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..bc0bfe205988 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(2); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => duration.add(other, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..ce4ea698682b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(2); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => duration.add(other, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/subclassing-ignored.js new file mode 100644 index 000000000000..3ea2b3e2eaf6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Duration, + [0, 0, 0, 4, 5, 6, 7, 987, 654, 321], + "add", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 5, 6, 7, 987, 654, 322), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..167f0ace7182 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.duration.prototype.add steps 5–6: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], [...], _duration_.[[Nanoseconds]], _other_.[[Years]], [...], _other_.[[Nanoseconds]], _relativeTo_). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-addduration steps 7.d–e and 7.g.i: + d. Let _intermediateNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _timeZone_, _calendar_, _y1_, [...], _ns1_). + e. Let _endNs_ be ? AddZonedDateTime(_intermediateNs_, _timeZone_, _calendar_, _y2_, [...], _ns2_). + [...] + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-differencezoneddatetime step 8: + 8. Let _intermediateNs_ be ? AddZonedDateTime(_ns1_, _timeZone_, _calendar_, _dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], 0, 0, 0, 0, 0, 0, 0). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "2000-01-01T09:00:00", // called once on the input relativeTo object + "2001-01-01T09:00:00", // called once on relativeTo plus the receiver + "2002-01-01T09:00:00", // called once on relativeTo plus the receiver plus the argument + "2002-01-01T09:00:00", // called once on relativeTo plus the years, months, and weeks from the difference of relativeTo minus endNs +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 12); + duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, hour: 9, timeZone } }); +}, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/timezone-string-datetime.js new file mode 100644 index 000000000000..2b6e13c3e5ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/timezone-string-datetime.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }); + instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/year-zero.js new file mode 100644 index 000000000000..39f09c11326a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/add/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = "-000000-11-04T00:00"; +assert.throws( + RangeError, + () => { instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/blank/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/blank/prop-desc.js new file mode 100644 index 000000000000..5e645da45856 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/blank/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.blank +description: The "blank" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "blank"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/days/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/days/prop-desc.js new file mode 100644 index 000000000000..94237f21b994 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/days/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.days +description: The "days" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "days"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/hours/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/hours/prop-desc.js new file mode 100644 index 000000000000..b1a92b63c151 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/hours/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.hours +description: The "hours" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "hours"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/microseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/microseconds/prop-desc.js new file mode 100644 index 000000000000..5b97cea8a303 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/microseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.microseconds +description: The "microseconds" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "microseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/milliseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/milliseconds/prop-desc.js new file mode 100644 index 000000000000..cb5e1bc1dada --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/milliseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.milliseconds +description: The "milliseconds" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "milliseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/minutes/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/minutes/prop-desc.js new file mode 100644 index 000000000000..894e470d9487 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/minutes/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.minutes +description: The "minutes" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "minutes"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/months/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/months/prop-desc.js new file mode 100644 index 000000000000..87eb38785bc2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/months/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.months +description: The "months" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "months"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/nanoseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/nanoseconds/prop-desc.js new file mode 100644 index 000000000000..84f337895d89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/nanoseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.nanoseconds +description: The "nanoseconds" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "nanoseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/basic.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/basic.js new file mode 100644 index 000000000000..2b22b3ea03da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/basic.js @@ -0,0 +1,54 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: Temporal.Duration.prototype.negated will return negated value of the input duration. +info: | + 3. Return ? CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]), abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +let d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.negated(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "zeros"); + +let d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.negated(), -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, + "positive values"); + +let d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.negated(), -1e5, -2e5, -3e5, -4e5, -5e5, -6e5, -7e5, -8e5, -9e5, -10e5, + "large positive values"); + +let d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.negated(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + "negative values"); + +let d5 = new Temporal.Duration(-1e5, -2e5, -3e5, -4e5, -5e5, -6e5, -7e5, -8e5, -9e5, -10e5); +TemporalHelpers.assertDuration( + d5.negated(), 1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5, + "large negative values"); + +let d6 = new Temporal.Duration(1, 0, 3, 0, 5, 0, 7, 0, 9, 0); +TemporalHelpers.assertDuration( + d6.negated(), -1, 0, -3, 0, -5, 0, -7, 0, -9, 0, + "some zeros with positive values"); + +let d7 = new Temporal.Duration(-1, 0, -3, 0, -5, 0, -7, 0, -9, 0); +TemporalHelpers.assertDuration( + d7.negated(), 1, 0, 3, 0, 5, 0, 7, 0, 9, 0, + "some zeros with negative values"); + +let d8 = new Temporal.Duration(0, -2, 0, -4, 0, -6, 0, -8, 0, -10); +TemporalHelpers.assertDuration( + d8.negated(), 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, + "other zeros with negative values"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/builtin.js new file mode 100644 index 000000000000..f94e6dad8b7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: > + Tests that Temporal.Duration.prototype.negated + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.negated), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.negated), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.negated), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.negated.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/length.js new file mode 100644 index 000000000000..bd9ba67d0e92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: Temporal.Duration.prototype.negated.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.negated, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/name.js new file mode 100644 index 000000000000..d9a8aa2a456f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: Temporal.Duration.prototype.negated.name is "negated". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.negated, "name", { + value: "negated", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/not-a-constructor.js new file mode 100644 index 000000000000..d612c474330a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: > + Temporal.Duration.prototype.negated does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.negated(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.negated), false, + "isConstructor(Temporal.Duration.prototype.negated)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/prop-desc.js new file mode 100644 index 000000000000..483ce9821586 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: The "negated" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.negated, + "function", + "`typeof Duration.prototype.negated` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "negated", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/subclassing-ignored.js new file mode 100644 index 000000000000..d436baa86bff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/negated/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Duration, + [0, 0, 0, 4, 5, 6, 7, 987, 654, 321], + "negated", + [], + (result) => TemporalHelpers.assertDuration(result, 0, 0, 0, -4, -5, -6, -7, -987, -654, -321), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/prop-desc.js new file mode 100644 index 000000000000..d4cdeced21be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-duration-prototype +description: The "prototype" property of Temporal.Duration +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Duration.prototype, "object"); +assert.notSameValue(Temporal.Duration.prototype, null); + +verifyProperty(Temporal.Duration, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/balance-negative-result.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/balance-negative-result.js new file mode 100644 index 000000000000..1200480136b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/balance-negative-result.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: A negative duration result is balanced correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-balanceduration step 4: + 4. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + sec-temporal.duration.prototype.round step 25: + 25. Let _result_ be ? BalanceDuration(_balanceResult_.[[Days]], _adjustResult_.[[Hours]], _adjustResult_.[[Minutes]], _adjustResult_.[[Seconds]], _adjustResult_.[[Milliseconds]], _adjustResult_.[[Microseconds]], _adjustResult_.[[Nanoseconds]], _largestUnit_, _relativeTo_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, -60); +const result = duration.round({ largestUnit: "days" }); +TemporalHelpers.assertDuration(result, 0, 0, 0, -2, -12, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/builtin.js new file mode 100644 index 000000000000..144511a2e53b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + Tests that Temporal.Duration.prototype.round + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.round), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.round), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.round), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.round.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..db506f8cbdbf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,76 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +// Rounding with smallestUnit a calendar unit. +// The calls come from these paths: +// Duration.round() -> +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// BalanceDurationRelative -> +// MoveRelativeDate -> calendar.dateAdd() (2x) +// calendar.dateAdd() +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// BalanceDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +const instance1 = new Temporal.Duration(1, 1, 1, 1, 1); +instance1.round({ smallestUnit: "days", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 9, "rounding with calendar smallestUnit"); + +// Rounding with a non-default largestUnit to cover the path in +// UnbalanceDurationRelative where larger units are converted into smaller +// units; and with a smallestUnit larger than days to cover the path in +// RoundDuration where days are converted into larger units. +// The calls come from these paths: +// Duration.round() -> +// UnbalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd() +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// MoveRelativeDate -> calendar.dateAdd() (5x) +// BalanceDurationRelative +// MoveRelativeDate -> calendar.dateAdd() +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() + +calendar.dateAddCallCount = 0; + +const instance2 = new Temporal.Duration(0, 1, 1, 1); +instance2.round({ largestUnit: "weeks", smallestUnit: "weeks", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 9, "rounding with non-default largestUnit and calendar smallestUnit"); + +// Rounding with smallestUnit a non-calendar unit, and having the resulting time +// difference be longer than a calendar day, covering the paths that go through +// AdjustRoundedDurationDays. +// The calls come from these paths: +// Duration.round() -> +// AdjustRoundedDurationDays -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// AddDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) +// BalanceDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +calendar.dateAddCallCount = 0; + +const instance3 = new Temporal.Duration(0, 0, 0, 0, 23, 59, 59, 999, 999, 999); +instance3.round({ largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 7, "rounding with time difference exceeding calendar day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..7ef310c4d0a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.Duration(1, 1, 1, 1); +const relativeTo = new Temporal.PlainDate(2000, 1, 1, calendar); +calendar.specificPlainDate = relativeTo; +instance.round({ largestUnit: "days", relativeTo }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..039cde4c2523 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,163 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.duration.prototype.round steps 20–25: + 20. Let _unbalanceResult_ be ? UnbalanceDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _largestUnit_, _relativeTo_). + 21. Let _roundResult_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _unbalanceResult_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_[[Seconds]], _duration_[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_). + 22. Let _adjustResult_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_). + 23. Let _balanceResult_ be ? BalanceDurationRelative(_adjustResult_.[[Years]], _adjustResult_.[[Months]], _adjustResult_.[[Weeks]], _adjustResult_.[[Days]], _largestUnit_, _relativeTo_). + 24. ... + 25. Let _result_ be ? BalanceDuration(_balanceResult_.[[Days]], _adjustResult_.[[Hours]], _adjustResult_.[[Minutes]], _adjustResult_.[[Seconds]], _adjustResult_.[[Milliseconds]], _adjustResult_.[[Microseconds]], _adjustResult.[[Nanoseconds]], _largestUnit_, _relativeTo_). + sec-temporal-unbalancedurationrelative steps 1 and 9.d.iii–v: + 1. If _largestUnit_ is *"year"*, or _years_, _months_, _weeks_, and _days_ are all 0, then + a. Return ... + ... + 9. If _largestUnit_ is *"month"*, then + ... + d. Repeat, while abs(_years_) > 0, + ... + iii. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). + iv. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). + v. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). + sec-temporal-roundduration steps 5.d and 8.n–p: + 5. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + ... + 8. If _unit_ is *"year"*, then + ... + n. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). + o. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). + p. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_) + sec-temporal-adjustroundeddurationdays steps 1 and 9: + 1. If _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot; or _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*; or _unit_ is *"nanosecond"* and _increment_ is 1, then + a. Return ... + ... + 9. Let _adjustedDateDuration_ be ? AddDuration(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0, 0, 0, 0, _direction_, 0, 0, 0, 0, 0, 0, _relativeTo_). + sec-temporal-addduration step 7.a–g: + a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot. + ... + f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + g. Else, + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-balancedurationrelative steps 1, 9.m–o, and 9.q.vi–viii: + 1. If _largestUnit_ is not one of *"year"*, *"month"*, or *"week"*, or _years_, _months_, _weeks_, and _days_ are all 0, then + a. Return ... + ... + 9. If _largestUnit_ is *"year"*, then + ... + m. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). + n. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). + o. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). + p. ... + q. Repeat, while abs(_months_) ≥ abs(_oneYearMonths_), + ... + vi. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). + vii. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). + viii. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). + sec-temporal-balanceduration step 3.a: + 3. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + sec-temporal-differencezoneddatetime steps 7 and 11: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + 11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_). + sec-temporal-nanosecondstodays step 11: + 11. 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*). + sec-temporal-differenceisodatetime steps 9–11: + 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). + 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +// Check with smallestUnit nanoseconds but roundingIncrement > 1; each call +// should result in two calls to dateUntil() originating from +// AdjustRoundedDurationDays, one with largestUnit equal to the largest unit in +// the duration higher than "day", and one with largestUnit: "day". +// Additionally one call with largestUnit: "month" in BalanceDurationRelative +// when the largestUnit given to round() is "year", and one call with +// largestUnit: "day" when the largestUnit given to round() is "year", "month", +// "week", or "day". + +const durations = [ + [1, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 1, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 0, 1, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 86399_999_999_999], +].map((args) => new Temporal.Duration(...args)); + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit, index) => { + const duration = durations[index]; + const relativeTo = new Temporal.ZonedDateTime(0n, "UTC", calendar); + duration.round({ largestUnit, roundingIncrement: 2, roundingMode: 'ceil', relativeTo }); + }, + { + years: ["year", "day", "month", "day"], + months: ["month", "day", "day"], + weeks: ["week", "day", "day"], + days: ["day", "day", "day"], + hours: ["day", "day"], + minutes: ["day", "day"], + seconds: ["day", "day"], + milliseconds: ["day", "day"], + microseconds: ["day", "day"], + nanoseconds: ["day", "day"] + } +); + +// Check the path that converts months to years and vice versa in +// BalanceDurationRelative and UnbalanceDurationRelative. + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const duration = new Temporal.Duration(5, 60); + const relativeTo = new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 0, 0, 0, calendar); + duration.round({ largestUnit, relativeTo }); + }, + { + years: ["month", "month", "month", "month", "month", "month"], + months: ["month", "month", "month", "month", "month"], + weeks: [], + days: [], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +// Check the paths that call dateUntil() in RoundDuration. These paths do not +// call dateUntil() in AdjustRoundedDurationDays. Note that there is no +// largestUnit: "month" call in BalanceDurationRelative and no largestUnit: +// "day" call in BalanceDuration, because the durations have rounded down to 0. + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const duration = new Temporal.Duration(0, 0, 0, 0, 1, 1, 1, 1, 1, 1); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + duration.round({ largestUnit, smallestUnit: largestUnit, relativeTo }); + }, { + years: ["day", "year"], + months: ["day"], + weeks: ["day"], + days: ["day"] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-fields-iterable.js new file mode 100644 index 000000000000..06519b36cc85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-fields-iterable.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.duration.prototype.round step 19: + 19. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); +duration.round({ smallestUnit: 'months', relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-possibly-required.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-possibly-required.js new file mode 100644 index 000000000000..7dbc578d2dda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-possibly-required.js @@ -0,0 +1,65 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: relativeTo argument required if days = 0 but years/months/weeks non-zero +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +const duration3 = new Temporal.Duration(0, 0, 5); +const duration4 = new Temporal.Duration(0, 0, 0, 42); +const pd = new Temporal.PlainDate(2021, 12, 15); +const relativeToYears = { relativeTo: pd, largestUnit: "years" }; +const relativeToMonths = { relativeTo: pd, largestUnit: "months" }; +const relativeToWeeks = { relativeTo: pd, largestUnit: "weeks" }; +const relativeToDays = { relativeTo: pd, largestUnit: "days" }; + +assert.throws( + RangeError, + () => { duration1.round({ relativeTo: pd }); }, + "rounding a year Duration fails without largest/smallest unit" +); + +TemporalHelpers.assertDuration(duration1.round(relativeToYears), 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "round year duration to years"); +TemporalHelpers.assertDuration(duration1.round(relativeToMonths), 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, "round year duration to months"); +TemporalHelpers.assertDuration(duration1.round(relativeToWeeks), 0, 0, 52, 1, 0, 0, 0, 0, 0, 0, "round year duration to weeks"); +TemporalHelpers.assertDuration(duration1.round(relativeToDays), 0, 0, 0, 365, 0, 0, 0, 0, 0, 0, "round year duration to days"); + +assert.throws( + RangeError, + () => { duration2.round({ relativeTo: pd }); }, + "rounding a month Duration fails without largest/smallest unit" +); + +TemporalHelpers.assertDuration(duration2.round(relativeToYears), 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "round month duration to years"); +TemporalHelpers.assertDuration(duration2.round(relativeToMonths), 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, "round month duration to months"); +TemporalHelpers.assertDuration(duration2.round(relativeToWeeks), 0, 0, 52, 1, 0, 0, 0, 0, 0, 0, "round month duration to weeks"); +TemporalHelpers.assertDuration(duration2.round(relativeToDays), 0, 0, 0, 365, 0, 0, 0, 0, 0, 0, "round month duration to days"); + +assert.throws( + RangeError, + () => { duration3.round({ relativeTo: pd }); }, + "rounding a week Duration fails without largest/smallest unit" +); + +TemporalHelpers.assertDuration(duration3.round(relativeToYears), 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, "round week duration to years"); +TemporalHelpers.assertDuration(duration3.round(relativeToMonths), 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, "round week duration to months"); +TemporalHelpers.assertDuration(duration3.round(relativeToWeeks), 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, "round week duration to weeks"); +TemporalHelpers.assertDuration(duration3.round(relativeToDays), 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, "round week duration to days"); + +assert.throws( + RangeError, + () => { duration4.round({ relativeTo: pd }); }, + "rounding a day Duration fails without largest/smallest unit" +); + +TemporalHelpers.assertDuration(duration4.round(relativeToYears), 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, "round day duration to years"); +TemporalHelpers.assertDuration(duration4.round(relativeToMonths), 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, "round day duration to months"); +TemporalHelpers.assertDuration(duration4.round(relativeToWeeks), 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, "round day duration to weeks"); +TemporalHelpers.assertDuration(duration4.round(relativeToDays), 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, "round day duration to days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-temporal-object.js new file mode 100644 index 000000000000..39efef076107 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.duration.prototype.round step 19: + 19. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); + duration.round({ smallestUnit: 'months', relativeTo: { year: 2000, month: 1, day: 1, calendar: temporalObject } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/dateuntil-field.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/dateuntil-field.js new file mode 100644 index 000000000000..e259ce0d0959 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/dateuntil-field.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + When consulting calendar.dateUntil() to calculate the number of months in a + year, the months property is not accessed on the result Duration +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +// One path, through UnbalanceDurationRelative, calls dateUntil() in a loop for +// each year in the duration + +const actual = []; +const expected1 = [ + "call dateUntil", + "call dateUntil", +]; +const duration = new Temporal.Duration(0, 12); +TemporalHelpers.observeProperty(actual, duration, "months", 1); + +const calendar = TemporalHelpers.calendarDateUntilObservable(actual, duration); +const relativeTo = new Temporal.PlainDateTime(2018, 10, 12, 0, 0, 0, 0, 0, 0, calendar); + +const years = new Temporal.Duration(2); +const result1 = years.round({ largestUnit: "months", relativeTo }); +TemporalHelpers.assertDuration(result1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, "result"); +assert.compareArray(actual, expected1, "operations"); + +// There is a second path, through BalanceDurationRelative, that calls +// dateUntil() in a loop for each year in the duration plus one extra time + +actual.splice(0, actual.length); // reset calls for next test +const expected2 = [ + "call dateUntil", + "call dateUntil", + "call dateUntil", +]; + +const months = new Temporal.Duration(0, 24); +const result2 = months.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "result"); +assert.compareArray(actual, expected2, "operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-invalid-string.js new file mode 100644 index 000000000000..95db46b11441 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-invalid-string.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +assert.throws(RangeError, () => duration.round({ largestUnit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..352cb88a5c5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDate(2000, 1, 1); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => duration.round({ largestUnit, relativeTo }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-undefined.js new file mode 100644 index 000000000000..ba1a633d8eab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-undefined.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(0, 0, 0, 0, 1, 120, 1, 123, 456, 789); +const explicit1 = duration1.round({ largestUnit: undefined, smallestUnit: "nanosecond" }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 3, 0, 1, 123, 456, 789, "default largestUnit is largest in input"); +const implicit1 = duration1.round({ smallestUnit: "nanosecond" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 3, 0, 1, 123, 456, 789, "default largestUnit is largest in input"); + +const duration2 = new Temporal.Duration(0, 0, 0, 0, 0, 120, 1, 123, 456, 789); +const explicit2 = duration2.round({ largestUnit: undefined, smallestUnit: "nanosecond" }); +TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 0, 120, 1, 123, 456, 789, "default largestUnit is largest in input"); +const implicit2 = duration2.round({ smallestUnit: "nanosecond" }); +TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 0, 120, 1, 123, 456, 789, "default largestUnit is largest in input"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-wrong-type.js new file mode 100644 index 000000000000..c4dafeda71b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/largestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 456, 789); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "minute", + (largestUnit) => duration.round({ largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 754, 56, 123, 456, 789, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/length.js new file mode 100644 index 000000000000..f89fe17939e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Temporal.Duration.prototype.round.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.round, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/name.js new file mode 100644 index 000000000000..7cbb8609c8ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Temporal.Duration.prototype.round.name is "round". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.round, "name", { + value: "round", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/not-a-constructor.js new file mode 100644 index 000000000000..3a91f5837a3f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + Temporal.Duration.prototype.round does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.round(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.round), false, + "isConstructor(Temporal.Duration.prototype.round)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/prop-desc.js new file mode 100644 index 000000000000..876fc83d43be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: The "round" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.round, + "function", + "`typeof Duration.prototype.round` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "round", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..6d3e3cf1621f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/read-time-fields-before-datefromfields.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.duration.prototype.round step 19: + 19. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.g: + g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInvalidGettersTime(); +const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); +duration.round({ smallestUnit: 'months', relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..6f4b5bf9a97f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.duration.prototype.round +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.round({ smallestUnit: "seconds", relativeTo: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.round({ smallestUnit: "seconds", relativeTo: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-no-time-units.js new file mode 100644 index 000000000000..ef01abbada07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-no-time-units.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Missing time units in relativeTo property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = { year: 2000, month: 1, day: 1 }; +const result = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..7e182b4491a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + assert.throws(RangeError, () => duration.round({ smallestUnit: "seconds", relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..f57aaf852e32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => duration.round({ smallestUnit: "seconds", relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..8de379e6fe87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + assert.throws(RangeError, () => duration.round({ smallestUnit: "seconds", relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..4a85e224600c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + assert.throws(TypeError, () => duration.round({ smallestUnit: "seconds", relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-datetime.js new file mode 100644 index 000000000000..10dc16766a1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-datetime.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + Conversion of ISO date-time strings as relativeTo option to + Temporal.ZonedDateTime or Temporal.PlainDateTime instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = "2019-11-01T00:00"; +const result1 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "bare date-time string is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00Z"; +const result2 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result2, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "date-time + Z is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00-07:00"; +const result3 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "date-time + offset is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00[-07:00]"; +const result4 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result4, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00Z[-07:00]"; +const result5 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result5, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+00:00[UTC]"; +const result6 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result6, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+04:15[UTC]"; +assert.throws(RangeError, () => instance.round({ largestUnit: "years", relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-invalid.js new file mode 100644 index 000000000000..32df5017a59f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown if relativeTo is a string with the wrong format +features: [Temporal] +---*/ + +['bad string', '15:30:45.123456', 'iso8601', 'UTC', 'P1YT1H'].forEach((relativeTo) => { + const duration = new Temporal.Duration(0, 0, 0, 31); + assert.throws(RangeError, () => duration.round({ largestUnit: "months", relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-plaindatetime.js new file mode 100644 index 000000000000..8459a1ec13a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-plaindatetime.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: The relativeTo option accepts a PlainDateTime-like ISO 8601 string +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +['2000-01-01', '2000-01-01T00:00', '2000-01-01T00:00[u-ca=iso8601]'].forEach((relativeTo) => { + const duration = new Temporal.Duration(0, 0, 0, 31); + const result = duration.round({ largestUnit: "months", relativeTo }); + TemporalHelpers.assertDuration(result, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-zoneddatetime-wrong-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-zoneddatetime-wrong-offset.js new file mode 100644 index 000000000000..41d37c8d54e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-zoneddatetime-wrong-offset.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Throws if a ZonedDateTime-like relativeTo string has the wrong UTC offset +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); +const relativeTo = "2000-01-01T00:00+05:30[UTC]"; +assert.throws( + RangeError, + () => instance.round({ largestUnit: "years", relativeTo }), + "round should throw RangeError on a string with UTC offset mismatch" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-zoneddatetime.js new file mode 100644 index 000000000000..7765f9eeca32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-string-zoneddatetime.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: The relativeTo option accepts a ZonedDateTime-like ISO 8601 string +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + '2000-01-01[UTC]', + '2000-01-01T00:00[UTC]', + '2000-01-01T00:00+00:00[UTC]', + '2000-01-01T00:00+00:00[UTC][u-ca=iso8601]', +].forEach((relativeTo) => { + const duration = new Temporal.Duration(0, 0, 0, 31); + const result = duration.round({ largestUnit: "months", relativeTo }); + TemporalHelpers.assertDuration(result, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-sub-minute-offset.js new file mode 100644 index 000000000000..0bc627a21aa3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-sub-minute-offset.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: relativeTo string accepts an inexact UTC offset rounded to hours and minutes +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = "2000-01-01T00:00+00:45[+00:44:30.123456789]"; +const result = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "rounded HH:MM is accepted in string"); + +relativeTo = "2000-01-01T00:00+00:44:30[+00:44:30.123456789]"; +assert.throws(RangeError, () => instance.round({ largestUnit: "years", relativeTo }), "no other rounding is accepted for offset"); + +const timeZone = new Temporal.TimeZone("+00:44:30.123456789"); +relativeTo = { year: 2000, month: 1, day: 1, offset: "+00:45", timeZone }; +assert.throws(RangeError, () => instance.round({ largestUnit: "years", relativeTo }), "rounded HH:MM not accepted as offset in property bag"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-undefined-throw-on-calendar-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-undefined-throw-on-calendar-units.js new file mode 100644 index 000000000000..807c8e69650e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-undefined-throw-on-calendar-units.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + The relativeTo option is required when the Duration contains years, months, + or weeks, and largestUnit is days; or largestUnit is weeks or months +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const oneYear = new Temporal.Duration(1); +const oneMonth = new Temporal.Duration(0, 1); +const oneWeek = new Temporal.Duration(0, 0, 1); +const oneDay = new Temporal.Duration(0, 0, 0, 1); + +const options = { largestUnit: "days" }; +TemporalHelpers.assertDuration(oneDay.round(options), 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "days do not require relativeTo"); +assert.throws(RangeError, () => oneWeek.round(options), "balancing weeks to days requires relativeTo"); +assert.throws(RangeError, () => oneMonth.round(options), "balancing months to days requires relativeTo"); +assert.throws(RangeError, () => oneYear.round(options), "balancing years to days requires relativeTo"); + +["months", "weeks"].forEach((largestUnit) => { + [oneDay, oneWeek, oneMonth, oneYear].forEach((duration) => { + assert.throws(RangeError, () => duration.round({ largestUnit }), `balancing ${duration} to ${largestUnit} requires relativeTo`); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..8584938ea580 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const relativeTo = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time; in this +// case via relativeTo. + +const result = duration.round({ relativeTo, largestUnit: "days" }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..c963bc42fbd3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => duration.round({ smallestUnit: "seconds", relativeTo: datetime })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..3b1b1188ca83 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => duration.round({ smallestUnit: "seconds", relativeTo: datetime }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..fa3fc6d604fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => duration.round({ smallestUnit: "seconds", relativeTo: datetime })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..8136e4407708 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => duration.round({ smallestUnit: "seconds", relativeTo: datetime })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/round-negative-result.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/round-negative-result.js new file mode 100644 index 000000000000..84616cd1231d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/round-negative-result.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: A negative duration result is balanced correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]\: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-roundduration step 6: + 6. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + sec-temporal.duration.prototype.round step 21: + 21. Let _roundResult_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _unbalanceResult_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_[[Seconds]], _duration_[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, -60); +const result = duration.round({ smallestUnit: "days" }); +TemporalHelpers.assertDuration(result, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-nan.js new file mode 100644 index 000000000000..7d19fa3768f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-nan.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.duration.prototype.round step 18: + 18. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 4, 12, 34, 56, 987, 654, 321); +assert.throws(RangeError, () => duration.round({ smallestUnit: 'second', roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-undefined.js new file mode 100644 index 000000000000..b2e9cfeadb5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.duration.prototype.round step 18: + 18. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 4, 12, 34, 56, 987, 654, 321); + +const explicit = duration.round({ smallestUnit: 'second', roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 4, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1"); + +const implicit = duration.round({ smallestUnit: 'second' }); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 4, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..6da009e3c669 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingincrement-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.round step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 4, 12, 34, 56, 987, 654, 321); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => duration.round({ smallestUnit: 'second', roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 12, 34, 57, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 12, 34, 56, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-invalid-string.js new file mode 100644 index 000000000000..28bf06c166be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => duration.round({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-undefined.js new file mode 100644 index 000000000000..de1a178305c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); + +const explicit1 = duration.round({ smallestUnit: "microsecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand"); +const implicit1 = duration.round({ smallestUnit: "microsecond" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand"); + +const explicit2 = duration.round({ smallestUnit: "millisecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand"); +const implicit2 = duration.round({ smallestUnit: "millisecond" }); +TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand"); + +const explicit3 = duration.round({ smallestUnit: "second", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand"); +const implicit3 = duration.round({ smallestUnit: "second" }); +TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-wrong-type.js new file mode 100644 index 000000000000..621050693c2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand", + (roundingMode) => duration.round({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 12, 34, 56, 123, 988, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-disallowed-units-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-disallowed-units-string.js new file mode 100644 index 000000000000..f21cdb197dca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-disallowed-units-string.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Specifically disallowed units for the smallestUnit option +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321); +const invalidUnits = [ + "era", + "eras", +]; +invalidUnits.forEach((smallestUnit) => { + assert.throws( + RangeError, + () => instance.round({ smallestUnit }), + `{ smallestUnit: "${smallestUnit}" } should not be allowed as an argument to round` + ); + assert.throws( + RangeError, + () => instance.round(smallestUnit), + `"${smallestUnit}" should not be allowed as an argument to round` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-invalid-string.js new file mode 100644 index 000000000000..1d3b92277481 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-invalid-string.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +assert.throws(RangeError, () => duration.round({ smallestUnit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-plurals-accepted-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-plurals-accepted-string.js new file mode 100644 index 000000000000..e79d41dce314 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-plurals-accepted-string.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Plural units are accepted as well for the shorthand for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321); +const validUnits = [ + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => duration.round(smallestUnit), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..75b51076bac6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDate(2000, 1, 1); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => duration.round({ smallestUnit, relativeTo }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-string-shorthand-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-string-shorthand-string.js new file mode 100644 index 000000000000..549e7f354828 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-string-shorthand-string.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: String as first argument is equivalent to options bag with smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321); +const validUnits = [ + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +validUnits.forEach((smallestUnit) => { + const full = instance.round({ smallestUnit }); + const shorthand = instance.round(smallestUnit); + TemporalHelpers.assertDurationsEqual(shorthand, full, `"${smallestUnit}" as first argument to round is equivalent to options bag`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-undefined.js new file mode 100644 index 000000000000..fb6bf56c38ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 1, 2, 3, 123, 456, 789); +const explicit1 = duration.round({ largestUnit: "day", smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 1, 2, 3, 123, 456, 789, "default smallestUnit is nanosecond"); +const implicit1 = duration.round({ largestUnit: "day" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 1, 2, 3, 123, 456, 789, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-wrong-type.js new file mode 100644 index 000000000000..8bd13396de4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => duration.round({ smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 12, 34, 56, 123, 988, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/subclassing-ignored.js new file mode 100644 index 000000000000..447feb06f2f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Duration, + [0, 0, 0, 4, 5, 6, 7, 987, 654, 321], + "round", + [{ smallestUnit: 'seconds' }], + (result) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 5, 6, 8, 0, 0, 0), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..228c934c005f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.duration.prototype.round steps 19, 21, and 24: + 19. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 21. Let _roundResult_ be ? RoundDuration(_unbalanceResult_.[[Years]], [...], _unbalanceResult_.[[Days]], _duration_.[[Hours]], [...], _duration_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_). + 24. If _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Set _relativeTo_ to ? MoveRelativeZonedDateTime(_relativeTo_, _balanceResult_.[[Years]], _balanceResult_.[[Months]], _balanceResult_.[[Weeks]], 0). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-roundduration step 5.c–d: + c. If _zonedRelativeTo_ is not *undefined*, then + i. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _years_, _months_, _weeks_, _days_). + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + sec-temporal-moverelativezoneddatetime step 1: + 1. Let _intermediateNs_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0). + sec-temporal-nanosecondstodays step 13: + 13. Let _intermediateNs_ be ? AddZonedDateTime(_startNs_, _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], 0, 0, 0, _days_, 0, 0, 0, 0, 0, 0). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "2000-01-01T00:00:00", // called once on the input relativeTo object + "2001-02-09T00:00:00", // called once on relativeTo plus years, months, weeks, days from the receiver + "2001-02-10T00:00:00", // called once on the previous value plus the calendar days difference between that and the time part of the duration + "2001-02-01T00:00:00", // called once on relativeTo plus the years, months, and weeks part of the balance result +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); + duration.round({ smallestUnit: 'months', relativeTo: { year: 2000, month: 1, day: 1, timeZone } }); +}, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/timezone-string-datetime.js new file mode 100644 index 000000000000..4cfff7dbdc1b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/timezone-string-datetime.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.round({ largestUnit: "months", relativeTo: { year: 2000, month: 5, day: 2, timeZone } }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.round({ largestUnit: "months", relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + instance.round({ largestUnit: "months", relativeTo: { year: 2000, month: 5, day: 2, timeZone } }); + instance.round({ largestUnit: "months", relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/year-zero.js new file mode 100644 index 000000000000..7464d539ca98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/round/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = "-000000-11-04T00:00"; +assert.throws( + RangeError, + () => { instance.round({ largestUnit: "years", relativeTo }); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/seconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/seconds/prop-desc.js new file mode 100644 index 000000000000..d8f4d9a498d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/seconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.seconds +description: The "seconds" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "seconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/sign/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/sign/prop-desc.js new file mode 100644 index 000000000000..e118147d3e7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/sign/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.sign +description: The "sign" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "sign"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..c296d5089c2c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const blank = new Temporal.Duration(); + +TemporalHelpers.assertDuration(blank.subtract("PT1.03125H"), 0, 0, 0, 0, -1, -1, -52, -500, 0, 0, + "positive fractional units rounded with correct rounding mode"); +TemporalHelpers.assertDuration(blank.subtract("-PT1.03125H"), 0, 0, 0, 0, 1, 1, 52, 500, 0, 0, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..06eea78f5188 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(); + +const resultHours = instance.subtract("-PT24.567890123H"); +TemporalHelpers.assertDuration(resultHours, 0, 0, 0, 0, 24, 34, 4, 404, 442, 799, "negative fractional hours"); + +const resultMinutes = instance.subtract("-PT1440.567890123M"); +TemporalHelpers.assertDuration(resultMinutes, 0, 0, 0, 0, 0, 1440, 34, 73, 407, 379, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/balance-negative-result.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/balance-negative-result.js new file mode 100644 index 000000000000..b937c0848555 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/balance-negative-result.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: A negative duration result is balanced correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-balanceduration step 4: + 4. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + sec-temporal-addduration steps 5–6: + 5. If _relativeTo_ is *undefined*, then + ... + b. Let _result_ be ! BalanceDuration(_d1_ + _d2_, _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_). + ... + 6. Else if _relativeTo_ has an [[InitializedTemporalPlainDateTime]] internal slot, then + ... + n. Let _result_ be ! BalanceDuration(_dateDifference_.[[Days]], _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_). + sec-temporal.duration.prototype.subtract step 6: + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], −_other_.[[Years]], −_other_.[[Months]], −_other_.[[Weeks]], −_other_.[[Days]], −_other_.[[Hours]], −_other_.[[Minutes]], −_other_.[[Seconds]], −_other_.[[Milliseconds]], −_other_.[[Microseconds]], −_other_.[[Nanoseconds]], _relativeTo_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(0, 0, 0, 0, -60); +const duration2 = new Temporal.Duration(0, 0, 0, -1); + +const resultNotRelative = duration1.subtract(duration2); +TemporalHelpers.assertDuration(resultNotRelative, 0, 0, 0, -1, -12, 0, 0, 0, 0, 0); + +const relativeTo = new Temporal.PlainDateTime(2000, 1, 1); +const resultRelative = duration1.subtract(duration2, { relativeTo }); +TemporalHelpers.assertDuration(resultRelative, 0, 0, 0, -1, -12, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/balance-negative-time-units.js new file mode 100644 index 000000000000..7cd7ad8412a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/balance-negative-time-units.js @@ -0,0 +1,63 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Negative time fields in relativeTo are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-differenceisodatetime step 2: + 2. Let _timeDifference_ be ? DifferenceTime(_h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_). + sec-temporal-differencezoneddatetime step 7: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + sec-temporal-addduration step 7.g.i: + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal.duration.prototype.subtract step 6: + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], −_other_.[[Years]], −_other_.[[Months]], −_other_.[[Weeks]], −_other_.[[Days]], −_other_.[[Hours]], −_other_.[[Minutes]], −_other_.[[Seconds]], −_other_.[[Milliseconds]], −_other_.[[Microseconds]], −_other_.[[Nanoseconds]], _relativeTo_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 1, 1, 1, 1, 1, 1); + +const timeZone = new Temporal.TimeZone("UTC"); +const relativeTo = new Temporal.ZonedDateTime(830998861_000_000_000n, timeZone); +// This code path is encountered if largestUnit is years, months, weeks, or days +// and relativeTo is a ZonedDateTime +const options = { largestUnit: "days", relativeTo }; + +const result1 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 2), options); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 2), options); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 2), options); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 2), options); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 2), options); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 2), options); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/builtin.js new file mode 100644 index 000000000000..d70030af3ea2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: > + Tests that Temporal.Duration.prototype.subtract + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.subtract), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.subtract), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.subtract), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.subtract.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..4d4f254729f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.Duration(1, 1, 1, 1); +instance.subtract(new Temporal.Duration(-1, -1, -1, -1), { relativeTo: new Temporal.ZonedDateTime(0n, timeZone, calendar) }); +assert.sameValue(calendar.dateAddCallCount, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..0bb1cc47c599 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.Duration(1, 1, 1, 1); +const relativeTo = new Temporal.PlainDate(2000, 1, 1, calendar); +calendar.specificPlainDate = relativeTo; +instance.subtract(new Temporal.Duration(-1, -1, -1, -1), { relativeTo }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..861b717c0ca2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,81 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.duration.prototype.subtract step 6: + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], −_other_.[[Years]], −_other_.[[Months]], −_other_.[[Weeks]], −_other_.[[Days]], −_other_.[[Hours]], −_other_.[[Minutes]], −_other_.[[Seconds]], −_other_.[[Milliseconds]], −_other_.[[Microseconds]], −_other_.[[Nanoseconds]], _relativeTo_). + sec-temporal-addduration steps 6-7: + 6. If _relativeTo_ has an [[InitializedTemporalPlainDateTime]] internal slot, then + ... + j. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + k. Let _differenceOptions_ be ! OrdinaryObjectCreate(*null*). + l. Perform ! CreateDataPropertyOrThrow(_differenceOptions_, *"largestUnit"*, _dateLargestUnit_). + m. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _datePart_, _end_, _differenceOptions_). + ... + 7. Else, + a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot. + ... + f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + g. Else, + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-differencezoneddatetime steps 7 and 11: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + 11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_). + sec-temporal-nanosecondstodays step 11: + 11. 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*). + sec-temporal-differenceisodatetime steps 9–11: + 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). + 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit, index) => { + const one = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(1)]); + const two = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(2)]); + const relativeTo = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + two.subtract(one, { relativeTo }); + }, + { + years: ["year"], + months: ["month"], + weeks: ["week"], + days: ["day"], + hours: ["day"], + minutes: ["day"], + seconds: ["day"], + milliseconds: ["day"], + microseconds: ["day"], + nanoseconds: ["day"] + } +); + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit, index) => { + const one = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(1)]); + const two = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(2)]); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); + two.subtract(one, { relativeTo }); + }, + { + years: ["year", "day"], + months: ["month", "day"], + weeks: ["week", "day"], + days: ["day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-fields-iterable.js new file mode 100644 index 000000000000..eec67c5cba3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-fields-iterable.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.duration.prototype.subtract step 5: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +duration1.subtract(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-temporal-object.js new file mode 100644 index 000000000000..7e849010871d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.duration.prototype.subtract step 5: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 12); + duration1.subtract(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar: temporalObject } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..729561ceb9bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/infinity-throws-rangeerror.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration.prototype.subtract throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.duration.prototype.subtract +features: [Temporal] +---*/ + +const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds']; + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDateTime(2000, 1, 1); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: Infinity }, { relativeTo })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { relativeTo })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/length.js new file mode 100644 index 000000000000..4e0e2ae95fbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Temporal.Duration.prototype.subtract.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.subtract, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/name.js new file mode 100644 index 000000000000..31f99615e4fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Temporal.Duration.prototype.subtract.name is "subtract". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.subtract, "name", { + value: "subtract", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..d44ae2ddc752 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/negative-infinity-throws-rangeerror.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration.prototype.subtract throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.duration.prototype.subtract +features: [Temporal] +---*/ + +const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds']; + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDateTime(2000, 1, 1); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity }, { relativeTo })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { relativeTo })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..e5b342e994f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.subtract({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/not-a-constructor.js new file mode 100644 index 000000000000..e06eb61832d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: > + Temporal.Duration.prototype.subtract does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.subtract(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.subtract), false, + "isConstructor(Temporal.Duration.prototype.subtract)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/options-undefined.js new file mode 100644 index 000000000000..f64b107c751c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/options-undefined.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +assert.throws(RangeError, () => duration1.subtract(duration2), "default relativeTo is undefined"); +assert.throws(RangeError, () => duration1.subtract(duration2, undefined), "default relativeTo is undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js new file mode 100644 index 000000000000..e153fdc06403 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Properties on an object passed to subtract() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 1, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDateTime(2000, 1, 1); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.subtract(argument, { relativeTo }); +TemporalHelpers.assertDuration(result, 0, 1, 0, 3, 4, 5, 6, 986, 653, 320); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/prop-desc.js new file mode 100644 index 000000000000..5499b8f69267 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: The "subtract" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.subtract, + "function", + "`typeof Duration.prototype.subtract` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "subtract", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..98f2d1c0d9ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/read-time-fields-before-datefromfields.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.duration.prototype.subtract step 5: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.g: + g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInvalidGettersTime(); +const duration1 = new Temporal.Duration(1); +const duration2 = new Temporal.Duration(0, 12); +duration1.subtract(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..928023c455ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.duration.prototype.subtract +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.subtract(instance, { relativeTo: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.subtract(instance, { relativeTo: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-no-time-units.js new file mode 100644 index 000000000000..efe2fcce564b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-no-time-units.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Missing time units in relativeTo property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = { year: 2000, month: 1, day: 1 }; +const result = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..37901ef4c372 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(0, 3); + assert.throws(RangeError, () => duration.subtract(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..dbef8089c38a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(0, 3); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => duration.subtract(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..e66fd63758fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(0, 3); + assert.throws(RangeError, () => duration.subtract(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..47abd8b7b72c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(0, 3); + assert.throws(TypeError, () => duration.subtract(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-datetime.js new file mode 100644 index 000000000000..beff33211f38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-datetime.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: > + Conversion of ISO date-time strings as relativeTo option to + Temporal.ZonedDateTime or Temporal.PlainDateTime instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = "2019-11-01T00:00"; +const result1 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bare date-time string is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00Z"; +const result2 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00-07:00"; +const result3 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + offset is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00[-07:00]"; +const result4 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00Z[-07:00]"; +const result5 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+00:00[UTC]"; +const result6 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+04:15[UTC]"; +assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-invalid.js new file mode 100644 index 000000000000..8c9e5c0fb465 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: RangeError thrown if relativeTo is a string with the wrong format +features: [Temporal] +---*/ + +['bad string', '15:30:45.123456', 'iso8601', 'UTC', 'P1YT1H'].forEach((relativeTo) => { + const duration = new Temporal.Duration(1, 0, 0, 41); + assert.throws(RangeError, () => duration.subtract(new Temporal.Duration(0, 0, 0, 10), { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-plaindatetime.js new file mode 100644 index 000000000000..d08bd3d68522 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-plaindatetime.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: The relativeTo option accepts a PlainDateTime-like ISO 8601 string +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +['2000-01-01', '2000-01-01T00:00', '2000-01-01T00:00[u-ca=iso8601]'].forEach((relativeTo) => { + const duration = new Temporal.Duration(1, 0, 0, 41); + const result = duration.subtract(new Temporal.Duration(0, 0, 0, 10), { relativeTo }); + TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-zoneddatetime-wrong-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-zoneddatetime-wrong-offset.js new file mode 100644 index 000000000000..ab0c9b7e9b67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-zoneddatetime-wrong-offset.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Throws if a ZonedDateTime-like relativeTo string has the wrong UTC offset +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); +const relativeTo = "2000-01-01T00:00+05:30[UTC]"; +assert.throws( + RangeError, + () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }), + "subtract should throw RangeError on a string with UTC offset mismatch" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-zoneddatetime.js new file mode 100644 index 000000000000..388e60c20306 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-string-zoneddatetime.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: The relativeTo option accepts a ZonedDateTime-like ISO 8601 string +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + '2000-01-01[UTC]', + '2000-01-01T00:00[UTC]', + '2000-01-01T00:00+00:00[UTC]', + '2000-01-01T00:00+00:00[UTC][u-ca=iso8601]', +].forEach((relativeTo) => { + const duration = new Temporal.Duration(1, 0, 0, 41); + const result = duration.subtract(new Temporal.Duration(0, 0, 0, 10), { relativeTo }); + TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-sub-minute-offset.js new file mode 100644 index 000000000000..4a938159e1bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-sub-minute-offset.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: relativeTo string accepts an inexact UTC offset rounded to hours and minutes +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = "2000-01-01T00:00+00:45[+00:44:30.123456789]"; +const result = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rounded HH:MM is accepted in string"); + +relativeTo = "2000-01-01T00:00+00:44:30[+00:44:30.123456789]"; +assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }), "no other rounding is accepted for offset"); + +const timeZone = new Temporal.TimeZone("+00:44:30.123456789"); +relativeTo = { year: 2000, month: 1, day: 1, offset: "+00:45", timeZone }; +assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }), "rounded HH:MM not accepted as offset in property bag"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..d3e948e0f1f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const relativeTo = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time; in this +// case via relativeTo. + +const result = duration.subtract(duration, { relativeTo }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..377ed25b5cb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(0, 3); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => duration.subtract(other, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..82b13321bfd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(0, 3); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => duration.subtract(other, { relativeTo }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..2ab70bac47c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(0, 3); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => duration.subtract(other, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..2b24e2f263c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const other = new Temporal.Duration(0, 3); + const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => duration.subtract(other, { relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/subclassing-ignored.js new file mode 100644 index 000000000000..46ff031103d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Duration, + [0, 0, 0, 4, 5, 6, 7, 987, 654, 321], + "subtract", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 5, 6, 7, 987, 654, 320), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..d242cdec94dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.duration.prototype.subtract steps 5–6: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], [...], _duration_.[[Nanoseconds]], −_other_.[[Years]], [...], −_other_.[[Nanoseconds]], _relativeTo_). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-addduration steps 7.d–e and 7.g.i: + d. Let _intermediateNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _timeZone_, _calendar_, _y1_, [...], _ns1_). + e. Let _endNs_ be ? AddZonedDateTime(_intermediateNs_, _timeZone_, _calendar_, _y2_, [...], _ns2_). + [...] + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-differencezoneddatetime step 8: + 8. Let _intermediateNs_ be ? AddZonedDateTime(_ns1_, _timeZone_, _calendar_, _dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], 0, 0, 0, 0, 0, 0, 0). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "2000-01-01T09:00:00", // called once on the input relativeTo object + "2001-01-01T09:00:00", // called once on relativeTo plus the receiver + "1999-12-01T09:00:00", // called once on relativeTo plus the receiver minus the argument + "1999-12-01T09:00:00", // called once on relativeTo plus the years, months, and weeks from the difference of relativeTo minus endNs +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 13); + duration1.subtract(duration2, { relativeTo: { year: 2000, month: 1, day: 1, hour: 9, timeZone } }); +}, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/timezone-string-datetime.js new file mode 100644 index 000000000000..4e0a5cb00bad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/timezone-string-datetime.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + instance.subtract(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }); + instance.subtract(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/year-zero.js new file mode 100644 index 000000000000..b7c9d22d71c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/subtract/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = "-000000-11-04T00:00"; +assert.throws( + RangeError, + () => { instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/basic.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/basic.js new file mode 100644 index 000000000000..2c7055f8c9f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/basic.js @@ -0,0 +1,243 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: Temporal.Duration.prototype.toJSON will return correct iso8601 string for the given duration. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Return ! TemporalDurationToString(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "auto"). +features: [Temporal] +---*/ + +let d = new Temporal.Duration(); +assert.sameValue(d.toJSON(), "PT0S", "zero duration"); + +d = new Temporal.Duration(1); +assert.sameValue(d.toJSON(), "P1Y", "positive small years"); +d = new Temporal.Duration(-1); +assert.sameValue(d.toJSON(), "-P1Y", "negative small years"); +d = new Temporal.Duration(1234567890); +assert.sameValue(d.toJSON(), "P1234567890Y", "positive large years"); +d = new Temporal.Duration(-1234567890); +assert.sameValue(d.toJSON(), "-P1234567890Y", "negative large years"); + +d = new Temporal.Duration(1, 2); +assert.sameValue(d.toJSON(), "P1Y2M", "positive years and months"); +d = new Temporal.Duration(-1, -2); +assert.sameValue(d.toJSON(), "-P1Y2M", "negative years and months"); +d = new Temporal.Duration(0, 2); +assert.sameValue(d.toJSON(), "P2M", "positive small months"); +d = new Temporal.Duration(0,-2); +assert.sameValue(d.toJSON(), "-P2M", "negative small months"); +d = new Temporal.Duration(0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890M", "positive large months"); +d = new Temporal.Duration(0,-1234567890); +assert.sameValue(d.toJSON(), "-P1234567890M", "negative large months"); + +d = new Temporal.Duration(1, 2, 3); +assert.sameValue(d.toJSON(), "P1Y2M3W", "positive years, months, weeks"); +d = new Temporal.Duration(-1, -2, -3); +assert.sameValue(d.toJSON(), "-P1Y2M3W", "negative years, months, weeks"); +d = new Temporal.Duration(0, 0, 3); +assert.sameValue(d.toJSON(), "P3W", "positive small weeks"); +d = new Temporal.Duration(0, 0, -3); +assert.sameValue(d.toJSON(), "-P3W", "negative small weeks"); +d = new Temporal.Duration(1, 0, 3); +assert.sameValue(d.toJSON(), "P1Y3W", "positive years and weeks"); +d = new Temporal.Duration(-1, 0, -3); +assert.sameValue(d.toJSON(), "-P1Y3W", "negative years and weeks"); +d = new Temporal.Duration(0, 2, 3); +assert.sameValue(d.toJSON(), "P2M3W", "positive months and weeks"); +d = new Temporal.Duration(0, -2, -3); +assert.sameValue(d.toJSON(), "-P2M3W", "negative months and weeks"); +d = new Temporal.Duration(0, 0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890W", "positive large weeks"); +d = new Temporal.Duration(0, 0, -1234567890); +assert.sameValue(d.toJSON(), "-P1234567890W", "negative large weeks"); + +d = new Temporal.Duration(1, 2, 3, 4); +assert.sameValue(d.toJSON(), "P1Y2M3W4D", "positive years, months, weeks, days"); +d = new Temporal.Duration(-1, -2, -3, -4); +assert.sameValue(d.toJSON(), "-P1Y2M3W4D", "negative years, months, weeks, days"); +d = new Temporal.Duration(0, 0, 0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890D", "positive large days"); +d = new Temporal.Duration(0, 0, 0, -1234567890); +assert.sameValue(d.toJSON(), "-P1234567890D", "negative large days"); +d = new Temporal.Duration(0, 0, 0, 4); +assert.sameValue(d.toJSON(), "P4D", "positive small days"); +d = new Temporal.Duration(0, 0, 0, -4); +assert.sameValue(d.toJSON(), "-P4D", "negative small days"); +d = new Temporal.Duration(1, 0, 0, 4); +assert.sameValue(d.toJSON(), "P1Y4D", "positive years and days"); +d = new Temporal.Duration(-1, 0, 0, -4); +assert.sameValue(d.toJSON(), "-P1Y4D", "negative years and days"); +d = new Temporal.Duration(0, 2, 0, 4); +assert.sameValue(d.toJSON(), "P2M4D", "positive months and days"); +d = new Temporal.Duration(0, -2, 0, -4); +assert.sameValue(d.toJSON(), "-P2M4D", "negative months and days"); +d = new Temporal.Duration(0, 0, 3, 4); +assert.sameValue(d.toJSON(), "P3W4D", "positive weeks and days"); +d = new Temporal.Duration(0, 0, -3, -4); +assert.sameValue(d.toJSON(), "-P3W4D", "negative weeks and days"); + +d = new Temporal.Duration(0, 0, 0, 0, 5); +assert.sameValue(d.toJSON(), "PT5H", "positive hours"); +d = new Temporal.Duration(0, 0, 0, 0, -5); +assert.sameValue(d.toJSON(), "-PT5H", "negative hours"); +d = new Temporal.Duration(1, 0, 0, 0, 5); +assert.sameValue(d.toJSON(), "P1YT5H", "positive years and hours"); +d = new Temporal.Duration(-1, 0, 0, 0, -5); +assert.sameValue(d.toJSON(), "-P1YT5H", "negative years and hours"); +d = new Temporal.Duration(0, 2, 0, 0, 5); +assert.sameValue(d.toJSON(), "P2MT5H", "positive months and hours"); +d = new Temporal.Duration(0, -2, 0, 0, -5); +assert.sameValue(d.toJSON(), "-P2MT5H", "negative months and hours"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 6); +assert.sameValue(d.toJSON(), "PT6M", "positive minutes"); +d = new Temporal.Duration(0, 0, 0, 0, 0, -6); +assert.sameValue(d.toJSON(), "-PT6M", "negative minutes"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 6); +assert.sameValue(d.toJSON(), "PT5H6M", "positive hours and minutes"); +d = new Temporal.Duration(0, 0, 0, 0, -5, -6); +assert.sameValue(d.toJSON(), "-PT5H6M", "negative hours and minutes"); +d = new Temporal.Duration(0, 0, 3, 0, 0, 6); +assert.sameValue(d.toJSON(), "P3WT6M", "positive weeks and minutes"); +d = new Temporal.Duration(0, 0, -3, 0, 0, -6); +assert.sameValue(d.toJSON(), "-P3WT6M", "negative weeks and minutes"); +d = new Temporal.Duration(0, 0, 0, 4, 0, 6); +assert.sameValue(d.toJSON(), "P4DT6M", "positive days and minutes"); +d = new Temporal.Duration(0, 0, 0, -4, 0, -6); +assert.sameValue(d.toJSON(), "-P4DT6M", "negative days and minutes"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 7); +assert.sameValue(d.toJSON(), "PT7S", "positive seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -7); +assert.sameValue(d.toJSON(), "-PT7S", "negative seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 0, 7); +assert.sameValue(d.toJSON(), "PT5H7S", "positive hours and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, -5, 0, -7); +assert.sameValue(d.toJSON(), "-PT5H7S", "negative hours and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 6, 7); +assert.sameValue(d.toJSON(), "PT6M7S", "positive minutes and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, -6, -7); +assert.sameValue(d.toJSON(), "-PT6M7S", "negative minutes and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 6, 7); +assert.sameValue(d.toJSON(), "PT5H6M7S", "positive hours, minutes, seconds"); +d = new Temporal.Duration(0, 0, 0, 0, -5, -6, -7); +assert.sameValue(d.toJSON(), "-PT5H6M7S", "negative hours, minutes, seconds"); +d = new Temporal.Duration(1, 0, 0, 0, 5, 6, 7); +assert.sameValue(d.toJSON(), "P1YT5H6M7S", "positive years, hours, minutes, seconds"); +d = new Temporal.Duration(-1, 0, 0, 0, -5, -6, -7); +assert.sameValue(d.toJSON(), "-P1YT5H6M7S", "negative years, hours, minutes, seconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 8); +assert.sameValue(d.toJSON(), "PT0.008S", "positive milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -8); +assert.sameValue(d.toJSON(), "-PT0.008S", "negative milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 80); +assert.sameValue(d.toJSON(), "PT0.08S", "positive milliseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -80); +assert.sameValue(d.toJSON(), "-PT0.08S", "negative milliseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 87); +assert.sameValue(d.toJSON(), "PT0.087S", "positive two-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -87); +assert.sameValue(d.toJSON(), "-PT0.087S", "negative two-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 876); +assert.sameValue(d.toJSON(), "PT0.876S", "positive three-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -876); +assert.sameValue(d.toJSON(), "-PT0.876S", "negative three-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 876543); +assert.sameValue(d.toJSON(), "PT876.543S", "positive large milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -876543); +assert.sameValue(d.toJSON(), "-PT876.543S", "negative large milliseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 9); +assert.sameValue(d.toJSON(), "PT0.000009S", "positive microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -9); +assert.sameValue(d.toJSON(), "-PT0.000009S", "negative microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 90); +assert.sameValue(d.toJSON(), "PT0.00009S", "positive microseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -90); +assert.sameValue(d.toJSON(), "-PT0.00009S", "negative microseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 98); +assert.sameValue(d.toJSON(), "PT0.000098S", "positive two-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -98); +assert.sameValue(d.toJSON(), "-PT0.000098S", "negative two-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 900); +assert.sameValue(d.toJSON(), "PT0.0009S", "positive microseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -900); +assert.sameValue(d.toJSON(), "-PT0.0009S", "negative microseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987); +assert.sameValue(d.toJSON(), "PT0.000987S", "positive three-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987); +assert.sameValue(d.toJSON(), "-PT0.000987S", "negative three-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987654); +assert.sameValue(d.toJSON(), "PT0.987654S", "positive large microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987654); +assert.sameValue(d.toJSON(), "-PT0.987654S", "negative large microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987654321); +assert.sameValue(d.toJSON(), "PT987.654321S", "positive larger microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987654321); +assert.sameValue(d.toJSON(), "-PT987.654321S", "negative larger microseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1); +assert.sameValue(d.toJSON(), "PT0.000000001S", "positive nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1); +assert.sameValue(d.toJSON(), "-PT0.000000001S", "negative nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 10); +assert.sameValue(d.toJSON(), "PT0.00000001S", "positive nanoseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -10); +assert.sameValue(d.toJSON(), "-PT0.00000001S", "negative nanoseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 12); +assert.sameValue(d.toJSON(), "PT0.000000012S", "positive two-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -12); +assert.sameValue(d.toJSON(), "-PT0.000000012S", "negative two-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 100); +assert.sameValue(d.toJSON(), "PT0.0000001S", "positive nanoseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -100); +assert.sameValue(d.toJSON(), "-PT0.0000001S", "negative nanoseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123); +assert.sameValue(d.toJSON(), "PT0.000000123S", "positive three-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123); +assert.sameValue(d.toJSON(), "-PT0.000000123S", "negative three-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123456); +assert.sameValue(d.toJSON(), "PT0.000123456S", "positive large nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123456); +assert.sameValue(d.toJSON(), "-PT0.000123456S", "negative large nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123456789); +assert.sameValue(d.toJSON(), "PT0.123456789S", "positive larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123456789); +assert.sameValue(d.toJSON(), "-PT0.123456789S", "negative larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1234567891); +assert.sameValue(d.toJSON(), "PT1.234567891S", "positive even larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1234567891); +assert.sameValue(d.toJSON(), "-PT1.234567891S", "negative even larger nanoseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 1); +assert.sameValue(d.toJSON(), "PT4.003002001S", "positive seconds and subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -1); +assert.sameValue(d.toJSON(), "-PT4.003002001S", "negative seconds and subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 90001); +assert.sameValue(d.toJSON(), "PT4.003092001S", "positive seconds and large subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -90001); +assert.sameValue(d.toJSON(), "-PT4.003092001S", "negative seconds and large subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 90080001); +assert.sameValue(d.toJSON(), "PT4.093082001S", "positive seconds and larger subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -90080001); +assert.sameValue(d.toJSON(), "-PT4.093082001S", "negative seconds and larger subseconds"); + +d = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 1); +assert.sameValue(d.toJSON(), "P1Y2M3W4DT5H6M7.008009001S", "all fields positive"); +d = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -1); +assert.sameValue(d.toJSON(), "-P1Y2M3W4DT5H6M7.008009001S", "all fields negative"); + +d = new Temporal.Duration(1234, 2345, 3456, 4567, 5678, 6789, 7890, 890, 901, 123); +assert.sameValue(d.toJSON(), "P1234Y2345M3456W4567DT5678H6789M7890.890901123S", "all fields large and positive"); +d = new Temporal.Duration(-1234, -2345, -3456, -4567, -5678, -6789, -7890, -890, -901, -123); +assert.sameValue(d.toJSON(), "-P1234Y2345M3456W4567DT5678H6789M7890.890901123S", "all fields large and negative"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..f7e6f1d7bebc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: > + Tests that Temporal.Duration.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/length.js new file mode 100644 index 000000000000..677218fef5da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: Temporal.Duration.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/name.js new file mode 100644 index 000000000000..1ba0653776cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: Temporal.Duration.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/negative-components.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/negative-components.js new file mode 100644 index 000000000000..db523b0a66e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/negative-components.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: Temporal.Duration.toJSON handles negative components +features: [Temporal] +---*/ +const d = new Temporal.Duration(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1); +const expected = "-P1Y1M1W1DT1H1M1.001001001S"; +assert.sameValue(d.toJSON(), expected, "toJSON with negative components"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..7c937be77313 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: > + Temporal.Duration.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.toJSON), false, + "isConstructor(Temporal.Duration.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..66e165392d57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: The "toJSON" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.toJSON, + "function", + "`typeof Duration.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/builtin.js new file mode 100644 index 000000000000..9a0424909d0b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tolocalestring +description: > + Tests that Temporal.Duration.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/length.js new file mode 100644 index 000000000000..9317f8dff901 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tolocalestring +description: Temporal.Duration.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/name.js new file mode 100644 index 000000000000..46f2f43c35cf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tolocalestring +description: Temporal.Duration.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 000000000000..27abbe918413 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tolocalestring +description: > + Temporal.Duration.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.toLocaleString), false, + "isConstructor(Temporal.Duration.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/prop-desc.js new file mode 100644 index 000000000000..ac70c97ee58d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.toLocaleString, + "function", + "`typeof Duration.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/balance.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/balance.js new file mode 100644 index 000000000000..ec3eaa187042 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/balance.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Verify that values are balanced correctly. +features: [Temporal] +---*/ + +assert.sameValue( + Temporal.Duration.from({ milliseconds: 3500 }).toString(), + "PT3.5S"); +assert.sameValue( + Temporal.Duration.from({ microseconds: 3500 }).toString(), + "PT0.0035S"); +assert.sameValue( + Temporal.Duration.from({ nanoseconds: 3500 }).toString(), + "PT0.0000035S"); +assert.sameValue( + new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 1111, 1111, 1111).toString(), + "PT1.112112111S"); +assert.sameValue( + Temporal.Duration.from({ seconds: 120, milliseconds: 3500 }).toString(), + "PT123.5S"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/blank-duration-precision.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/blank-duration-precision.js new file mode 100644 index 000000000000..950bbffdd53c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/blank-duration-precision.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: > + Precision is handled correctly for blank durations, whether specified by + fractionalSecondDigits or smallestUnit +features: [Temporal] +---*/ + +const blank = new Temporal.Duration(); + +assert.sameValue(blank.toString({ fractionalSecondDigits: "auto" }), "PT0S"); +assert.sameValue(blank.toString({ fractionalSecondDigits: 0 }), "PT0S"); +assert.sameValue(blank.toString({ fractionalSecondDigits: 2 }), "PT0.00S"); +assert.sameValue(blank.toString({ fractionalSecondDigits: 9 }), "PT0.000000000S"); + +assert.sameValue(blank.toString({ smallestUnit: "seconds" }), "PT0S"); +assert.sameValue(blank.toString({ smallestUnit: "milliseconds" }), "PT0.000S"); +assert.sameValue(blank.toString({ smallestUnit: "microseconds" }), "PT0.000000S"); +assert.sameValue(blank.toString({ smallestUnit: "nanoseconds" }), "PT0.000000000S"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/builtin.js new file mode 100644 index 000000000000..d2c4f651909d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: > + Tests that Temporal.Duration.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-exact-number-of-digits.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-exact-number-of-digits.js new file mode 100644 index 000000000000..2b5545b62a82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-exact-number-of-digits.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: | + The fractionalSecondDigits and smallestUnit options determine the exact number + of digits shown after the decimal separator, no more and no less +info: | + sec-temporaldurationtostring step 21: + 21. If any of _seconds_, _milliseconds_, _microseconds_, and _nanoseconds_ are not 0; or _years_, _months_, _weeks_, _days_, _hours_, and _minutes_ are all 0; or _precision_ is not *"auto"*; then +features: [Temporal] +---*/ + +const threeYears = new Temporal.Duration(3); +assert.sameValue(threeYears.toString({ fractionalSecondDigits: 0 }), "P3YT0S"); +assert.sameValue(threeYears.toString({ smallestUnit: 'seconds' }), "P3YT0S"); +assert.sameValue(threeYears.toString({ smallestUnit: 'milliseconds' }), "P3YT0.000S"); +assert.sameValue(threeYears.toString({ fractionalSecondDigits: 5 }), "P3YT0.00000S"); + +const halfHour = new Temporal.Duration(0, 0, 0, 0, 0, 30); +assert.sameValue(halfHour.toString({ fractionalSecondDigits: 0 }), "PT30M0S"); +assert.sameValue(halfHour.toString({ smallestUnit: 'seconds' }), "PT30M0S"); +assert.sameValue(halfHour.toString({ smallestUnit: 'milliseconds' }), "PT30M0.000S"); +assert.sameValue(halfHour.toString({ fractionalSecondDigits: 5 }), "PT30M0.00000S"); + +const hundredMs = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 100); +assert.sameValue(hundredMs.toString({ fractionalSecondDigits: 0 }), "PT0S"); +assert.sameValue(hundredMs.toString({ smallestUnit: 'seconds' }), "PT0S"); +assert.sameValue(hundredMs.toString({ smallestUnit: 'milliseconds' }), "PT0.100S"); +assert.sameValue(hundredMs.toString({ fractionalSecondDigits: 5 }), "PT0.10000S"); + +const zero = new Temporal.Duration(); +assert.sameValue(zero.toString({ fractionalSecondDigits: 0 }), "PT0S"); +assert.sameValue(zero.toString({ smallestUnit: 'seconds' }), "PT0S"); +assert.sameValue(zero.toString({ smallestUnit: 'milliseconds' }), "PT0.000S"); +assert.sameValue(zero.toString({ fractionalSecondDigits: 5 }), "PT0.00000S"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js new file mode 100644 index 000000000000..5342d129871f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values +info: | + sec-getstringornumberoption step 4: + 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.duration.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); + +for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos"]) { + assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-nan.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-nan.js new file mode 100644 index 000000000000..4f7d771b32e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-nan.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.duration.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-non-integer.js new file mode 100644 index 000000000000..841a8f22bbb6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-non-integer.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Rounding for fractionalSecondDigits option +info: | + sec-getstringornumberoption step 3.b: + b. Return floor(ℝ(_value_)). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.duration.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); + +const string = duration.toString({ fractionalSecondDigits: 2.5 }); +assert.sameValue(string, "P1Y2M3W4DT5H6M7.98S", "fractionalSecondDigits 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js new file mode 100644 index 000000000000..5ddcfe36c6fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option out of range +info: | + sec-getstringornumberoption step 3.a: + a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.duration.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); + +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -Infinity })); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -1 })); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: 10 })); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-undefined.js new file mode 100644 index 000000000000..84f0d55c0038 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Fallback value for fractionalSecondDigits option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.duration.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); + +const explicit = duration.toString({ fractionalSecondDigits: undefined }); +assert.sameValue(explicit, "P1Y2M3W4DT5H6M7.98765S", "default fractionalSecondDigits is auto"); + +const implicit = duration.toString({}); +assert.sameValue(implicit, "P1Y2M3W4DT5H6M7.98765S", "default fractionalSecondDigits is auto"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-wrong-type.js new file mode 100644 index 000000000000..cbd95cfdaca7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Type conversions for fractionalSecondDigits option +info: | + sec-getoption steps 8–9: + 8. Else if _type_ is Number, then + a. Set _value_ to ? ToNumber(value). + b. ... + 9. Else, + a. Set _value_ to ? ToString(value). + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.duration.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); +TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(duration); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/length.js new file mode 100644 index 000000000000..9eada90fcd03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Temporal.Duration.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/name.js new file mode 100644 index 000000000000..0f7b7d100a2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Temporal.Duration.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/negative-components.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/negative-components.js new file mode 100644 index 000000000000..fe0cabd98888 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/negative-components.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Temporal.Duration.toString handles negative components +features: [Temporal] +---*/ +assert.sameValue( + new Temporal.Duration(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1).toString(), + "-P1Y1M1W1DT1H1M1.001001001S"); +assert.sameValue( + Temporal.Duration.from({ milliseconds: -250 }).toString(), + "-PT0.25S"); +assert.sameValue( + Temporal.Duration.from({ milliseconds: -3500 }).toString(), + "-PT3.5S"); +assert.sameValue( + Temporal.Duration.from({ microseconds: -250 }).toString(), + "-PT0.00025S"); +assert.sameValue( + Temporal.Duration.from({ microseconds: -3500 }).toString(), + "-PT0.0035S"); +assert.sameValue( + Temporal.Duration.from({ nanoseconds: -250 }).toString(), + "-PT0.00000025S"); +assert.sameValue( + Temporal.Duration.from({ nanoseconds: -3500 }).toString(), + "-PT0.0000035S"); +assert.sameValue( + new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -1111, -1111, -1111).toString(), + "-PT1.112112111S"); +assert.sameValue( + Temporal.Duration.from({ seconds: -120, milliseconds: -3500 }).toString(), + "-PT123.5S"); +assert.sameValue( + Temporal.Duration.from({ weeks: -1, days: -1 }).toString(), + "-P1W1D"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..c1702253430c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: > + Temporal.Duration.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.toString), false, + "isConstructor(Temporal.Duration.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/options-undefined.js new file mode 100644 index 000000000000..e59cb12a4736 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); + +const explicit = duration.toString(undefined); +assert.sameValue(explicit, "P1Y2M3W4DT5H6M7.98765S", "default precision is auto, and rounding is trunc"); + +const implicit = duration.toString(); +assert.sameValue(implicit, "P1Y2M3W4DT5H6M7.98765S", "default precision is auto, and rounding is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/precision.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/precision.js new file mode 100644 index 000000000000..3a7c0b5767a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/precision.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: toString() produces a fractional part of the correct length +features: [Temporal] +---*/ + +const { Duration } = Temporal; + +const durationString = 'PT0.084000159S'; +const duration = Duration.from(durationString); +const precisionString = duration.toString({ + smallestUnit: 'milliseconds' +}); + +assert.sameValue(durationString, duration.toString()); +assert.sameValue(precisionString, "PT0.084S"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..406446767537 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: The "toString" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.toString, + "function", + "`typeof Duration.prototype.toString` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-invalid-string.js new file mode 100644 index 000000000000..18a40f192774 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => duration.toString({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-undefined.js new file mode 100644 index 000000000000..8244b34fa2a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Fallback value for roundingMode option +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); + +const explicit1 = duration.toString({ smallestUnit: "microsecond", roundingMode: undefined }); +assert.sameValue(explicit1, "PT12H34M56.123987S", "default roundingMode is trunc"); +const implicit1 = duration.toString({ smallestUnit: "microsecond" }); +assert.sameValue(implicit1, "PT12H34M56.123987S", "default roundingMode is trunc"); + +const explicit2 = duration.toString({ smallestUnit: "millisecond", roundingMode: undefined }); +assert.sameValue(explicit2, "PT12H34M56.123S", "default roundingMode is trunc"); +const implicit2 = duration.toString({ smallestUnit: "millisecond" }); +assert.sameValue(implicit2, "PT12H34M56.123S", "default roundingMode is trunc"); + +const explicit3 = duration.toString({ smallestUnit: "second", roundingMode: undefined }); +assert.sameValue(explicit3, "PT12H34M56S", "default roundingMode is trunc"); +const implicit3 = duration.toString({ smallestUnit: "second" }); +assert.sameValue(implicit3, "PT12H34M56S", "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-wrong-type.js new file mode 100644 index 000000000000..8bd76f27b780 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => duration.toString({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => assert.sameValue(result, "PT12H34M56.123987S", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js new file mode 100644 index 000000000000..247e8b7637b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +const values = ["eras", "years", "months", "weeks", "days", "hours", "minutes", "nonsense", "other string", "mill\u0131seconds", "SECONDS"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => duration.toString({ smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..b3830900e9fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-plurals-accepted.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const validUnits = [ + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => duration.toString({ smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-undefined.js new file mode 100644 index 000000000000..c84b941e4979 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-undefined.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Fallback value for smallestUnit option +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); + +const explicit1 = duration.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 }); +assert.sameValue(explicit1, "PT12H34M56.123987S", "default smallestUnit defers to fractionalSecondDigits"); +const implicit1 = duration.toString({ fractionalSecondDigits: 6 }); +assert.sameValue(implicit1, "PT12H34M56.123987S", "default smallestUnit defers to fractionalSecondDigits"); + +const explicit2 = duration.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 }); +assert.sameValue(explicit2, "PT12H34M56.123S", "default smallestUnit defers to fractionalSecondDigits"); +const implicit2 = duration.toString({ fractionalSecondDigits: 3 }); +assert.sameValue(implicit2, "PT12H34M56.123S", "default smallestUnit defers to fractionalSecondDigits"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-valid-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-valid-units.js new file mode 100644 index 000000000000..11ad7f828b79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-valid-units.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Valid units for the smallestUnit option +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + +assert.sameValue(duration.toString({ smallestUnit: "second" }), "P1Y2M3W4DT5H6M7S"); +assert.sameValue(duration.toString({ smallestUnit: "millisecond" }), "P1Y2M3W4DT5H6M7.987S"); +assert.sameValue(duration.toString({ smallestUnit: "microsecond" }), "P1Y2M3W4DT5H6M7.987654S"); +assert.sameValue(duration.toString({ smallestUnit: "nanosecond" }), "P1Y2M3W4DT5H6M7.987654321S"); + +const notValid = [ + "year", + "month", + "week", + "day", + "hour", + "minute", +]; + +notValid.forEach((smallestUnit) => { + assert.throws(RangeError, () => duration.toString({ smallestUnit }), smallestUnit); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-wrong-type.js new file mode 100644 index 000000000000..45bef000cb2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/toString/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => duration.toString({ smallestUnit }), + (result, descr) => assert.sameValue(result, "PT12H34M56.123987S", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/balance-negative-result.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/balance-negative-result.js new file mode 100644 index 000000000000..c60dee012726 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/balance-negative-result.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: A negative duration result is balanced correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-balanceduration step 4: + 4. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + sec-temporal.duration.prototype.round step 9: + 9. Let _balanceResult_ be ? BalanceDuration(_unbalanceResult_.[[Days]], _unbalanceResult_.[[Hours]], _unbalanceResult_.[[Minutes]], _unbalanceResult_.[[Seconds]], _unbalanceResult_.[[Milliseconds]], _unbalanceResult_.[[Microseconds]], _unbalanceResult_.[[Nanoseconds]], _unit_, _intermediate_). +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 0, -60); +const result = duration.total({ unit: "days" }); +assert.sameValue(result, -2.5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/builtin.js new file mode 100644 index 000000000000..4b3ada6f306d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + Tests that Temporal.Duration.prototype.total + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.total), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.total), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.total), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.total.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..75afa3acea8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,52 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +// Total of a calendar unit where larger calendar units have to be converted +// down, to cover the path that goes through UnbalanceDurationRelative +// The calls come from these paths: +// Duration.total() -> +// UnbalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd() (3x) +// BalanceDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() + +const instance1 = new Temporal.Duration(1, 1, 1, 1, 1); +instance1.total({ unit: "days", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 8, "converting larger calendar units down"); + +// Total of a calendar unit where smaller calendar units have to be converted +// up, to cover the path that goes through MoveRelativeZonedDateTime +// The calls come from these paths: +// Duration.total() -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// BalanceDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// MoveRelativeDate -> calendar.dateAdd() + +calendar.dateAddCallCount = 0; + +const instance2 = new Temporal.Duration(0, 0, 1, 1); +instance2.total({ unit: "weeks", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 6, "converting smaller calendar units up"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..2232f3eaf4ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.Duration(1, 1, 1, 1); +const relativeTo = new Temporal.PlainDate(2000, 1, 1, calendar); +calendar.specificPlainDate = relativeTo; +instance.total({ unit: "days", relativeTo }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..9fa92eb4f402 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,96 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.duration.prototype.total steps 7–11: + 7. Let _unbalanceResult_ be ? UnbalanceDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _relativeTo_). + ... + 10. Let _balanceResult_ be ? BalanceDuration(_unbalanceResult_.[[Days]], _unbalanceResult_.[[Hours]], _unbalanceResult_.[[Minutes]], _unbalanceResult_.[[Seconds]], _unbalanceResult_.[[Milliseconds]], _unbalanceResult_.[[Microseconds]], _unbalanceResult_.[[Nanoseconds]], _unit_, _intermediate_). + 11. Let _roundResult_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _balanceResult_.[[Days]], _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]], 1, _unit_, *"trunc"*, _relativeTo_). + sec-temporal-unbalancedurationrelative steps 1 and 9.d.iii–v: + 1. If _largestUnit_ is *"year"*, or _years_, _months_, _weeks_, and _days_ are all 0, then + a. Return ... + ... + 9. If _largestUnit_ is *"month"*, then + ... + d. Repeat, while abs(_years_) > 0, + ... + iii. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). + iv. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). + v. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). + sec-temporal-balanceduration step 3.a: + 3. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + sec-temporal-roundduration steps 5.d and 8.n–p: + 5. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + ... + 8. If _unit_ is *"year"*, then + ... + n. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). + o. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). + p. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_) + sec-temporal-nanosecondstodays step 11: + 11. 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*). + sec-temporal-differenceisodatetime steps 9–11: + 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). + 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +// Check the paths that go through NanosecondsToDays: one call to dateUntil() in +// BalanceDuration and one in RoundDuration with largestUnit: "day" when the +// unit is "year", "month", "week", or "day", and one extra call with +// largestUnit: "year" in RoundDuration when the unit is "year". + +const duration = new Temporal.Duration(0, 1, 1, 1, 1, 1, 1, 1, 1, 1); + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, unit) => { + const relativeTo = new Temporal.ZonedDateTime(0n, "UTC", calendar); + duration.total({ unit, relativeTo }); + }, + { + years: ["day", "day", "year"], + months: ["day", "day"], + weeks: ["day", "day"], + days: ["day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +// Check the path that converts years to months in UnbalanceDurationRelative. + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, unit) => { + const duration = new Temporal.Duration(5); + const relativeTo = new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 0, 0, 0, calendar); + duration.total({ unit, relativeTo }); + }, + { + years: ["year"], + months: ["month", "month", "month", "month", "month"], + weeks: [], + days: [], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-fields-iterable.js new file mode 100644 index 000000000000..a9a845631649 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-fields-iterable.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.duration.prototype.total step 4: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); +duration.total({ unit: 'seconds', relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-possibly-required.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-possibly-required.js new file mode 100644 index 000000000000..f2748a1c68c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-possibly-required.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Calendar required when days = 0 but years/months/weeks non-zero +features: [Temporal] +---*/ + +const yearInstance = new Temporal.Duration(1999); +const monthInstance = new Temporal.Duration(0, 49); +const weekInstance = new Temporal.Duration(0, 0, 1); +const dayInstance = new Temporal.Duration(0, 0, 0, 42); + +let relativeTo = new Temporal.PlainDate(2021, 12, 15); + +assert.throws( + RangeError, + () => { yearInstance.total({ unit: "days" }); }, + "total a Duration with non-zero years fails without largest/smallest unit" +); +const yearResult = yearInstance.total({ unit: "days", relativeTo }); +assert.sameValue(yearResult, 730120, "year duration contains proper days"); + +assert.throws( + RangeError, + () => { monthInstance.total({ unit: "days" }); }, + "total a Duration with non-zero month fails without largest/smallest unit" +); + +const monthResult = monthInstance.total({ unit: "days", relativeTo }); +assert.sameValue(monthResult, 1492, "month duration contains proper days"); + +assert.throws( + RangeError, + () => { weekInstance.total({ unit: "days" }); }, + "total a Duration with non-zero weeks fails without largest/smallest unit" +); + +const weekResult = weekInstance.total({ unit: "days", relativeTo }); +assert.sameValue(weekResult, 7, "week duration contains proper days"); + +const dayResultWithoutRelative = dayInstance.total({ unit: "days" }); +const dayResultWithRelative = dayInstance.total({ unit: "days", relativeTo }); +assert.sameValue(dayResultWithoutRelative, 42, "day duration without relative-to part contains proper days"); +assert.sameValue(dayResultWithRelative, 42, "day duration with relative-to part contains proper days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-temporal-object.js new file mode 100644 index 000000000000..c834e67ff290 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.duration.prototype.total step 4: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); + duration.total({ unit: 'seconds', relativeTo: { year: 2000, month: 1, day: 1, calendar: temporalObject } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/dateuntil-field.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/dateuntil-field.js new file mode 100644 index 000000000000..19239ae6224d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/dateuntil-field.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + When consulting calendar.dateUntil() to calculate the number of months in a + year, the months property is not accessed on the result Duration +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "call dateUntil", + "call dateUntil", +]; + +const duration = new Temporal.Duration(0, 12); +TemporalHelpers.observeProperty(actual, duration, "months", 1); + +const calendar = TemporalHelpers.calendarDateUntilObservable(actual, duration); +const relativeTo = new Temporal.PlainDateTime(2018, 10, 12, 0, 0, 0, 0, 0, 0, calendar); + +const years = new Temporal.Duration(2); +const result = years.total({ unit: "months", relativeTo }); +assert.sameValue(result, 24, "result"); +assert.compareArray(actual, expected, "operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/length.js new file mode 100644 index 000000000000..227088e877e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Temporal.Duration.prototype.total.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.total, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/name.js new file mode 100644 index 000000000000..c1ba133fb11f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Temporal.Duration.prototype.total.name is "total". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.total, "name", { + value: "total", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/not-a-constructor.js new file mode 100644 index 000000000000..abf1ec84d37d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + Temporal.Duration.prototype.total does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.total(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.total), false, + "isConstructor(Temporal.Duration.prototype.total)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/options-wrong-type.js new file mode 100644 index 000000000000..ac4625bc1b18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/options-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: TypeError thrown when options argument is missing or a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const values = [ + undefined, + null, + true, + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.Duration(0, 0, 0, 0, 1); +assert.throws(TypeError, () => instance.total(), "TypeError on missing argument"); +values.forEach((value) => { + assert.throws(TypeError, () => instance.total(value), `TypeError on wrong argument type ${typeof(value)}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/prop-desc.js new file mode 100644 index 000000000000..1a7b0a5740b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: The "total" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.total, + "function", + "`typeof Duration.prototype.total` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "total", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..6b1f823943c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/read-time-fields-before-datefromfields.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.duration.prototype.total step 4: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + sec-temporal-torelativetemporalobject step 4.g: + g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInvalidGettersTime(); +const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); +duration.total({ unit: 'seconds', relativeTo: { year: 2000, month: 1, day: 1, calendar } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..fd593ce59b01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.duration.prototype.total +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.total({ unit: "seconds", relativeTo: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.total({ unit: "seconds", relativeTo: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-no-time-units.js new file mode 100644 index 000000000000..8550d132faaa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-no-time-units.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Missing time units in relativeTo property bag default to 0 +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = { year: 2000, month: 1, day: 1 }; +const result = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result, 367, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..d2e4f8ca9d4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + assert.throws(RangeError, () => duration.total({ unit: "seconds", relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..89d6a6d6e692 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => duration.total({ unit: "seconds", relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..9c8e13831dea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + assert.throws(RangeError, () => duration.total({ unit: "seconds", relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..a6f9e394ed6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + assert.throws(TypeError, () => duration.total({ unit: "seconds", relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-datetime.js new file mode 100644 index 000000000000..c09a1e887f89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-datetime.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + Conversion of ISO date-time strings as relativeTo option to + Temporal.ZonedDateTime or Temporal.PlainDateTime instances +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = "2019-11-01T00:00"; +const result1 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result1, 367, "bare date-time string is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00Z"; +const result2 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result2, 367, "date-time + Z is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00-07:00"; +const result3 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result3, 367, "date-time + offset is a plain relativeTo"); + +relativeTo = "2019-11-01T00:00[-07:00]"; +const result4 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result4, 367, "date-time + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00Z[-07:00]"; +const result5 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result5, 367, "date-time + Z + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+00:00[UTC]"; +const result6 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result6, 367, "date-time + offset + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+04:15[UTC]"; +assert.throws(RangeError, () => instance.total({ unit: "days", relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-invalid.js new file mode 100644 index 000000000000..60d0f25974e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: RangeError thrown if relativeTo is a string with the wrong format +features: [Temporal] +---*/ + +['bad string', '15:30:45.123456', 'iso8601', 'UTC', 'P1YT1H'].forEach((relativeTo) => { + const duration = new Temporal.Duration(0, 0, 0, 31); + assert.throws(RangeError, () => duration.total({ unit: "months", relativeTo })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-plaindatetime.js new file mode 100644 index 000000000000..82b52a2fda2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-plaindatetime.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: The relativeTo option accepts a PlainDateTime-like ISO 8601 string +features: [Temporal] +---*/ + +['2000-01-01', '2000-01-01T00:00', '2000-01-01T00:00[u-ca=iso8601]'].forEach((relativeTo) => { + const duration = new Temporal.Duration(0, 0, 0, 31); + const result = duration.total({ unit: "months", relativeTo }); + assert.sameValue(result, 1); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-zoneddatetime-wrong-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-zoneddatetime-wrong-offset.js new file mode 100644 index 000000000000..d987551d2ad5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-zoneddatetime-wrong-offset.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Throws if a ZonedDateTime-like relativeTo string has the wrong UTC offset +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); +const relativeTo = "2000-01-01T00:00+05:30[UTC]"; +assert.throws( + RangeError, + () => instance.total({ unit: "days", relativeTo }), + "total should throw RangeError on a string with UTC offset mismatch" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-zoneddatetime.js new file mode 100644 index 000000000000..8b52616d103e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-string-zoneddatetime.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: The relativeTo option accepts a ZonedDateTime-like ISO 8601 string +features: [Temporal] +---*/ + +[ + '2000-01-01[UTC]', + '2000-01-01T00:00[UTC]', + '2000-01-01T00:00+00:00[UTC]', + '2000-01-01T00:00+00:00[UTC][u-ca=iso8601]', +].forEach((relativeTo) => { + const duration = new Temporal.Duration(0, 0, 0, 31); + const result = duration.total({ unit: "months", relativeTo }); + assert.sameValue(result, 1); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-sub-minute-offset.js new file mode 100644 index 000000000000..97bf73bdac7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-sub-minute-offset.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: relativeTo string accepts an inexact UTC offset rounded to hours and minutes +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = "2000-01-01T00:00+00:45[+00:44:30.123456789]"; +const result = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result, 367, "rounded HH:MM is accepted in string"); + +relativeTo = "2000-01-01T00:00+00:44:30[+00:44:30.123456789]"; +assert.throws(RangeError, () => instance.total({ unit: "days", relativeTo }), "no other rounding is accepted for offset"); + +const timeZone = new Temporal.TimeZone("+00:44:30.123456789"); +relativeTo = { year: 2000, month: 1, day: 1, offset: "+00:45", timeZone }; +assert.throws(RangeError, () => instance.total({ unit: "days", relativeTo }), "rounded HH:MM not accepted as offset in property bag"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-undefined-throw-on-calendar-units.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-undefined-throw-on-calendar-units.js new file mode 100644 index 000000000000..a845710605c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-undefined-throw-on-calendar-units.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + The relativeTo option is required when the Duration contains years, months, + or weeks, and unit is days; or unit is weeks or months +features: [Temporal, arrow-function] +---*/ + +const oneYear = new Temporal.Duration(1); +const oneMonth = new Temporal.Duration(0, 1); +const oneWeek = new Temporal.Duration(0, 0, 1); +const oneDay = new Temporal.Duration(0, 0, 0, 1); + +const options = { unit: "days" }; +assert.sameValue(oneDay.total(options), 1, "days do not require relativeTo"); +assert.sameValue(oneDay.total("days"), 1, "days do not require relativeTo (string shorthand)"); +assert.throws(RangeError, () => oneWeek.total(options), "total days of weeks requires relativeTo"); +assert.throws(RangeError, () => oneWeek.total("days"), "total days of weeks requires relativeTo (string shorthand)"); +assert.throws(RangeError, () => oneMonth.total(options), "total days of months requires relativeTo"); +assert.throws(RangeError, () => oneMonth.total("days"), "total days of months requires relativeTo (string shorthand)"); +assert.throws(RangeError, () => oneYear.total(options), "total days of years requires relativeTo"); +assert.throws(RangeError, () => oneYear.total("days"), "total days of years requires relativeTo (string shorthand)"); + +["months", "weeks"].forEach((unit) => { + [oneDay, oneWeek, oneMonth, oneYear].forEach((duration) => { + assert.throws(RangeError, () => duration.total({ unit }), `${duration} total ${unit} requires relativeTo`); + assert.throws(RangeError, () => duration.total(unit), `${duration} total ${unit} requires relativeTo (string shorthand)`); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..97a0bdb830fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const relativeTo = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time; in this +// case via relativeTo. + +const result = duration.total({ relativeTo, unit: "days" }); +assert.sameValue(result, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..3af889efe658 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => duration.total({ unit: "seconds", relativeTo: datetime })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..9b8a52a146e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => duration.total({ unit: "seconds", relativeTo: datetime }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..8f939f2926a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => duration.total({ unit: "seconds", relativeTo: datetime })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..b23356aea809 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => duration.total({ unit: "seconds", relativeTo: datetime })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..5c6171e13368 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.duration.prototype.total steps 4 and 10: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 10. Let _balanceResult_ be ? BalanceDuration(_unbalanceResult_.[[Days]], [...], _unbalanceResult_.[[Nanoseconds]], _unit_, _intermediate_). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "2000-01-01T00:00:00", // called once on the input relativeTo if ZonedDateTime + "2001-02-09T00:00:00", // called once on the intermediate ZonedDateTime with the calendar parts of the Duration added +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); + duration.total({ unit: 'seconds', relativeTo: { year: 2000, month: 1, day: 1, timeZone } }); +}, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/timezone-string-datetime.js new file mode 100644 index 000000000000..8496a2e9e427 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/timezone-string-datetime.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.total({ unit: "months", relativeTo: { year: 2000, month: 5, day: 2, timeZone } }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.total({ unit: "months", relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + instance.total({ unit: "months", relativeTo: { year: 2000, month: 5, day: 2, timeZone } }); + instance.total({ unit: "months", relativeTo: { year: 2000, month: 5, day: 2, timeZone: { timeZone } } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-disallowed-units-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-disallowed-units-string.js new file mode 100644 index 000000000000..a809afa1a9b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-disallowed-units-string.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Specifically disallowed units for the unit option +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321); +const invalidUnits = [ + "era", + "eras", +]; +invalidUnits.forEach((unit) => { + assert.throws( + RangeError, + () => instance.total({ unit }), + `{ unit: "${unit}" } should not be allowed as an argument to total` + ); + assert.throws( + RangeError, + () => instance.total(unit), + `"${unit}" should not be allowed as an argument to total` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-invalid-string.js new file mode 100644 index 000000000000..e8f44ec99c0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-invalid-string.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.protoype.total +description: RangeError thrown when unit option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaldurationtotal step 1: + 1. Let _unit_ be ? GetOption(_normalizedOptions_, *"unit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », *undefined*). + sec-temporal.duration.protoype.total step 5: + 5. Let _unit_ be ? ToTemporalDurationTotalUnit(_options_). +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 1); +assert.throws(RangeError, () => duration.total({ unit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted-string.js new file mode 100644 index 000000000000..10ab9c8cce2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted-string.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Plural units are accepted as well for the shorthand for the unit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321); +const validUnits = [ + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((unit) => duration.total(unit), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted.js new file mode 100644 index 000000000000..907013a3cbc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Plural units are accepted as well for the unit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const relativeTo = new Temporal.PlainDate(2000, 1, 1); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((unit) => duration.total({ unit, relativeTo }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-string-shorthand-string.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-string-shorthand-string.js new file mode 100644 index 000000000000..1656ed163e6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-string-shorthand-string.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: String as first argument is equivalent to options bag with unit option +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321); +const validUnits = [ + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +validUnits.forEach((unit) => { + const full = instance.total({ unit }); + const shorthand = instance.total(unit); + assert.sameValue(shorthand, full, `"${unit}" as first argument to total is equivalent to options bag`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-wrong-type.js new file mode 100644 index 000000000000..17cb6481219c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/unit-wrong-type.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Type conversions for unit option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaldurationtotal step 1: + 1. Let _unit_ be ? GetOption(_normalizedOptions_, *"unit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », *undefined*). + sec-temporal.duration.protoype.total step 5: + 5. Let _unit_ be ? ToTemporalDurationTotalUnit(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(0, 0, 0, 1); +TemporalHelpers.checkStringOptionWrongType("unit", "hour", + (unit) => duration.total({ unit }), + (result, descr) => assert.sameValue(result, 24, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/year-zero.js new file mode 100644 index 000000000000..998103d1df95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/total/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = "-000000-11-04T00:00"; +assert.throws( + RangeError, + () => { instance.total({ unit: "days", relativeTo }); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/builtin.js new file mode 100644 index 000000000000..3f3b70b680f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.valueof +description: > + Tests that Temporal.Duration.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/length.js new file mode 100644 index 000000000000..303ce90d094f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.valueof +description: Temporal.Duration.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/name.js new file mode 100644 index 000000000000..4987ef53fbef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.valueof +description: Temporal.Duration.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/not-a-constructor.js new file mode 100644 index 000000000000..8d9793048494 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.valueof +description: > + Temporal.Duration.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.valueOf), false, + "isConstructor(Temporal.Duration.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/prop-desc.js new file mode 100644 index 000000000000..6f0515265d5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.valueof +description: The "valueOf" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.valueOf, + "function", + "`typeof Duration.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/valueOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/weeks/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/weeks/prop-desc.js new file mode 100644 index 000000000000..41d8328102a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/weeks/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.weeks +description: The "weeks" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "weeks"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/all-negative.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/all-negative.js new file mode 100644 index 000000000000..d9c82daef35c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/all-negative.js @@ -0,0 +1,96 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces the fields with + all negative values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const argAllNegative = { + years: -9, + months: -8, + weeks: -7, + days: -6, + hours: -5, + minutes: -4, + seconds: -3, + milliseconds: -2, + microseconds: -1, + nanoseconds: -10, +}; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all zeroes with all negative" +); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all positive with all negative" +); + +const d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all positive large numbers with all negative" +); + +const d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all negative with all negative" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/all-positive.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/all-positive.js new file mode 100644 index 000000000000..cb5944e0824d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/all-positive.js @@ -0,0 +1,95 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces the fields with + all positive values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const argAllPositive = { + years: 9, + months: 8, + weeks: 7, + days: 6, + hours: 5, + minutes: 4, + seconds: 3, + milliseconds: 2, + microseconds: 1, + nanoseconds: 10, +}; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all zeroes with all positive" +); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all positive with all positive"); + +const d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all positive large numbers with all positive" +); + +const d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all negative with all positive" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js new file mode 100644 index 000000000000..f4dc04b36305 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + The durationLike argument must contain at least one correctly spelled property +features: [Temporal] +---*/ + +let d = new Temporal.Duration(1, 2, 3, 4, 5); + +[ + {}, + [], + () => {}, + // objects with only singular keys (plural is the correct spelling) + { year: 1 }, + { month: 2 }, + { week: 3 }, + { day: 4 }, + { hour: 5 }, + { minute: 6 }, + { second: 7 }, + { millisecond: 8 }, + { microsecond: 9 }, + { nanosecond: 10 }, +].forEach((badObject) => { + assert.throws(TypeError, () => d.with(badObject), + "Throw TypeError if temporalDurationLike is not valid"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js new file mode 100644 index 000000000000..d1fe48ca5cca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Throw TypeError if the temporalDurationLike argument is the wrong type +features: [Temporal] +---*/ + +let d = new Temporal.Duration(1, 2, 3, 4, 5); + +[ + "string", + "P1YT1M", + true, + false, + NaN, + Infinity, + undefined, + null, + 123, + Symbol(), + 456n, +].forEach((badInput) => { + assert.throws(TypeError, () => d.with(badInput), + "Throw TypeError if temporalDurationLike is not valid"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/branding.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/branding.js index 7a0b426066ed..cc0d3d4a4fb8 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/branding.js @@ -12,14 +12,16 @@ const with_ = Temporal.Duration.prototype.with; assert.sameValue(typeof with_, "function"); -assert.throws(TypeError, () => with_.call(undefined), "undefined"); -assert.throws(TypeError, () => with_.call(null), "null"); -assert.throws(TypeError, () => with_.call(true), "true"); -assert.throws(TypeError, () => with_.call(""), "empty string"); -assert.throws(TypeError, () => with_.call(Symbol()), "symbol"); -assert.throws(TypeError, () => with_.call(1), "1"); -assert.throws(TypeError, () => with_.call({}), "plain object"); -assert.throws(TypeError, () => with_.call(Temporal.Duration), "Temporal.Duration"); -assert.throws(TypeError, () => with_.call(Temporal.Duration.prototype), "Temporal.Duration.prototype"); +const arg = { years: 3 }; + +assert.throws(TypeError, () => with_.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => with_.call(null, arg), "null"); +assert.throws(TypeError, () => with_.call(true, arg), "true"); +assert.throws(TypeError, () => with_.call("", arg), "empty string"); +assert.throws(TypeError, () => with_.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => with_.call(1, arg), "1"); +assert.throws(TypeError, () => with_.call({}, arg), "plain object"); +assert.throws(TypeError, () => with_.call(Temporal.Duration, arg), "Temporal.Duration"); +assert.throws(TypeError, () => with_.call(Temporal.Duration.prototype, arg), "Temporal.Duration.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/builtin.js new file mode 100644 index 000000000000..cc68b2546fe8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Tests that Temporal.Duration.prototype.with + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Duration.prototype.with), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Duration.prototype.with), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Duration.prototype.with), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Duration.prototype.with.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/copy-properties-not-undefined.js new file mode 100644 index 000000000000..1c9a44210633 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/copy-properties-not-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: PreparePartialTemporalFields copies only defined properties of source object +info: | + 4. For each value _property_ of _fieldNames_, do + a. Let _value_ be ? Get(_fields_, _property_). + b. If _value_ is not *undefined*, then + ... + iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const d = new Temporal.Duration(9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + +TemporalHelpers.assertDuration( + d.with({ minutes: 11, hours: 6, months: undefined }), + 9, 8, 7, 6, 6, 11, 3, 2, 1, 0, + "only the properties that are present and defined in the plain object are copied" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..8ea74b43c535 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration.prototype.with handles a property bag if any value is Infinity +esid: sec-temporal.duration.prototype.with +features: [Temporal] +---*/ + +const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds']; + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.with({ [field]: Infinity })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.with({ [field]: obj })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/length.js new file mode 100644 index 000000000000..0b4020884d13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Temporal.Duration.prototype.with.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.with, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/name.js new file mode 100644 index 000000000000..1b49cf1e02e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Temporal.Duration.prototype.with.name is "with". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Duration.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..c84e2f379ef5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/negative-infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Duration.prototype.with throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.duration.prototype.with +features: [Temporal] +---*/ + +const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds']; + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.with({ [field]: -Infinity })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.with({ [field]: obj })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..d43fff4046ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.with({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.with({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/not-a-constructor.js new file mode 100644 index 000000000000..f75031928df4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Temporal.Duration.prototype.with does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Duration.prototype.with(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Duration.prototype.with), false, + "isConstructor(Temporal.Duration.prototype.with)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/order-of-operations.js new file mode 100644 index 000000000000..5bc9bb87575a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/order-of-operations.js @@ -0,0 +1,76 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Properties on an object passed to with() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.with(argument); +TemporalHelpers.assertDuration(result, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/partial-positive.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/partial-positive.js new file mode 100644 index 000000000000..1fcf68a06d3f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/partial-positive.js @@ -0,0 +1,89 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces only some of the + fields with positive values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const durationlike1 = { years: 9, hours: 5 }; +const durationlike2 = { months: 8, minutes: 4 }; +const durationlike3 = { weeks: 7, seconds: 3 }; +const durationlike4 = { days: 6, milliseconds: 2 }; +const durationlike5 = { microseconds: 987, nanoseconds: 123 }; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(durationlike1), 9, 0, 0, 0, 5, 0, 0, 0, 0, 0, "replace all zeroes with years and hours"); +TemporalHelpers.assertDuration( + d1.with(durationlike2), 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, "replace all zeroes wtih months and minutes"); +TemporalHelpers.assertDuration( + d1.with(durationlike3), 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, "replace all zeroes with weeks and seconds"); +TemporalHelpers.assertDuration( + d1.with(durationlike4), 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, "replace all zeroes with days and milliseconds"); +TemporalHelpers.assertDuration( + d1.with(durationlike5), 0, 0, 0, 0, 0, 0, 0, 0, 987, 123, "replace all zeroes with microseconds and nanoseconds"); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(durationlike1), 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, "replace all positive with years and hours"); +TemporalHelpers.assertDuration( + d2.with(durationlike2), 1, 8, 3, 4, 5, 4, 7, 8, 9, 10, "replace all positive with months and minutes"); +TemporalHelpers.assertDuration( + d2.with(durationlike3), 1, 2, 7, 4, 5, 6, 3, 8, 9, 10, "replace all positive with weeks and seconds"); +TemporalHelpers.assertDuration( + d2.with(durationlike4), 1, 2, 3, 6, 5, 6, 7, 2, 9, 10, "replace all positive with days and milliseconds"); +TemporalHelpers.assertDuration( + d2.with(durationlike5), 1, 2, 3, 4, 5, 6, 7, 8, 987, 123, "replace all positive with microseconds and nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/prop-desc.js new file mode 100644 index 000000000000..089d685b7605 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: The "with" property of Temporal.Duration.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Duration.prototype.with, + "function", + "`typeof Duration.prototype.with` is `function`" +); + +verifyProperty(Temporal.Duration.prototype, "with", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js new file mode 100644 index 000000000000..d62a20b49bfa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Throw RangeError if the resulting duration has mixed signs +info: | + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +---*/ + +const d1 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +const d2 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +fields.forEach((field) => { + assert.throws( + RangeError, + () => d1.with({ [field]: -1 }), + `sign in argument { ${field}: -1 } conflicting with sign of duration should throw RangeError` + ); + + assert.throws( + RangeError, + () => d2.with({ [field]: 1 }), + `sign in argument { ${field}: 1 } conflicting with sign of duration should throw RangeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/subclassing-ignored.js new file mode 100644 index 000000000000..e4cb685baef4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/with/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Duration, + [0, 0, 0, 4, 5, 6, 7, 987, 654, 321], + "with", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 5, 6, 7, 987, 654, 1), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/prototype/years/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/years/prop-desc.js new file mode 100644 index 000000000000..6f9a65911f01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/prototype/years/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.duration.prototype.years +description: The "years" property of Temporal.Duration.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Duration.prototype, "years"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/seconds-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/seconds-undefined.js new file mode 100644 index 000000000000..1cb0d3b60b48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/seconds-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1, 1, 1, 1, 1, 1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/shell.js b/js/src/tests/test262/built-ins/Temporal/Duration/shell.js index e69de29bb2d1..1d70b7579ee9 100644 --- a/js/src/tests/test262/built-ins/Temporal/Duration/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Duration/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/weeks-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/weeks-undefined.js new file mode 100644 index 000000000000..f7536b3fea06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/weeks-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [1, 1]; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Duration/years-undefined.js b/js/src/tests/test262/built-ins/Temporal/Duration/years-undefined.js new file mode 100644 index 000000000000..7907131bd0ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Duration/years-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = []; + +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/argument.js b/js/src/tests/test262/built-ins/Temporal/Instant/argument.js new file mode 100644 index 000000000000..62ea2c4590bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/argument.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant +description: TypeError thrown if input is of wrong primitive type +features: [Symbol, Temporal] +---*/ + +assert.throws(TypeError, () => new Temporal.Instant(), "undefined"); +assert.throws(TypeError, () => new Temporal.Instant(undefined), "undefined"); +assert.throws(TypeError, () => new Temporal.Instant(null), "null"); +assert.throws(TypeError, () => new Temporal.Instant(42), "number"); +assert.throws(TypeError, () => new Temporal.Instant(Symbol()), "symbol"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/basic.js new file mode 100644 index 000000000000..566da7f8bc7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/basic.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant +description: Basic functionality of the Temporal.Instant constructor +features: [Temporal] +---*/ + +const bigIntInstant = new Temporal.Instant(217175010123456789n); +assert(bigIntInstant instanceof Temporal.Instant, "BigInt instanceof"); +assert.sameValue(bigIntInstant.epochSeconds, 217175010, "BigInt epochSeconds"); +assert.sameValue(bigIntInstant.epochMilliseconds, 217175010123, "BigInt epochMilliseconds"); + +const stringInstant = new Temporal.Instant("217175010123456789"); +assert(stringInstant instanceof Temporal.Instant, "String instanceof"); +assert.sameValue(stringInstant.epochSeconds, 217175010, "String epochSeconds"); +assert.sameValue(stringInstant.epochMilliseconds, 217175010123, "String epochMilliseconds"); + +assert.throws(SyntaxError, () => new Temporal.Instant("abc123"), "invalid BigInt syntax"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/builtin.js new file mode 100644 index 000000000000..f3ac5bc169dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant +description: Tests that Temporal.Instant meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.Instant.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/argument-zoneddatetime.js new file mode 100644 index 000000000000..23e125396ab0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/argument-zoneddatetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.instant.compare steps 1–2: + 1. Set _one_ to ? ToTemporalInstant(_one_). + 2. Set _two_ to ? ToTemporalInstant(_two_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_000_000_000n); + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const result = Temporal.Instant.compare(datetime, instant); + assert.sameValue(result, 1, "comparison result"); +}); + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const result = Temporal.Instant.compare(instant, datetime); + assert.sameValue(result, -1, "comparison result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/era/browser.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/era/browser.js rename to js/src/tests/test262/built-ins/Temporal/Instant/compare/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/builtin.js new file mode 100644 index 000000000000..fc4c3f182e09 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: Tests that Temporal.Instant.compare meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.compare), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.compare), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.compare), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.compare.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/instant-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/instant-string-multiple-offsets.js new file mode 100644 index 000000000000..72a38b94807a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/instant-string-multiple-offsets.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: Instant strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const epoch = new Temporal.Instant(0n); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +assert.sameValue(Temporal.Instant.compare(str, epoch), 0, "UTC offset determined from offset part of string (first argument)"); +assert.sameValue(Temporal.Instant.compare(epoch, str), 0, "UTC offset determined from offset part of string (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/instant-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/instant-string.js new file mode 100644 index 000000000000..1f94f7c2156a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/instant-string.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: Conversion of ISO date-time strings to Temporal.Instant instances +features: [Temporal] +---*/ + +const epoch = new Temporal.Instant(0n); +const hourBefore = new Temporal.Instant(-3600_000_000_000n); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => Temporal.Instant.compare(str, epoch), "bare date-time string is not an instant (first argument)"); +assert.throws(RangeError, () => Temporal.Instant.compare(epoch, str), "bare date-time string is not an instant (second argument)"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => Temporal.Instant.compare(str, epoch), "date-time + IANA annotation is not an instant (first argument)"); +assert.throws(RangeError, () => Temporal.Instant.compare(epoch, str), "date-time + IANA annotation is not an instant (second argument)"); + +str = "1970-01-01T00:00Z"; +assert.sameValue(Temporal.Instant.compare(str, epoch), 0, "date-time + Z preserves exact time (first argument)"); +assert.sameValue(Temporal.Instant.compare(epoch, str), 0, "date-time + Z preserves exact time (second argument)"); + +str = "1970-01-01T00:00+01:00"; +assert.sameValue(Temporal.Instant.compare(str, hourBefore), 0, "date-time + offset preserves exact time with offset (first argument)"); +assert.sameValue(Temporal.Instant.compare(hourBefore, str), 0, "date-time + offset preserves exact time with offset (second argument)"); + +str = "1970-01-01T00:00Z[Etc/Ignored]"; +assert.sameValue(Temporal.Instant.compare(str, epoch), 0, "date-time + Z + IANA annotation ignores the IANA annotation (first argument)"); +assert.sameValue(Temporal.Instant.compare(epoch, str), 0, "date-time + Z + IANA annotation ignores the IANA annotation (second argument)"); + +str = "1970-01-01T00:00+01:00[Etc/Ignored]"; +assert.sameValue(Temporal.Instant.compare(str, hourBefore), 0, "date-time + offset + IANA annotation ignores the IANA annotation (first argument)"); +assert.sameValue(Temporal.Instant.compare(hourBefore, str), 0, "date-time + offset + IANA annotation ignores the IANA annotation (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/length.js new file mode 100644 index 000000000000..0c6d388ff3d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: Temporal.Instant.compare.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.compare, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/name.js new file mode 100644 index 000000000000..2bf1eb9de7dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: Temporal.Instant.compare.name is "compare" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.compare, "name", { + value: "compare", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/not-a-constructor.js new file mode 100644 index 000000000000..af5c0423c89d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: Temporal.Instant.compare does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.compare(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.compare), false, + "isConstructor(Temporal.Instant.compare)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/prop-desc.js new file mode 100644 index 000000000000..bfea5e1ac5c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: The "compare" property of Temporal.Instant +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.compare, + "function", + "`typeof Instant.compare` is `function`" +); + +verifyProperty(Temporal.Instant, "compare", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/compare/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Instant/compare/year-zero.js new file mode 100644 index 000000000000..9ee12478173c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/compare/year-zero.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.compare +description: Negative zero, as an extended year, fails +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); +const bad = '-000000-03-30T00:45Z'; + +assert.throws(RangeError, + () => Temporal.Instant.compare(bad, instance), + "minus zero is invalid extended year (first argument)"); +assert.throws(RangeError, + () => Temporal.Instant.compare(instance, bad), + "minus zero is invalid extended year (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/constructor.js new file mode 100644 index 000000000000..966fddb18893 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant +description: Temporal.Instant constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.Instant()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/argument-zoneddatetime.js new file mode 100644 index 000000000000..75b1ccc1a595 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/argument-zoneddatetime.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.instant.from step 2: + 2. Return ? ToTemporalInstant(_item_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const result = Temporal.Instant.from(datetime); + assert.sameValue(result.epochNanoseconds, result.epochNanoseconds, "epochNanoseconds result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/eraYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/eraYear/browser.js rename to js/src/tests/test262/built-ins/Temporal/Instant/from/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/builtin.js new file mode 100644 index 000000000000..e9c17cb74290 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Tests that Temporal.Instant.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/instant-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/instant-string-multiple-offsets.js new file mode 100644 index 000000000000..8b4dc9de3380 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/instant-string-multiple-offsets.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Instant strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = Temporal.Instant.from(str); +assert.sameValue(result.epochNanoseconds, 0n, "UTC offset determined from offset part of string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/instant-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/instant-string.js new file mode 100644 index 000000000000..4ae11c02e7b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/instant-string.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Conversion of ISO date-time strings to Temporal.Instant instances +features: [Temporal] +---*/ + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => Temporal.Instant.from(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => Temporal.Instant.from(str), "date-time + IANA annotation is not an instant"); + +str = "1970-01-01T00:00Z"; +const result1 = Temporal.Instant.from(str); +assert.sameValue(result1.epochNanoseconds, 0n, "date-time + Z preserves exact time"); + +str = "1970-01-01T00:00+01:00"; +const result2 = Temporal.Instant.from(str); +assert.sameValue(result2.epochNanoseconds, -3600_000_000_000n, "date-time + offset preserves exact time with offset"); + +str = "1970-01-01T00:00Z[Etc/Ignored]"; +const result3 = Temporal.Instant.from(str); +assert.sameValue(result3.epochNanoseconds, 0n, "date-time + Z + IANA annotation ignores the IANA annotation"); + +str = "1970-01-01T00:00+01:00[Etc/Ignored]"; +const result4 = Temporal.Instant.from(str); +assert.sameValue(result4.epochNanoseconds, -3600_000_000_000n, "date-time + offset + IANA annotation ignores the IANA annotation"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/length.js new file mode 100644 index 000000000000..0dc90ed9cba0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Temporal.Instant.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/name.js new file mode 100644 index 000000000000..498e801e07e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Temporal.Instant.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/not-a-constructor.js new file mode 100644 index 000000000000..e00d79c4a670 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Temporal.Instant.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.from), false, + "isConstructor(Temporal.Instant.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/prop-desc.js new file mode 100644 index 000000000000..2dbdf7af0261 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: The "from" property of Temporal.Instant +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.from, + "function", + "`typeof Instant.from` is `function`" +); + +verifyProperty(Temporal.Instant, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/subclassing-ignored.js new file mode 100644 index 000000000000..0c86accc1f3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/subclassing-ignored.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.Instant, + "from", + ["1976-11-18T14:23:30.123456789Z"], + (result) => assert.sameValue(result.epochNanoseconds, 217_175_010_123_456_789n, "epochNanoseconds result"), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/timezone-custom.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/timezone-custom.js new file mode 100644 index 000000000000..c416e7ac9ee0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/timezone-custom.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Time zone annotation is ignored in input ISO string +features: [Temporal] +---*/ + +const dateTimeString = "1975-02-02T14:25:36.123456789"; + +Object.defineProperty(Temporal.TimeZone, "from", { + get() { + throw new Test262Error("should not get Temporal.TimeZone.from"); + }, +}); + +const instant = Temporal.Instant.from(dateTimeString + "+01:00[Custom/TimeZone]"); +assert.sameValue(instant.epochMilliseconds, 160579536123); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Instant/from/year-zero.js new file mode 100644 index 000000000000..102a16602a6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/from/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.from +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "-000000-03-31T00:45Z", + "-000000-03-31T01:45+01:00", + "-000000-03-31T01:45:00+01:00[UTC]" +]; + +invalidStrings.forEach((str) => { + assert.throws( + RangeError, + () => Temporal.Instant.from(str), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/basic.js new file mode 100644 index 000000000000..f735124d5dac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/basic.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmicroseconds +description: Basic tests for Instant.fromEpochMicroseconds(). +features: [BigInt, Temporal] +---*/ + +const afterEpoch = Temporal.Instant.fromEpochMicroseconds(217175010_123_456n); +assert.sameValue(afterEpoch.epochNanoseconds, 217175010_123_456_000n, "fromEpochMicroseconds post epoch"); + +const beforeEpoch = Temporal.Instant.fromEpochMicroseconds(-217175010_876_543n); +assert.sameValue(beforeEpoch.epochNanoseconds, -217175010_876_543_000n, "fromEpochMicroseconds pre epoch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/era/browser.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/era/browser.js rename to js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/builtin.js new file mode 100644 index 000000000000..9e034224bcfc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmicroseconds +description: Tests that Temporal.Instant.fromEpochMicroseconds meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.fromEpochMicroseconds), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.fromEpochMicroseconds), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.fromEpochMicroseconds), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.fromEpochMicroseconds.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/length.js new file mode 100644 index 000000000000..116720efa727 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmicroseconds +description: Temporal.Instant.fromEpochMicroseconds.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.fromEpochMicroseconds, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/name.js new file mode 100644 index 000000000000..3556ace0824a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmicroseconds +description: Temporal.Instant.fromEpochMicroseconds.name is "fromEpochMicroseconds" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.fromEpochMicroseconds, "name", { + value: "fromEpochMicroseconds", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/not-a-constructor.js new file mode 100644 index 000000000000..d0f36ae2c33e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmicroseconds +description: Temporal.Instant.fromEpochMicroseconds does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.fromEpochMicroseconds(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.fromEpochMicroseconds), false, + "isConstructor(Temporal.Instant.fromEpochMicroseconds)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/prop-desc.js new file mode 100644 index 000000000000..8d2e620759f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmicroseconds +description: The "fromEpochMicroseconds" property of Temporal.Instant +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.fromEpochMicroseconds, + "function", + "`typeof Instant.fromEpochMicroseconds` is `function`" +); + +verifyProperty(Temporal.Instant, "fromEpochMicroseconds", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/subclassing-ignored.js new file mode 100644 index 000000000000..0afdd2d9634b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMicroseconds/subclassing-ignored.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmicroseconds +description: The receiver is never called by fromEpochMicroseconds() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.Instant, + "fromEpochMicroseconds", + [10n], + (result) => { + assert.sameValue(result.epochNanoseconds, 10_000n, "epochNanoseconds result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/basic.js new file mode 100644 index 000000000000..ca4c8efc1287 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/basic.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmilliseconds +description: Basic tests for Instant.fromEpochMilliseconds(). +features: [BigInt, Temporal] +---*/ + +const afterEpoch = Temporal.Instant.fromEpochMilliseconds(217175010_123); +assert.sameValue(afterEpoch.epochNanoseconds, 217175010_123_000_000n, "fromEpochMilliseconds post epoch"); + +const beforeEpoch = Temporal.Instant.fromEpochMilliseconds(-217175010_876); +assert.sameValue(beforeEpoch.epochNanoseconds, -217175010_876_000_000n, "fromEpochMilliseconds pre epoch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/eraYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/eraYear/browser.js rename to js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/builtin.js new file mode 100644 index 000000000000..f3de20db3b9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmilliseconds +description: Tests that Temporal.Instant.fromEpochMilliseconds meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.fromEpochMilliseconds), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.fromEpochMilliseconds), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.fromEpochMilliseconds), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.fromEpochMilliseconds.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/length.js new file mode 100644 index 000000000000..a3a32ded01d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmilliseconds +description: Temporal.Instant.fromEpochMilliseconds.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.fromEpochMilliseconds, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/name.js new file mode 100644 index 000000000000..b2eacb566576 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmilliseconds +description: Temporal.Instant.fromEpochMilliseconds.name is "fromEpochMilliseconds" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.fromEpochMilliseconds, "name", { + value: "fromEpochMilliseconds", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/not-a-constructor.js new file mode 100644 index 000000000000..e3ff16b3fcc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmilliseconds +description: Temporal.Instant.fromEpochMilliseconds does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.fromEpochMilliseconds(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.fromEpochMilliseconds), false, + "isConstructor(Temporal.Instant.fromEpochMilliseconds)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/prop-desc.js new file mode 100644 index 000000000000..be9a8684cdc4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmilliseconds +description: The "fromEpochMilliseconds" property of Temporal.Instant +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.fromEpochMilliseconds, + "function", + "`typeof Instant.fromEpochMilliseconds` is `function`" +); + +verifyProperty(Temporal.Instant, "fromEpochMilliseconds", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/subclassing-ignored.js new file mode 100644 index 000000000000..1b0aad1a2933 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochMilliseconds/subclassing-ignored.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochmilliseconds +description: The receiver is never called by fromEpochMilliseconds() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.Instant, + "fromEpochMilliseconds", + [10], + (result) => { + assert.sameValue(result.epochNanoseconds, 10_000_000n, "epochNanoseconds result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/basic.js new file mode 100644 index 000000000000..af6f12dadf3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/basic.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochnanoseconds +description: Basic tests for Instant.fromEpochNanoseconds(). +features: [BigInt, Temporal] +---*/ + +const afterEpoch = Temporal.Instant.fromEpochNanoseconds(217175010_123_456_789n); +assert.sameValue(afterEpoch.epochNanoseconds, 217175010_123_456_789n, "fromEpochNanoseconds post epoch"); + +const beforeEpoch = Temporal.Instant.fromEpochNanoseconds(-217175010_876_543_211n); +assert.sameValue(beforeEpoch.epochNanoseconds, -217175010_876_543_211n, "fromEpochNanoseconds pre epoch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/era/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/era/shell.js rename to js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/builtin.js new file mode 100644 index 000000000000..845befb43a0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochnanoseconds +description: Tests that Temporal.Instant.fromEpochNanoseconds meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.fromEpochNanoseconds), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.fromEpochNanoseconds), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.fromEpochNanoseconds), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.fromEpochNanoseconds.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/length.js new file mode 100644 index 000000000000..87be4c77d78c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochnanoseconds +description: Temporal.Instant.fromEpochNanoseconds.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.fromEpochNanoseconds, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/name.js new file mode 100644 index 000000000000..8de6602857f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochnanoseconds +description: Temporal.Instant.fromEpochNanoseconds.name is "fromEpochNanoseconds" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.fromEpochNanoseconds, "name", { + value: "fromEpochNanoseconds", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/not-a-constructor.js new file mode 100644 index 000000000000..db51a1882ef3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochnanoseconds +description: Temporal.Instant.fromEpochNanoseconds does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.fromEpochNanoseconds(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.fromEpochNanoseconds), false, + "isConstructor(Temporal.Instant.fromEpochNanoseconds)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/prop-desc.js new file mode 100644 index 000000000000..88d975468361 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochnanoseconds +description: The "fromEpochNanoseconds" property of Temporal.Instant +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.fromEpochNanoseconds, + "function", + "`typeof Instant.fromEpochNanoseconds` is `function`" +); + +verifyProperty(Temporal.Instant, "fromEpochNanoseconds", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/subclassing-ignored.js new file mode 100644 index 000000000000..5fa23ff9a4fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochNanoseconds/subclassing-ignored.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochnanoseconds +description: The receiver is never called by fromEpochNanoseconds() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.Instant, + "fromEpochNanoseconds", + [10n], + (result) => { + assert.sameValue(result.epochNanoseconds, 10n, "epochNanoseconds result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/basic.js new file mode 100644 index 000000000000..e4e8a3a9872d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/basic.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochseconds +description: Basic tests for Instant.fromEpochSeconds(). +features: [BigInt, Temporal] +---*/ + +const afterEpoch = Temporal.Instant.fromEpochSeconds(217175010); +assert.sameValue(afterEpoch.epochNanoseconds, 217175010_000_000_000n, "fromEpochSeconds post epoch"); + +const beforeEpoch = Temporal.Instant.fromEpochSeconds(-217175010); +assert.sameValue(beforeEpoch.epochNanoseconds, -217175010_000_000_000n, "fromEpochSeconds pre epoch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/eraYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/eraYear/shell.js rename to js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/builtin.js new file mode 100644 index 000000000000..7fe05a72d7f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochseconds +description: Tests that Temporal.Instant.fromEpochSeconds meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.fromEpochSeconds), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.fromEpochSeconds), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.fromEpochSeconds), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.fromEpochSeconds.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/length.js new file mode 100644 index 000000000000..4a2fc62bff0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochseconds +description: Temporal.Instant.fromEpochSeconds.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.fromEpochSeconds, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/name.js new file mode 100644 index 000000000000..8439043598d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochseconds +description: Temporal.Instant.fromEpochSeconds.name is "fromEpochSeconds" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.fromEpochSeconds, "name", { + value: "fromEpochSeconds", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/not-a-constructor.js new file mode 100644 index 000000000000..b4db100e3a4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochseconds +description: Temporal.Instant.fromEpochSeconds does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.fromEpochSeconds(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.fromEpochSeconds), false, + "isConstructor(Temporal.Instant.fromEpochSeconds)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/prop-desc.js new file mode 100644 index 000000000000..333bd7b44286 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochseconds +description: The "fromEpochSeconds" property of Temporal.Instant +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.fromEpochSeconds, + "function", + "`typeof Instant.fromEpochSeconds` is `function`" +); + +verifyProperty(Temporal.Instant, "fromEpochSeconds", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/subclassing-ignored.js new file mode 100644 index 000000000000..35b2f720c99b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/fromEpochSeconds/subclassing-ignored.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.fromepochseconds +description: The receiver is never called by fromEpochSeconds() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.Instant, + "fromEpochSeconds", + [10], + (result) => { + assert.sameValue(result.epochNanoseconds, 10_000_000_000n, "epochNanoseconds result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/length.js new file mode 100644 index 000000000000..4fb46964314f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant +description: Temporal.Instant.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/name.js new file mode 100644 index 000000000000..e41954a219d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant +description: Temporal.Instant.name is "Instant" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant, "name", { + value: "Instant", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prop-desc.js new file mode 100644 index 000000000000..39a72f2fc2d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant +description: The "Instant" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant, + "function", + "`typeof Instant` is `function`" +); + +verifyProperty(Temporal, "Instant", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..924875c5f771 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: Strings with fractional duration units are rounded with the correct rounding mode +features: [Temporal] +---*/ + +const epoch = new Temporal.Instant(0n); + +assert.sameValue(epoch.add("PT1.03125H").epochNanoseconds, 3712_500_000_000n, + "positive fractional units rounded with correct rounding mode"); +assert.sameValue(epoch.add("-PT1.03125H").epochNanoseconds, -3712_500_000_000n, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..cbfdbbcf629c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string-negative-fractional-units.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: Strings with fractional duration units are treated with the correct sign +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(1_000_000_000_000_000_000n); + +const resultHours = instance.add("-PT24.567890123H"); +assert.sameValue(resultHours.epochNanoseconds, 999_911_555_595_557_201n, "negative fractional hours"); + +const resultMinutes = instance.add("-PT1440.567890123M"); +assert.sameValue(resultMinutes.epochNanoseconds, 999_913_565_926_592_621n, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string.js new file mode 100644 index 000000000000..dd93884f289e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/argument-string.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: A string is parsed into the correct object when passed as the argument +features: [Temporal] +---*/ + +const instance = Temporal.Instant.fromEpochSeconds(10); +const result = instance.add("PT3H"); +assert.sameValue(result.epochNanoseconds, 10_810_000_000_000n, "epochNanoseconds result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/basic.js new file mode 100644 index 000000000000..e4727e6294bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/basic.js @@ -0,0 +1,75 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: Basic functionality of Temporal.Instant.prototype.add() +info: | + 1. Let instant be the this value. + 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). + 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »). + 4. Let ns be ? AddInstant(instant.[[EpochNanoseconds]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]). + 5. Return ! CreateTemporalInstant(ns). +features: [Temporal] +---*/ + +const inst = new Temporal.Instant(50000n); + +let result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 3, 2, 1)); +assert.sameValue( + 3052001n, + result.epochNanoseconds, + "add positive sub-seconds" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 1)); +assert.sameValue( + BigInt(4 * 1e9) + 3052001n, + result.epochNanoseconds, + "add positive seconds" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 5, 4, 3, 2, 1)); +assert.sameValue( + BigInt(5 * 60 + 4) * 1000000000n + 3052001n, + result.epochNanoseconds, + "add positive minutes" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 6, 5, 4, 3, 2, 1)); +assert.sameValue( + BigInt(6 * 3600 + 5 * 60 + 4) * 1000000000n + 3052001n, + result.epochNanoseconds, + "add positive hours" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -3, -2, -1)); +assert.sameValue( + -2952001n, + result.epochNanoseconds, + "add negative sub-seconds" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -1)); +assert.sameValue( + BigInt(-4 * 1e9) - 2952001n, + result.epochNanoseconds, + "add negative seconds" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, -5, -4, -3, -2, -1)); +assert.sameValue( + BigInt(5 * 60 + 4) * -1000000000n - 2952001n, + result.epochNanoseconds, + "add negative minutes" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, -6, -5, -4, -3, -2, -1)); +assert.sameValue( + BigInt(6 * 3600 + 5 * 60 + 4) * -1000000000n - 2952001n, + result.epochNanoseconds, + "add negative hours" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/branding.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/branding.js index d973b9672c5b..aff886ee6ac0 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/branding.js @@ -12,14 +12,16 @@ const add = Temporal.Instant.prototype.add; assert.sameValue(typeof add, "function"); -assert.throws(TypeError, () => add.call(undefined), "undefined"); -assert.throws(TypeError, () => add.call(null), "null"); -assert.throws(TypeError, () => add.call(true), "true"); -assert.throws(TypeError, () => add.call(""), "empty string"); -assert.throws(TypeError, () => add.call(Symbol()), "symbol"); -assert.throws(TypeError, () => add.call(1), "1"); -assert.throws(TypeError, () => add.call({}), "plain object"); -assert.throws(TypeError, () => add.call(Temporal.Instant), "Temporal.Instant"); -assert.throws(TypeError, () => add.call(Temporal.Instant.prototype), "Temporal.Instant.prototype"); +const arg = new Temporal.Duration(0, 0, 0, 0, 5); + +assert.throws(TypeError, () => add.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => add.call(null, arg), "null"); +assert.throws(TypeError, () => add.call(true, arg), "true"); +assert.throws(TypeError, () => add.call("", arg), "empty string"); +assert.throws(TypeError, () => add.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => add.call(1, arg), "1"); +assert.throws(TypeError, () => add.call({}, arg), "plain object"); +assert.throws(TypeError, () => add.call(Temporal.Instant, arg), "Temporal.Instant"); +assert.throws(TypeError, () => add.call(Temporal.Instant.prototype, arg), "Temporal.Instant.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/builtin.js new file mode 100644 index 000000000000..9367b2504757 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: > + Tests that Temporal.Instant.prototype.add + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.add), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.add), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.add), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.add.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/disallowed-duration-units.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/disallowed-duration-units.js new file mode 100644 index 000000000000..10328c0424b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/disallowed-duration-units.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: | + Temporal.Instant.prototype.add() throws RangeError when the duration has + non-zero years, months, weeks, or days. +info: | + 1. Let instant be the this value. + 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »). +features: [Temporal] +---*/ + +const inst = new Temporal.Instant(500000n); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(1)), + "should throw RangeError when the duration has non-zero years (positive)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 2)), + "should throw RangeError when the duration has non-zero months (positive)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 0, 3)), + "should throw RangeError when the duration has non-zero weeks (positive)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 0, 0, 4)), + "should throw RangeError when the duration has non-zero days (positive)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(-1)), + "should throw RangeError when the duration has non-zero years (negative)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, -2)), + "should throw RangeError when the duration has non-zero months (negative)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 0, -3)), + "should throw RangeError when the duration has non-zero weeks (negative)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 0, 0, -4)), + "should throw RangeError when the duration has non-zero days (negative)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..552291adab6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Instant.prototype.add throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.instant.prototype.add +features: [Temporal] +---*/ + +const fields = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.Instant.fromEpochSeconds(10); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: Infinity })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/length.js new file mode 100644 index 000000000000..a61450fcfdcf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: Temporal.Instant.prototype.add.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.add, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/name.js new file mode 100644 index 000000000000..88face7b9e42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: Temporal.Instant.prototype.add.name is "add". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.add, "name", { + value: "add", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..1a570ce111f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/negative-infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Instant.prototype.add throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.instant.prototype.add +features: [Temporal] +---*/ + +const fields = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.Instant.fromEpochSeconds(10); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: -Infinity })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..a2ca492a0ffb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(1_000_000_000_000_000_000n); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.add({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/not-a-constructor.js new file mode 100644 index 000000000000..65b83c518b78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: > + Temporal.Instant.prototype.add does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.add(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.add), false, + "isConstructor(Temporal.Instant.prototype.add)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/order-of-operations.js new file mode 100644 index 000000000000..95eae059f535 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/order-of-operations.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: Properties on an object passed to add() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(10n); +const expected = [ + "get days", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get years", +]; +const actual = []; +const fields = { + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.add(argument); +assert.sameValue(result.epochNanoseconds, 3661001001011n, "epochNanoseconds result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/prop-desc.js new file mode 100644 index 000000000000..920582c60154 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: The "add" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.add, + "function", + "`typeof Instant.prototype.add` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "add", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/result-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/result-out-of-range.js new file mode 100644 index 000000000000..049a572f39d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/result-out-of-range.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: RangeError thrown if result is outside representable range +features: [Temporal] +---*/ + +const fields = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const latest = Temporal.Instant.fromEpochNanoseconds(8640000_000_000_000_000_000n); + +fields.forEach((field) => { + assert.throws( + RangeError, + () => latest.add({ [field]: 1 }), + `adding ${field} with result out of range (positive)` + ); +}); + +const earliest = Temporal.Instant.fromEpochNanoseconds(-8640000_000_000_000_000_000n); + +fields.forEach((field) => { + assert.throws( + RangeError, + () => earliest.add({ [field]: -1 }), + `adding ${field} with result out of range (negative)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/subclassing-ignored.js new file mode 100644 index 000000000000..e388de16e3ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/add/subclassing-ignored.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: Objects of a subclass are never created as return values for add() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Instant, + [10n], + "add", + [{ nanoseconds: 5 }], + (result) => { + assert.sameValue(result.epochNanoseconds, 15n, "epochNanoseconds result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/builtin.js new file mode 100644 index 000000000000..b583174852a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/builtin.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-instant-objects +description: Temporal.Instant.prototype meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +const { Instant } = Temporal; + +assert.sameValue(Object.isExtensible(Instant.prototype), true, + "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Instant.prototype), + "[object Temporal.Instant]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Instant.prototype), Object.prototype, + "Built-in prototype objects must have Object.prototype as their prototype."); + +assert.sameValue(Instant.prototype.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMicroseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMicroseconds/basic.js new file mode 100644 index 000000000000..7cd11c596ee7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMicroseconds/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.instant.prototype.epochmicroseconds +description: Basic tests for epochMicroseconds. +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.Instant(217175010_123_456_789n); +assert.sameValue(afterEpoch.epochMicroseconds, 217175010_123_456n, "epochMicroseconds post epoch"); +assert.sameValue(typeof afterEpoch.epochMicroseconds, "bigint", "epochMicroseconds value is a bigint"); + +const beforeEpoch = new Temporal.Instant(-217175010_876_543_211n); +assert.sameValue(beforeEpoch.epochMicroseconds, -217175010_876_543n, "epochMicroseconds pre epoch"); +assert.sameValue(typeof beforeEpoch.epochMicroseconds, "bigint", "epochMicroseconds value is a bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMicroseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMicroseconds/prop-desc.js new file mode 100644 index 000000000000..dc6d8894949f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMicroseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.instant.prototype.epochmicroseconds +description: The "epochMicroseconds" property of Temporal.Instant.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Instant.prototype, "epochMicroseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMilliseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMilliseconds/basic.js new file mode 100644 index 000000000000..4fc2d7e5935e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMilliseconds/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.instant.prototype.epochmilliseconds +description: Basic tests for epochMilliseconds. +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.Instant(217175010_123_456_789n); +assert.sameValue(afterEpoch.epochMilliseconds, 217175010_123, "epochMilliseconds post epoch"); +assert.sameValue(typeof afterEpoch.epochMilliseconds, "number", "epochMilliseconds value is a number"); + +const beforeEpoch = new Temporal.Instant(-217175010_876_543_211n); +assert.sameValue(beforeEpoch.epochMilliseconds, -217175010_876, "epochMilliseconds pre epoch"); +assert.sameValue(typeof beforeEpoch.epochMilliseconds, "number", "epochMilliseconds value is a number"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMilliseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMilliseconds/prop-desc.js new file mode 100644 index 000000000000..e95e6b63e7e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochMilliseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.instant.prototype.epochmilliseconds +description: The "epochMilliseconds" property of Temporal.Instant.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Instant.prototype, "epochMilliseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochNanoseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochNanoseconds/basic.js new file mode 100644 index 000000000000..043b41ad3b14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochNanoseconds/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.instant.prototype.epochnanoseconds +description: Basic tests for epochNanoseconds. +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.Instant(217175010_123_456_789n); +assert.sameValue(afterEpoch.epochNanoseconds, 217175010_123_456_789n, "epochNanoseconds post epoch"); +assert.sameValue(typeof afterEpoch.epochNanoseconds, "bigint", "epochNanoseconds value is a bigint"); + +const beforeEpoch = new Temporal.Instant(-217175010_876_543_211n); +assert.sameValue(beforeEpoch.epochNanoseconds, -217175010_876_543_211n, "epochNanoseconds pre epoch"); +assert.sameValue(typeof beforeEpoch.epochNanoseconds, "bigint", "epochNanoseconds value is a bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochNanoseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochNanoseconds/prop-desc.js new file mode 100644 index 000000000000..4eadf260dd1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochNanoseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.instant.prototype.epochnanoseconds +description: The "epochNanoseconds" property of Temporal.Instant.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Instant.prototype, "epochNanoseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochSeconds/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochSeconds/basic.js new file mode 100644 index 000000000000..5b828e4efcfa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochSeconds/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.instant.prototype.epochseconds +description: Basic tests for epochSeconds. +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.Instant(217175010_123_456_789n); +assert.sameValue(afterEpoch.epochSeconds, 217175010, "epochSeconds post epoch"); +assert.sameValue(typeof afterEpoch.epochSeconds, "number", "epochSeconds value is a number"); + +const beforeEpoch = new Temporal.Instant(-217175010_876_543_211n); +assert.sameValue(beforeEpoch.epochSeconds, -217175010, "epochSeconds pre epoch"); +assert.sameValue(typeof beforeEpoch.epochSeconds, "number", "epochSeconds value is a number"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochSeconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochSeconds/prop-desc.js new file mode 100644 index 000000000000..4d9fa007c42a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/epochSeconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.instant.prototype.epochseconds +description: The "epochSeconds" property of Temporal.Instant.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Instant.prototype, "epochSeconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/argument-wrong-type.js new file mode 100644 index 000000000000..a5d45237095d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/argument-wrong-type.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: Appropriate error thrown when argument cannot be converted to a valid string +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.Instant.fromEpochSeconds(0); + +assert.throws(RangeError, () => instance.equals(undefined), "undefined"); +assert.throws(RangeError, () => instance.equals(null), "null"); +assert.throws(RangeError, () => instance.equals(true), "true"); +assert.throws(RangeError, () => instance.equals(""), "empty string"); +assert.throws(TypeError, () => instance.equals(Symbol()), "symbol"); +assert.throws(RangeError, () => instance.equals(1), "1"); +assert.throws(RangeError, () => instance.equals({}), "plain object"); +assert.throws(RangeError, () => instance.equals(Temporal.Instant), "Temporal.Instant"); +assert.throws(TypeError, () => instance.equals(Temporal.Instant.prototype), "Temporal.Instant.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/argument-zoneddatetime.js new file mode 100644 index 000000000000..f08c3e43fbce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/argument-zoneddatetime.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.instant.prototype.until step 3: + 3. Set _other_ to ? ToTemporalInstant(_other_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert(instant.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/builtin.js new file mode 100644 index 000000000000..ce4488e6cbd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: > + Tests that Temporal.Instant.prototype.equals + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.equals), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.equals), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.equals), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.equals.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/instant-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/instant-string-multiple-offsets.js new file mode 100644 index 000000000000..9602dc008f78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/instant-string-multiple-offsets.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: Instant strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = instance.equals(str); +assert.sameValue(result, true, "UTC offset determined from offset part of string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/instant-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/instant-string.js new file mode 100644 index 000000000000..4e6adadb30ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/instant-string.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: Conversion of ISO date-time strings to Temporal.Instant instances +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.equals(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => instance.equals(str), "date-time + IANA annotation is not an instant"); + +str = "1970-01-01T00:00Z"; +const result1 = instance.equals(str); +assert.sameValue(result1, true, "date-time + Z preserves exact time"); + +str = "1970-01-01T00:00+01:00"; +const result2 = instance.equals(str); +assert.sameValue(result2, false, "date-time + offset preserves exact time with offset"); + +str = "1970-01-01T00:00Z[Etc/Ignored]"; +const result3 = instance.equals(str); +assert.sameValue(result3, true, "date-time + Z + IANA annotation ignores the IANA annotation"); + +str = "1970-01-01T00:00+01:00[Etc/Ignored]"; +const result4 = instance.equals(str); +assert.sameValue(result4, false, "date-time + offset + IANA annotation ignores the IANA annotation"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/length.js new file mode 100644 index 000000000000..abb3e90addb1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: Temporal.Instant.prototype.equals.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.equals, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/name.js new file mode 100644 index 000000000000..6dfd908029ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: Temporal.Instant.prototype.equals.name is "equals". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.equals, "name", { + value: "equals", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/not-a-constructor.js new file mode 100644 index 000000000000..e976f8c9e707 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: > + Temporal.Instant.prototype.equals does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.equals(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.equals), false, + "isConstructor(Temporal.Instant.prototype.equals)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/prop-desc.js new file mode 100644 index 000000000000..9eea39edf7d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: The "equals" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.equals, + "function", + "`typeof Instant.prototype.equals` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "equals", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/year-zero.js new file mode 100644 index 000000000000..fa94136a64cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/equals/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.equals +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "-000000-03-30T00:45Z", + "-000000-03-30T01:45+01:00", + "-000000-03-30T01:45:00+01:00[UTC]" +]; +const instance = new Temporal.Instant(0n); +invalidStrings.forEach((str) => { + assert.throws( + RangeError, + () => instance.equals(str), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/prop-desc.js new file mode 100644 index 000000000000..b5caa79003ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-instant-prototype +description: The "prototype" property of Temporal.Instant +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Instant.prototype, "object"); +assert.notSameValue(Temporal.Instant.prototype, null); + +verifyProperty(Temporal.Instant, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/builtin.js new file mode 100644 index 000000000000..1ed3ba9780dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: > + Tests that Temporal.Instant.prototype.round + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.round), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.round), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.round), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.round.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/length.js new file mode 100644 index 000000000000..47b2ebeb30db --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Temporal.Instant.prototype.round.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.round, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/name.js new file mode 100644 index 000000000000..cc1942243045 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Temporal.Instant.prototype.round.name is "round". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.round, "name", { + value: "round", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/not-a-constructor.js new file mode 100644 index 000000000000..de8dbc8157a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: > + Temporal.Instant.prototype.round does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.round(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.round), false, + "isConstructor(Temporal.Instant.prototype.round)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/options-wrong-type.js new file mode 100644 index 000000000000..4c334fe9a1ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/options-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: TypeError thrown when options argument is missing or a primitive +features: [Symbol, Temporal] +---*/ + +const values = [ + undefined, + null, + true, + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.Instant(0n); +assert.throws(TypeError, () => instance.round(), "missing argument"); +for (const value of values) { + assert.throws(TypeError, () => instance.round(value), `argument ${String(value)}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/prop-desc.js new file mode 100644 index 000000000000..9e1a348fec70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: The "round" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.round, + "function", + "`typeof Instant.prototype.round` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "round", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-nan.js new file mode 100644 index 000000000000..a1b7ec0c6380 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-nan.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.round step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *true*). +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_654_321n); +assert.throws(RangeError, () => instant.round({ smallestUnit: 'second', roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-non-integer.js new file mode 100644 index 000000000000..4c03d1169f9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_000_000_005n); +const result = instant.round({ smallestUnit: "nanosecond", roundingIncrement: 2.5 }); +assert.sameValue(result.epochNanoseconds, 1_000_000_000_000_000_006n, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..29fae7d3cc24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_000_000_005n); +assert.throws(RangeError, () => instant.round({ smallestUnit: "nanoseconds", roundingIncrement: -Infinity })); +assert.throws(RangeError, () => instant.round({ smallestUnit: "nanoseconds", roundingIncrement: -1 })); +assert.throws(RangeError, () => instant.round({ smallestUnit: "nanoseconds", roundingIncrement: 0 })); +assert.throws(RangeError, () => instant.round({ smallestUnit: "nanoseconds", roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-undefined.js new file mode 100644 index 000000000000..a272147e4aee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.round step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *true*). +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + +const explicit = instant.round({ smallestUnit: 'second', roundingIncrement: undefined }); +assert.sameValue(explicit.epochNanoseconds, 1_000_000_001_000_000_000n, "default roundingIncrement is 1"); + +const implicit = instant.round({ smallestUnit: 'second' }); +assert.sameValue(implicit.epochNanoseconds, 1_000_000_001_000_000_000n, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..ecab863cb953 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingincrement-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.round step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => instant.round({ smallestUnit: 'second', roundingIncrement }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_001_000_000_000n, descr), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_000_000_000n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-invalid-string.js new file mode 100644 index 000000000000..c2e44664ddd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => instant.round({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-undefined.js new file mode 100644 index 000000000000..d0a464752bdf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Fallback value for roundingMode option +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); + +const explicit1 = instant.round({ smallestUnit: "microsecond", roundingMode: undefined }); +assert.sameValue(explicit1.epochNanoseconds, 1_000_000_000_123_988_000n, "default roundingMode is halfExpand"); +const implicit1 = instant.round({ smallestUnit: "microsecond" }); +assert.sameValue(implicit1.epochNanoseconds, 1_000_000_000_123_988_000n, "default roundingMode is halfExpand"); + +const explicit2 = instant.round({ smallestUnit: "millisecond", roundingMode: undefined }); +assert.sameValue(explicit2.epochNanoseconds, 1_000_000_000_124_000_000n, "default roundingMode is halfExpand"); +const implicit2 = instant.round({ smallestUnit: "millisecond" }); +assert.sameValue(implicit2.epochNanoseconds, 1_000_000_000_124_000_000n, "default roundingMode is halfExpand"); + +const explicit3 = instant.round({ smallestUnit: "second", roundingMode: undefined }); +assert.sameValue(explicit3.epochNanoseconds, 1_000_000_000_000_000_000n, "default roundingMode is halfExpand"); +const implicit3 = instant.round({ smallestUnit: "second" }); +assert.sameValue(implicit3.epochNanoseconds, 1_000_000_000_000_000_000n, "default roundingMode is halfExpand"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-wrong-type.js new file mode 100644 index 000000000000..095a6351f056 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand", + (roundingMode) => instant.round({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_123_988_000n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-disallowed-units.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-disallowed-units.js new file mode 100644 index 000000000000..8167be007d6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-disallowed-units.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Specifically disallowed units for the smallestUnit option +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Instant(1_000_000_000_987_654_321n); +const invalidUnits = [ + "era", + "eras", + "year", + "month", + "week", + "years", + "months", + "weeks", + "day", + "days", +]; +invalidUnits.forEach((smallestUnit) => { + assert.throws( + RangeError, + () => instance.round({ smallestUnit }), + `{ smallestUnit: "${smallestUnit}" } should not be allowed as an argument to round` + ); + assert.throws( + RangeError, + () => instance.round(smallestUnit), + `"${smallestUnit}" should not be allowed as an argument to round` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-invalid-string.js new file mode 100644 index 000000000000..2da339c56d64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-invalid-string.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); +assert.throws(RangeError, () => instant.round({ smallestUnit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..a2e1363281fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_654_321n); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => instant.round({ smallestUnit }), validUnits); +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => instant.round(smallestUnit), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-string-shorthand.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-string-shorthand.js new file mode 100644 index 000000000000..93b77ef70b07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-string-shorthand.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: String as first argument is equivalent to options bag with smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.Instant(1_000_000_000_987_654_321n); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +validUnits.forEach((smallestUnit) => { + const full = instance.round({ smallestUnit }); + const shorthand = instance.round(smallestUnit); + TemporalHelpers.assertInstantsEqual(shorthand, full, `"${smallestUnit}" as first argument to round is equivalent to options bag`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-wrong-type.js new file mode 100644 index 000000000000..cecfd6ef1a68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => instant.round({ smallestUnit }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_123_988_000n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/subclassing-ignored.js new file mode 100644 index 000000000000..ab18439e09f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/round/subclassing-ignored.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Instant, + [10n], + "round", + [{ smallestUnit: 'second', roundingMode: 'ceil' }], + (result) => { + assert.sameValue(result.epochNanoseconds, 1_000_000_000n, "epochNanoseconds result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/argument-zoneddatetime.js new file mode 100644 index 000000000000..5bc5e911dd82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/argument-zoneddatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.instant.prototype.since step 3: + 3. Set _other_ to ? ToTemporalInstant(_other_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const instant = new Temporal.Instant(1_000_000_000_000_000_000n); + const result = instant.since(datetime); + assert.sameValue(result.total({ unit: "nanoseconds" }), -987654321, "nanoseconds result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/builtin.js new file mode 100644 index 000000000000..125c0e05f57c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: > + Tests that Temporal.Instant.prototype.since + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.since), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.since), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.since), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.since.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/instant-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/instant-string-multiple-offsets.js new file mode 100644 index 000000000000..4b4736375d2c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/instant-string-multiple-offsets.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Instant strings with UTC offset fractional part are not confused with time fractional part +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = instance.since(str); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "UTC offset determined from offset part of string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/instant-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/instant-string.js new file mode 100644 index 000000000000..d50dac22a119 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/instant-string.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Conversion of ISO date-time strings to Temporal.Instant instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.since(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => instance.since(str), "date-time + IANA annotation is not an instant"); + +str = "1970-01-01T00:00Z"; +const result1 = instance.since(str); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z preserves exact time"); + +str = "1970-01-01T00:00+01:00"; +const result2 = instance.since(str); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 0, 0, 3600, 0, 0, 0, "date-time + offset preserves exact time with offset"); + +str = "1970-01-01T00:00Z[Etc/Ignored]"; +const result3 = instance.since(str); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation ignores the IANA annotation"); + +str = "1970-01-01T00:00+01:00[Etc/Ignored]"; +const result4 = instance.since(str); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 0, 0, 3600, 0, 0, 0, "date-time + offset + IANA annotation ignores the IANA annotation"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-invalid-string.js new file mode 100644 index 000000000000..1757cfeedbfc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..68ec837f9ebf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_086_403_661_988_655_322n); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => later.since(earlier, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..b8a902bd63a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +const units = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => later.since(earlier, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-undefined.js new file mode 100644 index 000000000000..8d1f220e9b90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); + +const explicit = later.since(earlier, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default largestUnit is second"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default largestUnit is second"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-wrong-type.js new file mode 100644 index 000000000000..8a44bb291d51 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "hour", + (largestUnit) => later.since(earlier, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit.js new file mode 100644 index 000000000000..d6580c58f290 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/largestunit.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Specify behavior of Instant.since when largest specified unit is specified +includes: [temporalHelpers.js] +features: [Temporal, BigInt] +---*/ +const thePast = new Temporal.Instant(1234567890123456789n); +const theFuture = new Temporal.Instant(2345678901234567890n); +TemporalHelpers.assertDuration(theFuture.since(thePast), 0, 0, 0, 0, 0, 0, 1111111011, 111, 111, 101, 'does not include higher units than necessary (largest unit unspecified)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'hours' }), 0, 0, 0, 0, 308641, 56, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit is hours)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'minutes' }), 0, 0, 0, 0, 0, 18518516, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit is minutes)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'seconds' }), 0, 0, 0, 0, 0, 0, 1111111011, 111, 111, 101, 'does not include higher units than necessary (largest unit is seconds)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'milliseconds' }), 0, 0, 0, 0, 0, 0, 0, 1111111011111, 111, 101, 'does not include higher units than necessary (largest unit is milliseconds)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'microseconds' }), 0, 0, 0, 0, 0, 0, 0, 0, 1111111011111111, 101, 'does not include higher units than necessary (largest unit is microseconds)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'nanoseconds' }), 0, 0, 0, 0, 0, 0, 0, 0, 0, 1111111011111111000, 'does not include higher units than necessary (largest unit is nanoseconds)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/length.js new file mode 100644 index 000000000000..2fc319bbcb70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Temporal.Instant.prototype.since.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.since, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/name.js new file mode 100644 index 000000000000..f9c6ac87cf71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Temporal.Instant.prototype.since.name is "since". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.since, "name", { + value: "since", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/not-a-constructor.js new file mode 100644 index 000000000000..690fa5c4228c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: > + Temporal.Instant.prototype.since does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.since(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.since), false, + "isConstructor(Temporal.Instant.prototype.since)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/options-undefined.js new file mode 100644 index 000000000000..ea8befc48218 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/options-undefined.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const earlier = new Temporal.Instant(957270896_987_654_321n); +const later = new Temporal.Instant(959949296_987_654_322n); + +const explicit = later.since(earlier, undefined); +assert.sameValue(explicit.years, 0, "default largest unit is seconds"); +assert.sameValue(explicit.months, 0, "default largest unit is seconds"); +assert.sameValue(explicit.weeks, 0, "default largest unit is seconds"); +assert.sameValue(explicit.days, 0, "default largest unit is seconds"); +assert.sameValue(explicit.hours, 0, "default largest unit is seconds"); +assert.sameValue(explicit.minutes, 0, "default largest unit is seconds"); +assert.sameValue(explicit.seconds, 2678400, "default largest unit is seconds"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = later.since(earlier); +assert.sameValue(implicit.years, 0, "default largest unit is seconds"); +assert.sameValue(implicit.months, 0, "default largest unit is seconds"); +assert.sameValue(implicit.weeks, 0, "default largest unit is seconds"); +assert.sameValue(implicit.days, 0, "default largest unit is seconds"); +assert.sameValue(implicit.hours, 0, "default largest unit is seconds"); +assert.sameValue(implicit.minutes, 0, "default largest unit is seconds"); +assert.sameValue(implicit.seconds, 2678400, "default largest unit is seconds"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/prop-desc.js new file mode 100644 index 000000000000..9d5fec965e8a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: The "since" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.since, + "function", + "`typeof Instant.prototype.since` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "since", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-nan.js new file mode 100644 index 000000000000..18de9f52286d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_000_090_061_988_655_322n); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-non-integer.js new file mode 100644 index 000000000000..ff9ea655ff6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_000_000_000_000_005n); +const result = later.since(earlier, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..63586cbf4065 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_000_000_000_000_005n); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -1 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 0 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-undefined.js new file mode 100644 index 000000000000..03164b071cdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_000_090_061_988_655_322n); + +const explicit = later.since(earlier, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..25221df428be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_000_090_061_988_655_322n); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => later.since(earlier, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-invalid-string.js new file mode 100644 index 000000000000..b36d4d334ad2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_123_987_500n); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-undefined.js new file mode 100644 index 000000000000..35b4f910e54b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_123_987_500n); + +const explicit1 = later.since(earlier, { smallestUnit: "microsecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, "default roundingMode is trunc"); +const implicit1 = later.since(earlier, { smallestUnit: "microsecond" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, "default roundingMode is trunc"); + +const explicit2 = later.since(earlier, { smallestUnit: "millisecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 0, 0, 90061, 123, 0, 0, "default roundingMode is trunc"); +const implicit2 = later.since(earlier, { smallestUnit: "millisecond" }); +TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 0, 0, 90061, 123, 0, 0, "default roundingMode is trunc"); + +const explicit3 = later.since(earlier, { smallestUnit: "second", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 0, 0, 90061, 0, 0, 0, "default roundingMode is trunc"); +const implicit3 = later.since(earlier, { smallestUnit: "second" }); +TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 0, 0, 90061, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-wrong-type.js new file mode 100644 index 000000000000..9de9efb94f44 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_123_987_500n); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-invalid-string.js new file mode 100644 index 000000000000..6f8e163bf989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..db9603a621f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_086_403_661_988_655_322n); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => later.since(earlier, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-undefined.js new file mode 100644 index 000000000000..d1b4322497cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); + +const explicit = later.since(earlier, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-wrong-type.js new file mode 100644 index 000000000000..f871561bb223 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => later.since(earlier, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/year-zero.js new file mode 100644 index 000000000000..8a19b0310fdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/since/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.since +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "-000000-03-30T00:45Z", + "-000000-03-30T01:45+01:00", + "-000000-03-30T01:45:00+01:00[UTC]" +]; +const instance = new Temporal.Instant(0n); +invalidStrings.forEach((str) => { + assert.throws( + RangeError, + () => instance.since(str), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..206b2297bc1f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: Strings with fractional duration units are rounded with the correct rounding mode +features: [Temporal] +---*/ + +const epoch = new Temporal.Instant(0n); + +assert.sameValue(epoch.subtract("PT1.03125H").epochNanoseconds, -3712_500_000_000n, + "positive fractional units rounded with correct rounding mode"); +assert.sameValue(epoch.subtract("-PT1.03125H").epochNanoseconds, 3712_500_000_000n, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..c28f85b9ac0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string-negative-fractional-units.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: Strings with fractional duration units are treated with the correct sign +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(1_000_000_000_000_000_000n); + +const resultHours = instance.subtract("-PT24.567890123H"); +assert.sameValue(resultHours.epochNanoseconds, 1_000_088_444_404_442_799n, "negative fractional hours"); + +const resultMinutes = instance.subtract("-PT1440.567890123M"); +assert.sameValue(resultMinutes.epochNanoseconds, 1_000_086_434_073_407_379n, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string.js new file mode 100644 index 000000000000..b059c12c0889 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/argument-string.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: A string is parsed into the correct object when passed as the argument +features: [Temporal] +---*/ + +const instance = Temporal.Instant.fromEpochSeconds(10); +const result = instance.subtract("PT3H"); +assert.sameValue(result.epochNanoseconds, -10_790_000_000_000n, "epochNanoseconds result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/basic.js new file mode 100644 index 000000000000..6736ca43a362 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/basic.js @@ -0,0 +1,75 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: Basic functionality of Temporal.Instant.prototype.subtract() +info: | + 1. Let instant be the this value. + 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). + 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »). + 4. Let ns be ? AddInstant(instant.[[EpochNanoseconds]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]). + 5. Return ! CreateTemporalInstant(ns). +features: [Temporal] +---*/ + +const inst = new Temporal.Instant(50000n); + +let result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 3, 2, 1)); +assert.sameValue( + -2952001n, + result.epochNanoseconds, + "subtract positive sub-seconds" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 1)); +assert.sameValue( + BigInt(-4 * 1e9) - 2952001n, + result.epochNanoseconds, + "subtract positive seconds" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 5, 4, 3, 2, 1)); +assert.sameValue( + BigInt(5 * 60 + 4) * -1000000000n - 2952001n, + result.epochNanoseconds, + "subtract positive minutes" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 6, 5, 4, 3, 2, 1)); +assert.sameValue( + BigInt(6 * 3600 + 5 * 60 + 4) * -1000000000n - 2952001n, + result.epochNanoseconds, + "subtract positive hours" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -3, -2, -1)); +assert.sameValue( + 3052001n, + result.epochNanoseconds, + "subtract negative sub-seconds" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -1)); +assert.sameValue( + BigInt(4 * 1e9) + 3052001n, + result.epochNanoseconds, + "subtract negative seconds" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, -5, -4, -3, -2, -1)); +assert.sameValue( + BigInt(5 * 60 + 4) * 1000000000n + 3052001n, + result.epochNanoseconds, + "subtract negative minutes" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, -6, -5, -4, -3, -2, -1)); +assert.sameValue( + BigInt(6 * 3600 + 5 * 60 + 4) * 1000000000n + 3052001n, + result.epochNanoseconds, + "subtract negative hours" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/branding.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/branding.js index de44412321c1..1805b9a9b4ff 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/branding.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/branding.js @@ -12,14 +12,16 @@ const subtract = Temporal.Instant.prototype.subtract; assert.sameValue(typeof subtract, "function"); -assert.throws(TypeError, () => subtract.call(undefined), "undefined"); -assert.throws(TypeError, () => subtract.call(null), "null"); -assert.throws(TypeError, () => subtract.call(true), "true"); -assert.throws(TypeError, () => subtract.call(""), "empty string"); -assert.throws(TypeError, () => subtract.call(Symbol()), "symbol"); -assert.throws(TypeError, () => subtract.call(1), "1"); -assert.throws(TypeError, () => subtract.call({}), "plain object"); -assert.throws(TypeError, () => subtract.call(Temporal.Instant), "Temporal.Instant"); -assert.throws(TypeError, () => subtract.call(Temporal.Instant.prototype), "Temporal.Instant.prototype"); +const arg = new Temporal.Duration(0, 0, 0, 0, 5); + +assert.throws(TypeError, () => subtract.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => subtract.call(null, arg), "null"); +assert.throws(TypeError, () => subtract.call(true, arg), "true"); +assert.throws(TypeError, () => subtract.call("", arg), "empty string"); +assert.throws(TypeError, () => subtract.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => subtract.call(1, arg), "1"); +assert.throws(TypeError, () => subtract.call({}, arg), "plain object"); +assert.throws(TypeError, () => subtract.call(Temporal.Instant, arg), "Temporal.Instant"); +assert.throws(TypeError, () => subtract.call(Temporal.Instant.prototype, arg), "Temporal.Instant.prototype"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/builtin.js new file mode 100644 index 000000000000..61e91aa19319 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: > + Tests that Temporal.Instant.prototype.subtract + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.subtract), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.subtract), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.subtract), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.subtract.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/disallowed-duration-units.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/disallowed-duration-units.js new file mode 100644 index 000000000000..24084784dfb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/disallowed-duration-units.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: | + Temporal.Instant.prototype.subtract() throws RangeError when the duration has + non-zero years, months, weeks or days. +info: | + 1. Let instant be the this value. + 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »). +features: [Temporal] +---*/ + +let i1 = new Temporal.Instant(500000n); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(1)), + "should throw RangeError when the duration has non-zero years (positive)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 2)), + "should throw RangeError when the duration has non-zero months (positive)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 0, 3)), + "should throw RangeError when the duration has non-zero weeks (positive)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 0, 0, 4)), + "should throw RangeError when the duration has non-zero days (positive)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(-1)), + "should throw RangeError when the duration has non-zero years (negative)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, -2)), + "should throw RangeError when the duration has non-zero months (negative)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 0, -3)), + "should throw RangeError when the duration has non-zero weeks (negative)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 0, 0, -4)), + "should throw RangeError when the duration has non-zero days (negative)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..84b18e4accbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Instant.prototype.subtract throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.instant.prototype.subtract +features: [Temporal] +---*/ + +const fields = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.Instant.fromEpochSeconds(10); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: Infinity })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/length.js new file mode 100644 index 000000000000..793e4c9d4702 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: Temporal.Instant.prototype.subtract.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.subtract, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/name.js new file mode 100644 index 000000000000..f9609ea1361a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: Temporal.Instant.prototype.subtract.name is "subtract". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.subtract, "name", { + value: "subtract", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..4a854ea44d16 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/negative-infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.Instant.prototype.subtract throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.instant.prototype.subtract +features: [Temporal] +---*/ + +const fields = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.Instant.fromEpochSeconds(10); + +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity })); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..99970d8574b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(1_000_000_000_000_000_000n); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.subtract({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/not-a-constructor.js new file mode 100644 index 000000000000..83f277119e84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: > + Temporal.Instant.prototype.subtract does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.subtract(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.subtract), false, + "isConstructor(Temporal.Instant.prototype.subtract)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/order-of-operations.js new file mode 100644 index 000000000000..864707430a09 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/order-of-operations.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: Properties on an object passed to subtract() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(10n); +const expected = [ + "get days", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get years", +]; +const actual = []; +const fields = { + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.subtract(argument); +assert.sameValue(result.epochNanoseconds, -3661001000991n, "epochNanoseconds result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/prop-desc.js new file mode 100644 index 000000000000..6205779c684d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: The "subtract" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.subtract, + "function", + "`typeof Instant.prototype.subtract` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "subtract", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/result-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/result-out-of-range.js new file mode 100644 index 000000000000..3dafb18205e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/result-out-of-range.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: RangeError thrown if result is outside representable range +features: [Temporal] +---*/ + +const fields = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const earliest = Temporal.Instant.fromEpochNanoseconds(-8640000_000_000_000_000_000n); + +fields.forEach((field) => { + assert.throws( + RangeError, + () => earliest.subtract({ [field]: 1 }), + `subtracting ${field} with result out of range (negative)` + ); +}); + +const latest = Temporal.Instant.fromEpochNanoseconds(8640000_000_000_000_000_000n); + +fields.forEach((field) => { + assert.throws( + RangeError, + () => latest.subtract({ [field]: -1 }), + `subtracting ${field} with result out of range (positive)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/subclassing-ignored.js new file mode 100644 index 000000000000..46491b3f8029 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/subtract/subclassing-ignored.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: Objects of a subclass are never created as return values for subtract() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.Instant, + [10n], + "subtract", + [{ nanoseconds: 5 }], + (result) => { + assert.sameValue(result.epochNanoseconds, 5n, "epochNanoseconds result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/basic.js new file mode 100644 index 000000000000..c4d7db4548f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: Basic tests for toJSON() +features: [Temporal] +---*/ + +const instantBeforeEpoch = Temporal.Instant.from("1963-02-13T10:36:29.123456789+01:00"); +assert.sameValue(instantBeforeEpoch.toJSON(), "1963-02-13T09:36:29.123456789Z"); + +const instantAfterEpoch = Temporal.Instant.from("1976-11-18T15:23:30.123456789+01:00"); +assert.sameValue(instantAfterEpoch.toJSON(), "1976-11-18T14:23:30.123456789Z"); +assert.sameValue(instantAfterEpoch.toJSON("+01:00"), "1976-11-18T14:23:30.123456789Z", + "after epoch with ignored argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..e6871c6ed786 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: > + Tests that Temporal.Instant.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/length.js new file mode 100644 index 000000000000..82a5f5e012c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: Temporal.Instant.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/name.js new file mode 100644 index 000000000000..17640052f0fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: Temporal.Instant.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/negative-epochnanoseconds.js new file mode 100644 index 000000000000..a3642afe5cff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/negative-epochnanoseconds.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.Instant(-13849764_999_999_999n); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.toJSON(); +assert.sameValue(result, "1969-07-24T16:50:35.000000001Z"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..13acce20734b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: > + Temporal.Instant.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.toJSON), false, + "isConstructor(Temporal.Instant.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..d10ab1d03da1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: The "toJSON" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.toJSON, + "function", + "`typeof Instant.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..4dd2d4a04150 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +const instance = new Temporal.Instant(1_000_000_000_987_654_321n); + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => instance.toJSON(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/year-format.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/year-format.js new file mode 100644 index 000000000000..4d5de3dbca88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toJSON/year-format.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +function epochNsInYear(year) { + // Return an epoch nanoseconds value near the middle of the given year + const avgNsPerYear = 31_556_952_000_000_000n; + return (year - 1970n) * avgNsPerYear + (avgNsPerYear / 2n); +} + +let instance = new Temporal.Instant(epochNsInYear(-100000n)); +assert.sameValue(instance.toJSON(), "-100000-07-01T21:30:36Z", "large negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-10000n)); +assert.sameValue(instance.toJSON(), "-010000-07-01T21:30:36Z", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-9999n)); +assert.sameValue(instance.toJSON(), "-009999-07-02T03:19:48Z", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-1000n)); +assert.sameValue(instance.toJSON(), "-001000-07-02T09:30:36Z", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-999n)); +assert.sameValue(instance.toJSON(), "-000999-07-02T15:19:48Z", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-1n)); +assert.sameValue(instance.toJSON(), "-000001-07-02T15:41:24Z", "year -1 formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(0n)); +assert.sameValue(instance.toJSON(), "0000-07-01T21:30:36Z", "year 0 formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(1n)); +assert.sameValue(instance.toJSON(), "0001-07-02T03:19:48Z", "year 1 formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(999n)); +assert.sameValue(instance.toJSON(), "0999-07-02T03:41:24Z", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(1000n)); +assert.sameValue(instance.toJSON(), "1000-07-02T09:30:36Z", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(9999n)); +assert.sameValue(instance.toJSON(), "9999-07-02T15:41:24Z", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(10000n)); +assert.sameValue(instance.toJSON(), "+010000-07-01T21:30:36Z", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(100000n)); +assert.sameValue(instance.toJSON(), "+100000-07-01T21:30:36Z", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/builtin.js new file mode 100644 index 000000000000..8a2851f1ddf3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: > + Tests that Temporal.Instant.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/length.js new file mode 100644 index 000000000000..663ee65ea1eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: Temporal.Instant.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/name.js new file mode 100644 index 000000000000..efd0cdea1665 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: Temporal.Instant.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 000000000000..78c53e3a5809 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: > + Temporal.Instant.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.toLocaleString), false, + "isConstructor(Temporal.Instant.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/prop-desc.js new file mode 100644 index 000000000000..88784085f8ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.toLocaleString, + "function", + "`typeof Instant.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/return-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/return-string.js new file mode 100644 index 000000000000..de171da4279c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/return-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: > + toLocaleString return a string. +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(957270896_987_650_000n); + +assert.sameValue(typeof instant.toLocaleString("en", { dateStyle: "short" }), "string"); +assert.sameValue(typeof instant.toLocaleString("en", { timeStyle: "short" }), "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/basic.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/basic.js new file mode 100644 index 000000000000..c56ae6fa9967 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/basic.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Basic tests for toString(). +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.Instant(217175010_123_456_789n); +assert.sameValue(afterEpoch.toString(), "1976-11-18T14:23:30.123456789Z", "basic toString() after epoch"); + +const beforeEpoch = new Temporal.Instant(-217175010_876_543_211n); +assert.sameValue(beforeEpoch.toString(), "1963-02-13T09:36:29.123456789Z", "basic toString() before epoch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/builtin.js new file mode 100644 index 000000000000..87c9840b724b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: > + Tests that Temporal.Instant.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-invalid-string.js new file mode 100644 index 000000000000..3e8962aa9cb0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-invalid-string.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values +info: | + sec-getstringornumberoption step 4: + 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.instant.prototype.tostring step 6: + 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_650_000n); + +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-nan.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-nan.js new file mode 100644 index 000000000000..f9dae69bc513 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-nan.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.instant.prototype.tostring step 6: + 6. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_650_000n); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-non-integer.js new file mode 100644 index 000000000000..ee0d110daedc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-non-integer.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Rounding for fractionalSecondDigits option +info: | + sec-getstringornumberoption step 3.b: + b. Return floor(ℝ(_value_)). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.instant.prototype.tostring step 6: + 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_650_000n); + +const string = instant.toString({ fractionalSecondDigits: 2.5 }); +assert.sameValue(string, "2001-09-09T01:46:40.98Z", "fractionalSecondDigits 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-out-of-range.js new file mode 100644 index 000000000000..84ed25e6a228 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-out-of-range.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option out of range +info: | + sec-getstringornumberoption step 3.a: + a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.instant.prototype.tostring step 6: + 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_650_000n); + +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: -1 })); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: 10 })); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: -Infinity })); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-undefined.js new file mode 100644 index 000000000000..387e0eb514e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Fallback value for fractionalSecondDigits option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.instant.prototype.tostring step 6: + 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_650_000n); + +const explicit = instant.toString({ fractionalSecondDigits: undefined }); +assert.sameValue(explicit, "2001-09-09T01:46:40.98765Z", "default fractionalSecondDigits is auto"); + +const implicit = instant.toString({}); +assert.sameValue(implicit, "2001-09-09T01:46:40.98765Z", "default fractionalSecondDigits is auto"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-wrong-type.js new file mode 100644 index 000000000000..7b952de46aa2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Type conversions for fractionalSecondDigits option +info: | + sec-getoption steps 8–9: + 8. Else if _type_ is Number, then + a. Set _value_ to ? ToNumber(value). + b. ... + 9. Else, + a. Set _value_ to ? ToString(value). + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.instant.prototype.tostring step 6: + 6. Let _precision_ be ? ToSecondsStringPrecision(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_987_650_000n); +TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(instant); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/length.js new file mode 100644 index 000000000000..5ed491c941e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Temporal.Instant.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/name.js new file mode 100644 index 000000000000..51e3291fcf01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Temporal.Instant.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/negative-epochnanoseconds.js new file mode 100644 index 000000000000..b588bb7da20a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/negative-epochnanoseconds.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.Instant(-13849764_999_999_999n); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.toString(); +assert.sameValue(result, "1969-07-24T16:50:35.000000001Z"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..b325aed41409 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: > + Temporal.Instant.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.toString), false, + "isConstructor(Temporal.Instant.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/options-undefined.js new file mode 100644 index 000000000000..9afe5a73f957 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/options-undefined.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +includes: [compareArray.js] +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const actual = []; +const expected = []; + +const instant = Temporal.Instant.from("1975-02-02T14:25:36.12345Z"); + +Object.defineProperty(Temporal.TimeZone, "from", { + get() { + actual.push("get Temporal.TimeZone.from"); + return function(identifier) { + actual.push("call Temporal.TimeZone.from"); + assert.sameValue(identifier, "UTC"); + }; + }, +}); + +assert.sameValue( + instant.toString(), + "1975-02-02T14:25:36.12345Z", + "default time zone is none, precision is auto, and rounding is trunc" +); +assert.compareArray(actual, expected); + +assert.sameValue( + instant.toString(undefined), + "1975-02-02T14:25:36.12345Z", + "default time zone is none, precision is auto, and rounding is trunc" +); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/precision.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/precision.js new file mode 100644 index 000000000000..5f999c4c2617 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/precision.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: toString() produces a fractional part of the correct length +features: [Temporal] +---*/ + +const { Instant } = Temporal; + +const isoString = '2020-01-01T23:58:57.012034Z'; +const instant = Instant.from(isoString); +const instantIsoStrMicros = instant.toString({ + smallestUnit: 'microseconds' +}); + +assert.sameValue(instantIsoStrMicros, isoString); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..a9b66b33f382 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: The "toString" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.toString, + "function", + "`typeof Instant.prototype.toString` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-invalid-string.js new file mode 100644 index 000000000000..00cd93819382 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => instant.toString({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-undefined.js new file mode 100644 index 000000000000..3ab988b16d7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Fallback value for roundingMode option +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); + +const explicit1 = instant.toString({ smallestUnit: "microsecond", roundingMode: undefined }); +assert.sameValue(explicit1, "2001-09-09T01:46:40.123987Z", "default roundingMode is trunc"); +const implicit1 = instant.toString({ smallestUnit: "microsecond" }); +assert.sameValue(implicit1, "2001-09-09T01:46:40.123987Z", "default roundingMode is trunc"); + +const explicit2 = instant.toString({ smallestUnit: "millisecond", roundingMode: undefined }); +assert.sameValue(explicit2, "2001-09-09T01:46:40.123Z", "default roundingMode is trunc"); +const implicit2 = instant.toString({ smallestUnit: "millisecond" }); +assert.sameValue(implicit2, "2001-09-09T01:46:40.123Z", "default roundingMode is trunc"); + +const explicit3 = instant.toString({ smallestUnit: "second", roundingMode: undefined }); +assert.sameValue(explicit3, "2001-09-09T01:46:40Z", "default roundingMode is trunc"); +const implicit3 = instant.toString({ smallestUnit: "second" }); +assert.sameValue(implicit3, "2001-09-09T01:46:40Z", "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-wrong-type.js new file mode 100644 index 000000000000..52c466f1ba26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => instant.toString({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.123987Z", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-invalid-string.js new file mode 100644 index 000000000000..7eb4723bf79a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-invalid-string.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); +assert.throws(RangeError, () => instant.toString({ smallestUnit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..70181d7529ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_456_789n); +const validUnits = [ + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => instant.toString({ smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-undefined.js new file mode 100644 index 000000000000..5e3a3ff8f9f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-undefined.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Fallback value for smallestUnit option +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); + +const explicit1 = instant.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 }); +assert.sameValue(explicit1, "2001-09-09T01:46:40.123987Z", "default smallestUnit defers to fractionalSecondDigits"); +const implicit1 = instant.toString({ fractionalSecondDigits: 6 }); +assert.sameValue(implicit1, "2001-09-09T01:46:40.123987Z", "default smallestUnit defers to fractionalSecondDigits"); + +const explicit2 = instant.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 }); +assert.sameValue(explicit2, "2001-09-09T01:46:40.123Z", "default smallestUnit defers to fractionalSecondDigits"); +const implicit2 = instant.toString({ fractionalSecondDigits: 3 }); +assert.sameValue(implicit2, "2001-09-09T01:46:40.123Z", "default smallestUnit defers to fractionalSecondDigits"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-valid-units.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-valid-units.js new file mode 100644 index 000000000000..ae5f02742229 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-valid-units.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Valid units for the smallestUnit option +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_456_789n); + +assert.sameValue(instant.toString({ smallestUnit: "minute" }), "2001-09-09T01:46Z"); +assert.sameValue(instant.toString({ smallestUnit: "second" }), "2001-09-09T01:46:40Z"); +assert.sameValue(instant.toString({ smallestUnit: "millisecond" }), "2001-09-09T01:46:40.123Z"); +assert.sameValue(instant.toString({ smallestUnit: "microsecond" }), "2001-09-09T01:46:40.123456Z"); +assert.sameValue(instant.toString({ smallestUnit: "nanosecond" }), "2001-09-09T01:46:40.123456789Z"); + +const notValid = [ + "era", + "year", + "month", + "week", + "day", + "hour", +]; + +notValid.forEach((smallestUnit) => { + assert.throws(RangeError, () => instant.toString({ smallestUnit }), smallestUnit); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-wrong-type.js new file mode 100644 index 000000000000..ee24478ed4ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => instant.toString({ smallestUnit }), + (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.123987Z", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..f3f5b67c09cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(RangeError, () => instant.toString({ timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..f8fc53979beb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => instant.toString({ timeZone }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..074c1b310367 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(RangeError, () => instant.toString({ timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..4c21413f5ba3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(TypeError, () => instant.toString({ timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-offset.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-offset.js new file mode 100644 index 000000000000..d8500ae1ece8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-offset.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: The time zone offset part of the string serialization +features: [BigInt, Temporal] +---*/ + +const instant = new Temporal.Instant(0n); + +function test(timeZoneIdentifier, expected, description) { + const timeZone = new Temporal.TimeZone(timeZoneIdentifier); + assert.sameValue(instant.toString({ timeZone }), expected, description); +} + +test("UTC", "1970-01-01T00:00:00+00:00", "offset of UTC is +00:00"); +test("+01:00", "1970-01-01T01:00:00+01:00", "positive offset"); +test("-05:00", "1969-12-31T19:00:00-05:00", "negative offset"); +test("+00:44:59.123456789", "1970-01-01T00:44:59.123456789+00:45", "sub-minute offset"); +test("-00:00:10.987654321", "1969-12-31T23:59:49.012345679+00:00", "sub-minute offset that rounds to zero"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-string-datetime.js new file mode 100644 index 000000000000..da07e6603ce6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-string-datetime.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.toString({ timeZone }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.toString({ timeZone: { timeZone } }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = instance.toString({ timeZone }); +assert.sameValue(result1.substr(-6), "+00:00", "date-time + Z is UTC time zone"); +const result2 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result2.substr(-6), "+00:00", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = instance.toString({ timeZone }); +assert.sameValue(result3.substr(-6), "-07:00", "date-time + offset is the offset time zone"); +const result4 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result4.substr(-6), "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = instance.toString({ timeZone }); +assert.sameValue(result5.substr(-6), "+00:00", "date-time + IANA annotation is the offset time zone"); +const result6 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result6.substr(-6), "+00:00", "date-time + IANA annotation is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = instance.toString({ timeZone }); +assert.sameValue(result7.substr(-6), "+00:00", "date-time + Z + IANA annotation is the offset time zone"); +const result8 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result8.substr(-6), "+00:00", "date-time + Z + IANA annotation is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = instance.toString({ timeZone }); +assert.sameValue(result9.substr(-6), "+00:00", "date-time + offset + IANA annotation is the offset time zone"); +const result10 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result10.substr(-6), "+00:00", "date-time + offset + IANA annotation is the offset time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..ae2939f5511c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = instance.toString({ timeZone }); +assert.sameValue(result1.substr(-6), "+01:46", "Time zone string determined from offset"); +const result2 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result2.substr(-6), "+01:46", "Time zone string determined from offset"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone.js new file mode 100644 index 000000000000..a6364ab1d31f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/timezone.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Passing a TimeZone to options calls getOffsetNanosecondsFor twice, but not toString +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "has timeZone.timeZone", + "get timeZone.getOffsetNanosecondsFor", + "call timeZone.getOffsetNanosecondsFor", + "get timeZone.getOffsetNanosecondsFor", + "call timeZone.getOffsetNanosecondsFor", +]; + +const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456Z"); +const timeZone = new Proxy({ + name: "Custom/TimeZone", + + toString() { + actual.push("call timeZone.toString"); + return TemporalHelpers.toPrimitiveObserver(actual, "Custom/TimeZone", "name"); + }, + + getOffsetNanosecondsFor(instantArg) { + actual.push("call timeZone.getOffsetNanosecondsFor"); + assert.sameValue(instantArg.epochNanoseconds, instant.epochNanoseconds); + return -8735135801679; + }, +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + }, +}); + +Object.defineProperty(Temporal.TimeZone, "from", { + get() { + actual.push("get Temporal.TimeZone.from"); + return undefined; + }, +}); + +assert.sameValue(instant.toString({ timeZone }), "1975-02-02T12:00:00.987654321-02:26"); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/year-format.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/year-format.js new file mode 100644 index 000000000000..c53194fbf590 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toString/year-format.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +function epochNsInYear(year) { + // Return an epoch nanoseconds value near the middle of the given year + const avgNsPerYear = 31_556_952_000_000_000n; + return (year - 1970n) * avgNsPerYear + (avgNsPerYear / 2n); +} + +let instance = new Temporal.Instant(epochNsInYear(-100000n)); +assert.sameValue(instance.toString(), "-100000-07-01T21:30:36Z", "large negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-10000n)); +assert.sameValue(instance.toString(), "-010000-07-01T21:30:36Z", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-9999n)); +assert.sameValue(instance.toString(), "-009999-07-02T03:19:48Z", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-1000n)); +assert.sameValue(instance.toString(), "-001000-07-02T09:30:36Z", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-999n)); +assert.sameValue(instance.toString(), "-000999-07-02T15:19:48Z", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-1n)); +assert.sameValue(instance.toString(), "-000001-07-02T15:41:24Z", "year -1 formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(0n)); +assert.sameValue(instance.toString(), "0000-07-01T21:30:36Z", "year 0 formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(1n)); +assert.sameValue(instance.toString(), "0001-07-02T03:19:48Z", "year 1 formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(999n)); +assert.sameValue(instance.toString(), "0999-07-02T03:41:24Z", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(1000n)); +assert.sameValue(instance.toString(), "1000-07-02T09:30:36Z", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(9999n)); +assert.sameValue(instance.toString(), "9999-07-02T15:41:24Z", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(10000n)); +assert.sameValue(instance.toString(), "+010000-07-01T21:30:36Z", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(100000n)); +assert.sameValue(instance.toString(), "+100000-07-01T21:30:36Z", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/era/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toStringTag/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/era/shell.js rename to js/src/tests/test262/built-ins/Temporal/Instant/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toStringTag/prop-desc.js new file mode 100644 index 000000000000..08feae2e3c4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toStringTag/prop-desc.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype-@@tostringtag +description: The @@toStringTag property of Temporal.Instant +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +const { Instant } = Temporal; +verifyProperty(Instant.prototype, Symbol.toStringTag, { + value: "Temporal.Instant", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/eraYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toStringTag/shell.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/eraYear/shell.js rename to js/src/tests/test262/built-ins/Temporal/Instant/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/builtin.js new file mode 100644 index 000000000000..7563cc95f197 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: > + Tests that Temporal.Instant.prototype.toZonedDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.toZonedDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.toZonedDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.toZonedDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.toZonedDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/calendar-temporal-object.js new file mode 100644 index 000000000000..afb9a882ba4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/calendar-temporal-object.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.instant.prototype.tozoneddatetime step 6: + 6. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + const result = instant.toZonedDateTime({ timeZone: "UTC", calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/length.js new file mode 100644 index 000000000000..088c48f63298 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: Temporal.Instant.prototype.toZonedDateTime.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toZonedDateTime, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/name.js new file mode 100644 index 000000000000..af1c576a92a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: Temporal.Instant.prototype.toZonedDateTime.name is "toZonedDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toZonedDateTime, "name", { + value: "toZonedDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/not-a-constructor.js new file mode 100644 index 000000000000..1768b10ec96d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: > + Temporal.Instant.prototype.toZonedDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.toZonedDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.toZonedDateTime), false, + "isConstructor(Temporal.Instant.prototype.toZonedDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/plain-custom-timezone.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/plain-custom-timezone.js new file mode 100644 index 000000000000..2af5f9bb818b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/plain-custom-timezone.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: TimeZone.getPlainDateTimeFor is not called +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "has timeZone.timeZone", +]; + +const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456789Z"); +const dateTime = Temporal.PlainDateTime.from("1963-07-02T12:00:00.987654321"); +const calendar = Temporal.Calendar.from("iso8601"); +const timeZone = new Proxy({ + getPlainDateTimeFor() { + actual.push("call timeZone.getPlainDateTimeFor"); + return dateTime; + } +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + }, +}); + +const result = instant.toZonedDateTime({ timeZone, calendar }); +assert.sameValue(result.epochNanoseconds, instant.epochNanoseconds); + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/prop-desc.js new file mode 100644 index 000000000000..004706c1aa18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: The "toZonedDateTime" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.toZonedDateTime, + "function", + "`typeof Instant.prototype.toZonedDateTime` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "toZonedDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..9a78fead5be1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone, calendar: "iso8601" }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..fb4979038e6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTime/timezone-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/builtin.js new file mode 100644 index 000000000000..7f560b705a55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetimeiso +description: > + Tests that Temporal.Instant.prototype.toZonedDateTimeISO + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.toZonedDateTimeISO), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.toZonedDateTimeISO), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.toZonedDateTimeISO), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.toZonedDateTimeISO.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/length.js new file mode 100644 index 000000000000..8350bfa81193 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetimeiso +description: Temporal.Instant.prototype.toZonedDateTimeISO.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toZonedDateTimeISO, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/name.js new file mode 100644 index 000000000000..cb2e8efd69c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetimeiso +description: Temporal.Instant.prototype.toZonedDateTimeISO.name is "toZonedDateTimeISO". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.toZonedDateTimeISO, "name", { + value: "toZonedDateTimeISO", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/not-a-constructor.js new file mode 100644 index 000000000000..4c77144f2858 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetimeiso +description: > + Temporal.Instant.prototype.toZonedDateTimeISO does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.toZonedDateTimeISO(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.toZonedDateTimeISO), false, + "isConstructor(Temporal.Instant.prototype.toZonedDateTimeISO)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/prop-desc.js new file mode 100644 index 000000000000..dffd4f95aa2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetimeiso +description: The "toZonedDateTimeISO" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.toZonedDateTimeISO, + "function", + "`typeof Instant.prototype.toZonedDateTimeISO` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "toZonedDateTimeISO", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-datetime.js new file mode 100644 index 000000000000..ca2e44891c7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-datetime.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetimeiso +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.toZonedDateTimeISO(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.toZonedDateTimeISO({ timeZone }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..39165867f696 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetimeiso +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/argument-zoneddatetime.js new file mode 100644 index 000000000000..3167716e1759 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/argument-zoneddatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.instant.prototype.until step 3: + 3. Set _other_ to ? ToTemporalInstant(_other_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const instant = new Temporal.Instant(1_000_000_000_000_000_000n); + const result = instant.until(datetime); + assert.sameValue(result.total({ unit: "nanoseconds" }), 987654321, "nanoseconds result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/builtin.js new file mode 100644 index 000000000000..ccaed38b499b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: > + Tests that Temporal.Instant.prototype.until + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.until), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.until), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.until), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.until.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/instant-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/instant-string-multiple-offsets.js new file mode 100644 index 000000000000..f6c6187ff259 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/instant-string-multiple-offsets.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Instant strings with UTC offset fractional part are not confused with time fractional part +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = instance.until(str); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "UTC offset determined from offset part of string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/instant-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/instant-string.js new file mode 100644 index 000000000000..3f0d98b72d18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/instant-string.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Conversion of ISO date-time strings to Temporal.Instant instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.until(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => instance.until(str), "date-time + IANA annotation is not an instant"); + +str = "1970-01-01T00:00Z"; +const result1 = instance.until(str); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z preserves exact time"); + +str = "1970-01-01T00:00+01:00"; +const result2 = instance.until(str); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 0, 0, -3600, 0, 0, 0, "date-time + offset preserves exact time with offset"); + +str = "1970-01-01T00:00Z[Etc/Ignored]"; +const result3 = instance.until(str); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation ignores the IANA annotation"); + +str = "1970-01-01T00:00+01:00[Etc/Ignored]"; +const result4 = instance.until(str); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 0, 0, -3600, 0, 0, 0, "date-time + offset + IANA annotation ignores the IANA annotation"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-invalid-string.js new file mode 100644 index 000000000000..1abf15f9884b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..c5f9b9bcef77 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_086_403_661_988_655_322n); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => earlier.until(later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..2ceb45dcbefd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +const units = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => earlier.until(later, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-undefined.js new file mode 100644 index 000000000000..67465d86007d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); + +const explicit = earlier.until(later, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default largestUnit is second"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default largestUnit is second"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-wrong-type.js new file mode 100644 index 000000000000..136312199ddc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "hour", + (largestUnit) => earlier.until(later, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/length.js new file mode 100644 index 000000000000..b4c51642bb23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Temporal.Instant.prototype.until.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.until, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/name.js new file mode 100644 index 000000000000..48e75c455126 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Temporal.Instant.prototype.until.name is "until". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.until, "name", { + value: "until", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/not-a-constructor.js new file mode 100644 index 000000000000..3b7145fd8fdf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: > + Temporal.Instant.prototype.until does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.until(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.until), false, + "isConstructor(Temporal.Instant.prototype.until)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/options-undefined.js new file mode 100644 index 000000000000..9a1603bf75fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/options-undefined.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const earlier = new Temporal.Instant(957270896_987_654_321n); +const later = new Temporal.Instant(959949296_987_654_322n); + +const explicit = earlier.until(later, undefined); +assert.sameValue(explicit.years, 0, "default largest unit is seconds"); +assert.sameValue(explicit.months, 0, "default largest unit is seconds"); +assert.sameValue(explicit.weeks, 0, "default largest unit is seconds"); +assert.sameValue(explicit.days, 0, "default largest unit is seconds"); +assert.sameValue(explicit.hours, 0, "default largest unit is seconds"); +assert.sameValue(explicit.minutes, 0, "default largest unit is seconds"); +assert.sameValue(explicit.seconds, 2678400, "default largest unit is seconds"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = earlier.until(later); +assert.sameValue(implicit.years, 0, "default largest unit is seconds"); +assert.sameValue(implicit.months, 0, "default largest unit is seconds"); +assert.sameValue(implicit.weeks, 0, "default largest unit is seconds"); +assert.sameValue(implicit.days, 0, "default largest unit is seconds"); +assert.sameValue(implicit.hours, 0, "default largest unit is seconds"); +assert.sameValue(implicit.minutes, 0, "default largest unit is seconds"); +assert.sameValue(implicit.seconds, 2678400, "default largest unit is seconds"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/prop-desc.js new file mode 100644 index 000000000000..862175eb7bde --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: The "until" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.until, + "function", + "`typeof Instant.prototype.until` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "until", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-nan.js new file mode 100644 index 000000000000..49b3c7aac6de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_000_090_061_988_655_322n); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-non-integer.js new file mode 100644 index 000000000000..74109913b0a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_000_000_000_000_005n); +const result = earlier.until(later, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..a023d2b8a9b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_000_000_000_000_005n); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-undefined.js new file mode 100644 index 000000000000..51ed46d76014 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_000_090_061_988_655_322n); + +const explicit = earlier.until(later, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..a84889bbfb0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.instant.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_000_090_061_988_655_322n); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => earlier.until(later, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-invalid-string.js new file mode 100644 index 000000000000..01d5e95dbcdb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_123_987_500n); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-undefined.js new file mode 100644 index 000000000000..ff142694a8ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_123_987_500n); + +const explicit1 = earlier.until(later, { smallestUnit: "microsecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, "default roundingMode is trunc"); +const implicit1 = earlier.until(later, { smallestUnit: "microsecond" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, "default roundingMode is trunc"); + +const explicit2 = earlier.until(later, { smallestUnit: "millisecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 0, 0, 90061, 123, 0, 0, "default roundingMode is trunc"); +const implicit2 = earlier.until(later, { smallestUnit: "millisecond" }); +TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 0, 0, 90061, 123, 0, 0, "default roundingMode is trunc"); + +const explicit3 = earlier.until(later, { smallestUnit: "second", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 0, 0, 90061, 0, 0, 0, "default roundingMode is trunc"); +const implicit3 = earlier.until(later, { smallestUnit: "second" }); +TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 0, 0, 90061, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-wrong-type.js new file mode 100644 index 000000000000..f3343c525fad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_123_987_500n); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-invalid-string.js new file mode 100644 index 000000000000..d1b250667b51 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..2f057a5deeda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_987_654_321n); +const later = new Temporal.Instant(1_086_403_661_988_655_322n); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => earlier.until(later, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-undefined.js new file mode 100644 index 000000000000..2d6af8c58e2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); + +const explicit = earlier.until(later, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-wrong-type.js new file mode 100644 index 000000000000..76d0e907bd29 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); +const later = new Temporal.Instant(1_000_090_061_987_654_321n); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => earlier.until(later, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/year-zero.js new file mode 100644 index 000000000000..a59c48a7955a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/until/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.until +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "-000000-03-30T00:45Z", + "-000000-03-30T01:45+01:00", + "-000000-03-30T01:45:00+01:00[UTC]" +]; +const instance = new Temporal.Instant(0n); +invalidStrings.forEach((str) => { + assert.throws( + RangeError, + () => instance.until(str), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/builtin.js new file mode 100644 index 000000000000..afee4885dd23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.valueof +description: > + Tests that Temporal.Instant.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Instant.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Instant.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Instant.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Instant.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/length.js new file mode 100644 index 000000000000..172645e3e761 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.valueof +description: Temporal.Instant.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/name.js new file mode 100644 index 000000000000..18e790a79a34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.valueof +description: Temporal.Instant.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Instant.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/not-a-constructor.js new file mode 100644 index 000000000000..bd41d4781dca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.valueof +description: > + Temporal.Instant.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Instant.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Instant.prototype.valueOf), false, + "isConstructor(Temporal.Instant.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/prop-desc.js new file mode 100644 index 000000000000..82d18adb3b80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.valueof +description: The "valueOf" property of Temporal.Instant.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Instant.prototype.valueOf, + "function", + "`typeof Instant.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.Instant.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Instant/prototype/valueOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Now/builtin.js b/js/src/tests/test262/built-ins/Temporal/Now/builtin.js new file mode 100644 index 000000000000..7bac02a8da91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now +description: Tests that Temporal.Now meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Now), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Now), + "[object Temporal.Now]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Now), + Object.prototype, "prototype"); + +assert.sameValue(Temporal.Now.prototype, + undefined, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/instant/length.js b/js/src/tests/test262/built-ins/Temporal/Now/instant/length.js index 1b22ad925c23..45725bfff42f 100644 --- a/js/src/tests/test262/built-ins/Temporal/Now/instant/length.js +++ b/js/src/tests/test262/built-ins/Temporal/Now/instant/length.js @@ -4,6 +4,15 @@ /*--- esid: sec-temporal.now.instant description: Temporal.Now.instant.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. includes: [propertyHelper.js] features: [Temporal] ---*/ diff --git a/js/src/tests/test262/built-ins/Temporal/Now/instant/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/instant/prop-desc.js index 0a21a6dd1b66..9627d5747fe2 100644 --- a/js/src/tests/test262/built-ins/Temporal/Now/instant/prop-desc.js +++ b/js/src/tests/test262/built-ins/Temporal/Now/instant/prop-desc.js @@ -8,6 +8,8 @@ includes: [propertyHelper.js] features: [Temporal] ---*/ +assert.sameValue(typeof Temporal.Now.instant, "function", "typeof is function"); + verifyProperty(Temporal.Now, 'instant', { enumerable: false, writable: true, diff --git a/js/src/tests/test262/built-ins/Temporal/Now/instant/return-value-instance.js b/js/src/tests/test262/built-ins/Temporal/Now/instant/return-value-instance.js new file mode 100644 index 000000000000..65a88144a149 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/instant/return-value-instance.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.instant +description: Temporal.Now.instant returns an Instant +features: [Temporal] +---*/ + +const instant = Temporal.Now.instant(); +assert(instant instanceof Temporal.Instant); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/era/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/era/shell.js rename to js/src/tests/test262/built-ins/Temporal/Now/plainDate/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/calendar-temporal-object.js new file mode 100644 index 000000000000..8e336826fc50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/calendar-temporal-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.now.plaindate step 1: + 1. Let _dateTime_ be ? SystemDateTime(_temporalTimeZoneLike_, _calendar_). + sec-temporal-systemdatetime step 3: + 3. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = Temporal.Now.plainDate(temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/calendar-undefined.js new file mode 100644 index 000000000000..ad20e314e518 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/calendar-undefined.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: Throws when the calendar argument is undefined +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.Now.plainDate(), "implicit"); +assert.throws(RangeError, () => Temporal.Now.plainDate(undefined), "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/length.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/length.js new file mode 100644 index 000000000000..e2922111281b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: Temporal.Now.plainDate.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Now.plainDate, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/prop-desc.js new file mode 100644 index 000000000000..36860cad7aaa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/prop-desc.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: The "plainDate" property of Temporal.Now +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Now.plainDate, "function", "typeof is function"); + +verifyProperty(Temporal.Now, "plainDate", { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..02f6de55dfa8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(RangeError, () => Temporal.Now.plainDate("iso8601", timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..9f5bf1e4bf05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindate +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.Now.plainDate('iso8601', timeZone), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..ea3f0cc824dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(RangeError, () => Temporal.Now.plainDate("iso8601", timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..6f6a668341cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(TypeError, () => Temporal.Now.plainDate("iso8601", timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-string-datetime.js new file mode 100644 index 000000000000..e899aaded3d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/timezone-string-datetime.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Now.plainDate("iso8601", timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Now.plainDate("iso8601", { timeZone }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + Temporal.Now.plainDate("iso8601", timeZone); + Temporal.Now.plainDate("iso8601", { timeZone }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDate/toPlainDate-override.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/toPlainDate-override.js new file mode 100644 index 000000000000..c3ac179b3834 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDate/toPlainDate-override.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: PlainDateTime.toPlainDate is not observably called +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "has timeZone.timeZone", + "get timeZone.getOffsetNanosecondsFor", + "call timeZone.getOffsetNanosecondsFor", +]; + +Object.defineProperty(Temporal.PlainDateTime.prototype, "toPlainDate", { + get() { + actual.push("get Temporal.PlainDateTime.prototype.toPlainDate"); + return function() { + actual.push("call Temporal.PlainDateTime.prototype.toPlainDate"); + }; + }, +}); + +const timeZone = new Proxy({ + getOffsetNanosecondsFor(instant) { + actual.push("call timeZone.getOffsetNanosecondsFor"); + assert.sameValue(instant instanceof Temporal.Instant, true, "Instant"); + return 86399_999_999_999; + }, +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + }, +}); + +const result = Temporal.Now.plainDate("iso8601", timeZone); +assert.notSameValue(result, undefined); +assert.sameValue(result instanceof Temporal.PlainDate, true); + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/eraYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/eraYear/shell.js rename to js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/length.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/length.js new file mode 100644 index 000000000000..5711accab99f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindateiso +description: Temporal.Now.plainDateISO.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Now.plainDateISO, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/prop-desc.js new file mode 100644 index 000000000000..a90fd4eb5d6a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/prop-desc.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindateiso +description: The "plainDateISO" property of Temporal.Now +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Now.plainDateISO, "function", "typeof is function"); + +verifyProperty(Temporal.Now, "plainDateISO", { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/return-value.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/return-value.js new file mode 100644 index 000000000000..e6c07f87b570 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/return-value.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindateiso +description: Functions when time zone argument is omitted +features: [Temporal] +---*/ + +const d = Temporal.Now.plainDateISO(); +assert(d instanceof Temporal.PlainDate); +assert.sameValue(d.calendar.id, "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..a2abdc18310c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindateiso +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(RangeError, () => Temporal.Now.plainDateISO(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..5e35f7c56cfb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindateiso +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.Now.plainDateISO(timeZone), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..fc89f5676c1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindateiso +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(RangeError, () => Temporal.Now.plainDateISO(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..dd405912a504 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindateiso +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(TypeError, () => Temporal.Now.plainDateISO(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-string-datetime.js new file mode 100644 index 000000000000..9f099a0429b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateISO/timezone-string-datetime.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindateiso +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Now.plainDateISO(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Now.plainDateISO({ timeZone }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + Temporal.Now.plainDateISO(timeZone); + Temporal.Now.plainDateISO({ timeZone }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-object.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-object.js index a8dae0b11d23..98a98dd351d2 100644 --- a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-object.js +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-object.js @@ -10,7 +10,12 @@ features: [Proxy, Temporal] ---*/ const actual = []; -const expected = [ +const expectedWithout = [ + 'has calendar.calendar', + 'get calendar.calendar', + 'has nestedCalendar.calendar' +]; +const expectedWith = [ 'has calendar.calendar', 'get calendar.calendar', 'has nestedCalendar.calendar', @@ -59,6 +64,13 @@ Object.defineProperty(Temporal.Calendar, 'from', { Temporal.Now.plainDateTime(calendar); -assert.compareArray(actual, expected, 'The value of actual is expected to equal the value of expected'); +assert.compareArray(actual, expectedWithout, 'Observable interactions without `calendar` property'); + +actual.length = 0; +nestedCalendar.calendar = null; + +Temporal.Now.plainDateTime(calendar); + +assert.compareArray(actual, expectedWith, 'Observable interactions with `calendar` property'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-temporal-object.js index c0dde0280a10..9a4d310765c7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-temporal-object.js +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-temporal-object.js @@ -19,7 +19,7 @@ features: [Temporal, arrow-function] TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { const result = Temporal.Now.plainDateTime(temporalObject); - assert.sameValue(result.calendar, calendar, 'The value of result.calendar is expected to equal the value of calendar'); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); }); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-undefined.js new file mode 100644 index 000000000000..20dd5e3c76b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/calendar-undefined.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindatetime +description: Throws when the calendar argument is undefined +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.Now.plainDateTime(), "implicit"); +assert.throws(RangeError, () => Temporal.Now.plainDateTime(undefined), "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/prop-desc.js index a41874f3a721..8f8fc724b387 100644 --- a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/prop-desc.js +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/prop-desc.js @@ -8,6 +8,8 @@ includes: [propertyHelper.js] features: [Temporal] ---*/ +assert.sameValue(typeof Temporal.Now.plainDateTime, "function", "typeof is function"); + verifyProperty(Temporal.Now, 'plainDateTime', { enumerable: false, writable: true, diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/shell.js index 2639dd7f693d..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/shell.js @@ -49,6 +49,29 @@ var TemporalHelpers = { assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); }, + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + /* * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): * @@ -92,17 +115,32 @@ var TemporalHelpers = { }, /* - * assertPlainMonthDay(monthDay, monthCode, day[, description]): + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): * * Shorthand for asserting that each field of a Temporal.PlainMonthDay is * equal to an expected value. (Except the `calendar` property, since callers * may want to assert either object equality with an object they put in there, * or the result of monthDay.calendar.toString().) */ - assertPlainMonthDay(monthDay, monthCode, day, description = "") { + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); }, /* @@ -121,6 +159,18 @@ var TemporalHelpers = { assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); }, + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + /* * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): * @@ -137,6 +187,670 @@ var TemporalHelpers = { assert.sameValue(yearMonth.month, month, `${description} month result`); assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + /* * Check that any calendar-carrying Temporal object has its [[Calendar]] * internal slot read by ToTemporalCalendar, and does not fetch the calendar @@ -180,6 +894,506 @@ var TemporalHelpers = { }); }, + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + /* * specificOffsetTimeZone(): * @@ -208,4 +1422,96 @@ var TemporalHelpers = { } return new SpecificOffsetTimeZone(offsetValue); }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, }; diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..cf300d604959 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.Now.plainDateTime('iso8601', timeZone), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..8ebb3c319f29 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone-string-datetime.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Now.plainDateTime("iso8601", timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Now.plainDateTime("iso8601", { timeZone }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + Temporal.Now.plainDateTime("iso8601", timeZone); + Temporal.Now.plainDateTime("iso8601", { timeZone }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone.js new file mode 100644 index 000000000000..664b121bc656 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTime/timezone.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindatetime +description: The value returned by TimeZone.getOffsetNanosecondsFor affects the result +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "has timeZone.timeZone", + "get timeZone.getOffsetNanosecondsFor", + "call timeZone.getOffsetNanosecondsFor", +]; + +const timeZone = new Proxy({ + getOffsetNanosecondsFor(instant) { + actual.push("call timeZone.getOffsetNanosecondsFor"); + assert.sameValue(instant instanceof Temporal.Instant, true, "Instant"); + return -Number(instant.epochNanoseconds % 86400_000_000_000n); + }, +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + }, +}); + +const calendar = Temporal.Calendar.from("iso8601"); + +const result = Temporal.Now.plainDateTime(calendar, timeZone); +for (const property of ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]) { + assert.sameValue(result[property], 0, property); +} + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/era/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/era/shell.js rename to js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/extensible.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/extensible.js new file mode 100644 index 000000000000..dfec16d3847f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/extensible.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Temporal.Now.plainDateTimeISO is extensible. +features: [Temporal] +---*/ + +assert( + Object.isExtensible(Temporal.Now.plainDateTimeISO), + 'Object.isExtensible(Temporal.Now.plainDateTimeISO) must return true' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/length.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/length.js new file mode 100644 index 000000000000..616f2d9bfe80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: The `length` property of Temporal.Now.plainDateTimeISO +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Now.plainDateTimeISO, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/name.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/name.js new file mode 100644 index 000000000000..1b40f10220a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/name.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plainDateTimeISO +description: Temporal.Now.plainDateTimeISO.name is "plainDateTimeISO". +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + Temporal.Now.plainDateTimeISO.name, + 'plainDateTimeISO', + 'The value of Temporal.Now.plainDateTimeISO.name is expected to be "plainDateTimeISO"' +); + +verifyProperty(Temporal.Now.plainDateTimeISO, 'name', { + enumerable: false, + writable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/not-a-constructor.js new file mode 100644 index 000000000000..f9af5bf8bac1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/not-a-constructor.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Temporal.Now.plainDateTimeISO does not implement [[Construct]] +includes: [isConstructor.js] +features: [Reflect.construct, Temporal, arrow-function] +---*/ + +assert.sameValue(isConstructor(Temporal.Now.plainDateTimeISO), false, 'isConstructor(Temporal.Now.plainDateTimeISO) must return false'); + +assert.throws(TypeError, () => { + new Temporal.Now.plainDateTimeISO(); +}, 'new Temporal.Now.plainDateTimeISO() throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/prop-desc.js new file mode 100644 index 000000000000..354c53a4a6e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: The "plainDateTimeISO" property of Temporal.Now +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Now.plainDateTimeISO, "function", "typeof is function"); + +verifyProperty(Temporal.Now, 'plainDateTimeISO', { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/return-value-calendar.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/return-value-calendar.js new file mode 100644 index 000000000000..bfc4a75c139d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/return-value-calendar.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Temporal.Now.plainDateTimeISO is extensible. +features: [Temporal] +---*/ + +const result = Temporal.Now.plainDateTimeISO(); +assert(result.calendar instanceof Temporal.Calendar); +assert.sameValue(result.calendar.id, "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/return-value.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/return-value.js new file mode 100644 index 000000000000..0d2612634d34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/return-value.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Return value describes the start of a day +features: [BigInt, Temporal] +---*/ +const timeZone = { + getOffsetNanosecondsFor(instant) { + return -Number(instant.epochNanoseconds % 86400000000000n); + } +}; + +const result = Temporal.Now.plainDateTimeISO(timeZone); + +for (const property of ['hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond']) { + assert.sameValue(result[property], 0, 'The value of result[property] is expected to be 0'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/time-zone-undefined.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/time-zone-undefined.js new file mode 100644 index 000000000000..007a745e6d45 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/time-zone-undefined.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Functions when time zone argument is omitted +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = []; + +Object.defineProperty(Temporal.TimeZone, "from", { + get() { + actual.push("get Temporal.TimeZone.from"); + return undefined; + }, +}); + +const resultExplicit = Temporal.Now.plainDateTimeISO(undefined); +assert( + resultExplicit instanceof Temporal.PlainDateTime, + 'The result of evaluating (resultExplicit instanceof Temporal.PlainDateTime) is expected to be true' +); + +assert.compareArray(actual, expected, 'The value of actual is expected to equal the value of expected'); + +const resultImplicit = Temporal.Now.plainDateTimeISO(); +assert( + resultImplicit instanceof Temporal.PlainDateTime, + 'The result of evaluating (resultImplicit instanceof Temporal.PlainDateTime) is expected to be true' +); + +assert.compareArray(actual, expected, 'The value of actual is expected to equal the value of expected'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-invocation.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-invocation.js new file mode 100644 index 000000000000..b9a0fbd503a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-invocation.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Correctly invokes `getOffsetNanosecondsFor` method of TimeZone-like objects +features: [Temporal] +---*/ + +var calls = []; +var timeZone = { + getOffsetNanosecondsFor: function() { + calls.push({ + args: arguments, + this: this + }); + return 0; + }, +}; + +Temporal.Now.plainDateTimeISO(timeZone); + +assert.sameValue(calls.length, 1, 'The value of calls.length is expected to be 1'); +assert.sameValue(calls[0].args.length, 1, 'The value of calls[0].args.length is expected to be 1'); +assert( + calls[0].args[0] instanceof Temporal.Instant, + 'The result of evaluating (calls[0].args[0] instanceof Temporal.Instant) is expected to be true' +); +assert.sameValue(calls[0].this, timeZone, 'The value of calls[0].this is expected to equal the value of timeZone'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..f0807eb4d775 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal, arrow-function] +includes: [temporalHelpers.js] +---*/ +[3600000000000.5, NaN].forEach(wrongOffset => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws( + RangeError, + () => Temporal.Now.plainDateTimeISO(timeZone), + 'Temporal.Now.plainDateTimeISO(timeZone) throws a RangeError exception' + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-non-method.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-non-method.js new file mode 100644 index 000000000000..da6792a88362 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-non-method.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Rejects when `getOffsetNanosecondsFor` property is not a method +features: [Temporal] +---*/ + +var timeZone = { + getOffsetNanosecondsFor: 7 +}; + +assert.throws(TypeError, function() { + Temporal.Now.plainDateTimeISO(timeZone); +}, 'Temporal.Now.plainDateTimeISO(timeZone) throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-not-a-number.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-not-a-number.js new file mode 100644 index 000000000000..c8445777607f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-not-a-number.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Rejects non-numeric nanosecond values reported by TimeZone-like object +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ +const invalidValues = [ + undefined, + null, + true, + '2020-01-01T12:45:36', + Symbol(), + 2n, + {}, + Temporal.PlainDateTime, + Temporal.PlainDateTime.prototype +]; + +for (const dateTime of invalidValues) { + let callCount = 0; + + const timeZone = { + getOffsetNanosecondsFor(instant, calendar) { + callCount += 1; + return dateTime; + } + }; + + assert.throws( + TypeError, + () => Temporal.Now.plainDateTimeISO(timeZone), + 'Temporal.Now.plainDateTimeISO(timeZone) throws a TypeError exception' + ); + + assert.sameValue(callCount, 1, 'The value of callCount is expected to be 1'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..104d5f68d40d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.Now.plainDateTimeISO(timeZone), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..ce113778a531 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal, arrow-function] +includes: [temporalHelpers.js] +---*/ +[-86400000000001, 86400000000001, -Infinity, Infinity].forEach(wrongOffset => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws( + RangeError, + () => Temporal.Now.plainDateTimeISO(timeZone), + 'Temporal.Now.plainDateTimeISO(timeZone) throws a RangeError exception' + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-poisoned.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-poisoned.js new file mode 100644 index 000000000000..55ac7f640337 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-poisoned.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Forwards error when accessing `getOffsetNanosecondsFor` property throws +features: [Temporal] +---*/ + +var timeZone = { + get getOffsetNanosecondsFor() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Temporal.Now.plainDateTimeISO(timeZone); +}, 'Temporal.Now.plainDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-throws.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-throws.js new file mode 100644 index 000000000000..fea7cbd9fbaf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-throws.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Forwards error when `getOffsetNanosecondsFor` throws +features: [Temporal] +---*/ + +var timeZone = { + getOffsetNanosecondsFor() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Temporal.Now.plainDateTimeISO(timeZone); +}, 'Temporal.Now.plainDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..50dcfd4ad0dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: TypeError thrown if time zone reports an offset that is not a Number +features: [BigInt, Symbol, Temporal, arrow-function] +includes: [temporalHelpers.js] +---*/ +[undefined, null, true, '+01:00', Symbol(), 3600000000000n, {}, { + valueOf() { + return 3600000000000; + } +}].forEach(wrongOffset => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws( + TypeError, + () => Temporal.Now.plainDateTimeISO(timeZone), + 'Temporal.Now.plainDateTimeISO(timeZone) throws a TypeError exception' + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-call-tostring.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-call-tostring.js new file mode 100644 index 000000000000..302b4420251c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-call-tostring.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Forwards error thrown by invoking "toString" property +features: [Temporal] +---*/ + +var timeZone = { + timeZone: { + timeZone: true, + toString: function() { + throw new Test262Error(); + }, + } +}; + +assert.throws(Test262Error, function() { + Temporal.Now.plainDateTimeISO(timeZone); +}, 'Temporal.Now.plainDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-get-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-get-timezone.js new file mode 100644 index 000000000000..c420601cd285 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-get-timezone.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Forwards error thrown by retrieving value of "timeZone" property +features: [Temporal] +---*/ + +var timeZone = { + get timeZone() { + throw new Test262Error(); + }, +}; + +assert.throws(Test262Error, function() { + Temporal.Now.plainDateTimeISO(timeZone); +}, 'Temporal.Now.plainDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-has-nested-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-has-nested-timezone.js new file mode 100644 index 000000000000..28b73434e04c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-has-nested-timezone.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Forwards error thrown by checking presence of nested "timeZone" property +features: [Proxy, Temporal] +---*/ + +var timeZone = { + timeZone: new Proxy({}, { + has: function(target, property) { + if (property === 'timeZone') { + throw new Test262Error(); + } + }, + }) +}; + +assert.throws(Test262Error, function() { + Temporal.Now.plainDateTimeISO(timeZone); +}, 'Temporal.Now.plainDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-has-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-has-timezone.js new file mode 100644 index 000000000000..18b568794d08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object-fail-has-timezone.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Forwards error thrown by checking presence of "timeZone" property +features: [Proxy, Temporal] +---*/ + +var timeZone = new Proxy({}, { + has: function(target, property) { + if (property === 'timeZone') { + throw new Test262Error(); + } + }, +}); + +assert.throws(Test262Error, function() { + Temporal.Now.plainDateTimeISO(timeZone); +}, 'Temporal.Now.plainDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object.js new file mode 100644 index 000000000000..b1aa3a9c8879 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-object.js @@ -0,0 +1,80 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Observable interactions with the provided timezone-like object +includes: [compareArray.js] +features: [BigInt, Proxy, Temporal] +---*/ +const actual = []; + +const expected = [ + 'has timeZone.timeZone', + 'get timeZone.timeZone', + 'has nestedTimeZone.timeZone', + 'get nestedTimeZone.getOffsetNanosecondsFor', + 'call nestedTimeZone.getOffsetNanosecondsFor' +]; + +const nestedTimeZone = new Proxy({ + getOffsetNanosecondsFor(instant) { + actual.push('call nestedTimeZone.getOffsetNanosecondsFor'); + + assert.sameValue( + instant instanceof Temporal.Instant, + true, + 'The result of evaluating (instant instanceof Temporal.Instant) is expected to be true' + ); + + return -Number(instant.epochNanoseconds % 86400000000000n); + } +}, { + has(target, property) { + actual.push(`has nestedTimeZone.${String(property)}`); + return property in target; + }, + + get(target, property) { + actual.push(`get nestedTimeZone.${String(property)}`); + return target[property]; + } +}); + +const timeZone = new Proxy({ + timeZone: nestedTimeZone, + + getOffsetNanosecondsFor(instant) { + actual.push('call timeZone.getOffsetNanosecondsFor'); + + assert.sameValue( + instant instanceof Temporal.Instant, + true, + 'The result of evaluating (instant instanceof Temporal.Instant) is expected to be true' + ); + + return -Number(instant.epochNanoseconds % 86400000000000n); + } +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + } +}); + +Object.defineProperty(Temporal.TimeZone, 'from', { + get() { + actual.push('get Temporal.TimeZone.from'); + return undefined; + } +}); + +Temporal.Now.plainDateTimeISO(timeZone); +assert.compareArray(actual, expected, 'The value of actual is expected to equal the value of expected'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-string-datetime.js new file mode 100644 index 000000000000..388400cf3ea4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainDateTimeISO/timezone-string-datetime.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Now.plainDateTimeISO(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Now.plainDateTimeISO({ timeZone }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + Temporal.Now.plainDateTimeISO(timeZone); + Temporal.Now.plainDateTimeISO({ timeZone }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/eraYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/eraYear/shell.js rename to js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/length.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/length.js new file mode 100644 index 000000000000..0ab120b09aa9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: Temporal.Now.plainTimeISO.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Now.plainTimeISO, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/prop-desc.js new file mode 100644 index 000000000000..6e448adfb120 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/prop-desc.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: The "plainTimeISO" property of Temporal.Now +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Now.plainTimeISO, "function", "typeof is function"); + +verifyProperty(Temporal.Now, "plainTimeISO", { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/return-value.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/return-value.js new file mode 100644 index 000000000000..ffaf84f453a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/return-value.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: Functions when time zone argument is omitted +features: [Temporal] +---*/ + +const t = Temporal.Now.plainTimeISO(); +assert(t instanceof Temporal.PlainTime); +assert.sameValue(t.calendar.id, "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..187aae24e3af --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(RangeError, () => Temporal.Now.plainTimeISO(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..0eecf670c744 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaintimeiso +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.Now.plainTimeISO(timeZone), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..6272859988e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(RangeError, () => Temporal.Now.plainTimeISO(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..7dcd16f5e3ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(TypeError, () => Temporal.Now.plainTimeISO(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-string-datetime.js new file mode 100644 index 000000000000..622fd94a7aa8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone-string-datetime.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Now.plainTimeISO(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Now.plainTimeISO({ timeZone }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[UTC]", + "2021-08-19T1730[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T1730Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", + "2021-08-19T1730-07:00[UTC]", + "2021-08-19T17:30-0700[UTC]", + "2021-08-19T1730-0700[UTC]", +].forEach((timeZone) => { + Temporal.Now.plainTimeISO(timeZone); + Temporal.Now.plainTimeISO({ timeZone }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone.js new file mode 100644 index 000000000000..e3db6b6f786e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/timezone.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: The value returned by TimeZone.getOffsetNanosecondsFor affects the result +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "has timeZone.timeZone", + "get timeZone.getOffsetNanosecondsFor", + "call timeZone.getOffsetNanosecondsFor", +]; + +const timeZone = new Proxy({ + getOffsetNanosecondsFor(instant) { + actual.push("call timeZone.getOffsetNanosecondsFor"); + assert.sameValue(instant instanceof Temporal.Instant, true, "Instant"); + return -Number(instant.epochNanoseconds % 86400_000_000_000n); + }, +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + }, +}); + +const result = Temporal.Now.plainTimeISO(timeZone); +assert.sameValue(result instanceof Temporal.PlainTime, true); +for (const property of ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]) { + assert.sameValue(result[property], 0, property); +} + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/toPlainTime-override.js b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/toPlainTime-override.js new file mode 100644 index 000000000000..ea5910393e4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/plainTimeISO/toPlainTime-override.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaintimeiso +description: PlainDateTime.toPlainTime is not observably called +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "has timeZone.timeZone", + "get timeZone.getOffsetNanosecondsFor", + "call timeZone.getOffsetNanosecondsFor", +]; + +Object.defineProperty(Temporal.PlainDateTime.prototype, "toPlainTime", { + get() { + actual.push("get Temporal.PlainDateTime.prototype.toPlainTime"); + return function() { + actual.push("call Temporal.PlainDateTime.prototype.toPlainTime"); + }; + }, +}); + +const timeZone = new Proxy({ + getOffsetNanosecondsFor(instant) { + actual.push("call timeZone.getOffsetNanosecondsFor"); + assert.sameValue(instant instanceof Temporal.Instant, true, "Instant"); + return -Number(instant.epochNanoseconds % 86400_000_000_000n); + }, +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + }, +}); + +const result = Temporal.Now.plainTimeISO(timeZone); +assert.sameValue(result instanceof Temporal.PlainTime, true); +for (const property of ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]) { + assert.sameValue(result[property], 0, property); +} + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/prop-desc.js new file mode 100644 index 000000000000..146270892b9b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now +description: The "Now" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Now, + "object", + "`typeof Now` is `object`" +); + +verifyProperty(Temporal, "Now", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/timeZone/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/timeZone/prop-desc.js index 26cc5ef94bb5..77ac73657931 100644 --- a/js/src/tests/test262/built-ins/Temporal/Now/timeZone/prop-desc.js +++ b/js/src/tests/test262/built-ins/Temporal/Now/timeZone/prop-desc.js @@ -13,6 +13,8 @@ includes: [propertyHelper.js] features: [Temporal] ---*/ +assert.sameValue(typeof Temporal.Now.timeZone, "function", "typeof is function"); + verifyProperty(Temporal.Now, 'timeZone', { enumerable: false, writable: true, diff --git a/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/browser.js b/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/prop-desc.js new file mode 100644 index 000000000000..9c6733d12d99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-now-@@tostringtag +description: The @@toStringTag property of Temporal.Now +includes: [propertyHelper.js] +features: [Symbol.toStringTag, Temporal] +---*/ + +verifyProperty(Temporal.Now, Symbol.toStringTag, { + value: "Temporal.Now", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/string.js b/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/string.js new file mode 100644 index 000000000000..c661addffd18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/toStringTag/string.js @@ -0,0 +1,13 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-now-@@tostringtag +description: The @@toStringTag property of Temporal.Now produces the correct value in toString +features: [Symbol.toStringTag, Temporal] +---*/ + +assert.sameValue(String(Temporal.Now), "[object Temporal.Now]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/browser.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-function.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-function.js new file mode 100644 index 000000000000..63e14bf13a21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-function.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Behavior when provided calendar value is a function +includes: [compareArray.js] +features: [BigInt, Proxy, Temporal] +---*/ +const actual = []; + +const expected = [ + 'has timeZone.timeZone' +]; + +const calendar = function() {}; + +const timeZone = new Proxy({ + getOffsetNanosecondsFor(instant) { + actual.push('call timeZone.getOffsetNanosecondsFor'); + return -Number(instant.epochNanoseconds % 86400000000000n); + } +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + } +}); + +Object.defineProperty(Temporal.Calendar, 'from', { + get() { + actual.push('get Temporal.Calendar.from'); + return undefined; + } +}); + +const result = Temporal.Now.zonedDateTime(calendar, timeZone); + +assert.compareArray(actual, expected, 'The value of actual is expected to equal the value of expected'); + +for (const property of ['hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond']) { + assert.sameValue(result[property], 0, 'The value of result[property] is expected to be 0'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-call-tostring.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-call-tostring.js new file mode 100644 index 000000000000..1e0adc0f04db --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-call-tostring.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Forwards error thrown by invoking "toString" property +features: [Temporal] +---*/ + +var calendar = { + calendar: { + calendar: true, + toString: function() { + throw new Test262Error(); + }, + } +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTime(calendar); +}, 'Temporal.Now.zonedDateTime(calendar) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-get-calendar.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-get-calendar.js new file mode 100644 index 000000000000..8ca9d933f3b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-get-calendar.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Forwards error thrown by retrieving value of "calendar" property +features: [Temporal] +---*/ + +var calendar = { + get calendar() { + throw new Test262Error(); + }, +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTime(calendar); +}, 'Temporal.Now.zonedDateTime(calendar) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-has-calendar.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-has-calendar.js new file mode 100644 index 000000000000..5ea6f9e942bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-has-calendar.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: Forwards error thrown by checking presence of "calendar" property +features: [Proxy, Temporal] +---*/ + +var calendar = new Proxy({}, { + has: function(target, property) { + if (property === 'calendar') { + throw new Test262Error(); + } + }, +}); + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTime(calendar); +}, 'Temporal.Now.zonedDateTime(calendar) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-has-nested-calendar.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-has-nested-calendar.js new file mode 100644 index 000000000000..f6e7c8396335 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object-fail-has-nested-calendar.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Forwards error thrown by checking presence of nested "calendar" property +features: [Proxy, Temporal] +---*/ + +var calendar = { + calendar: new Proxy({}, { + has: function(target, property) { + if (property === 'calendar') { + throw new Test262Error(); + } + }, + }) +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTime(calendar); +}, 'Temporal.Now.zonedDateTime(calendar) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object.js new file mode 100644 index 000000000000..ce66947b55ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-object.js @@ -0,0 +1,76 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: Observable interactions with the provided calendar-like object +includes: [compareArray.js] +features: [Proxy, Temporal] +---*/ + +const actual = []; +const expectedWithout = [ + 'has calendar.calendar', + 'get calendar.calendar', + 'has nestedCalendar.calendar' +]; +const expectedWith = [ + 'has calendar.calendar', + 'get calendar.calendar', + 'has nestedCalendar.calendar', + 'get nestedCalendar.Symbol(Symbol.toPrimitive)', + 'get nestedCalendar.toString', + 'call nestedCalendar.toString' +]; +const nestedCalendar = new Proxy({ + toString: function() { + actual.push('call nestedCalendar.toString'); + return 'iso8601'; + } +}, { + has(target, property) { + actual.push(`has nestedCalendar.${String(property)}`); + return property in target; + }, + get(target, property) { + actual.push(`get nestedCalendar.${String(property)}`); + return target[property]; + }, +}); +const calendar = new Proxy({ + calendar: nestedCalendar, + toString: function() { + actual.push('call calendar.toString'); + return 'iso8601'; + }, +}, { + has(target, property) { + actual.push(`has calendar.${String(property)}`); + return property in target; + }, + get(target, property) { + actual.push(`get calendar.${String(property)}`); + return target[property]; + }, +}); + +Object.defineProperty(Temporal.Calendar, 'from', { + get() { + actual.push('get Temporal.Calendar.from'); + return undefined; + }, +}); + +Temporal.Now.zonedDateTime(calendar); + +assert.compareArray(actual, expectedWithout, 'Observable interactions without `calendar` property'); + +actual.length = 0; +nestedCalendar.calendar = null; + +Temporal.Now.zonedDateTime(calendar); + +assert.compareArray(actual, expectedWith, 'Observable interactions with `calendar` property'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-temporal-object.js new file mode 100644 index 000000000000..6fba42ec4db2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-temporal-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.now.zoneddatetime step 1: + 1. Return ? SystemZonedDateTime(_temporalTimeZoneLike_, _calendar_). + sec-temporal-systemzoneddatetime step 3: + 3. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = Temporal.Now.zonedDateTime(temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-undefined.js new file mode 100644 index 000000000000..63a693c4c100 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/calendar-undefined.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: Throws when the calendar argument is undefined +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.Now.zonedDateTime(), "implicit"); +assert.throws(RangeError, () => Temporal.Now.zonedDateTime(undefined), "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/extensible.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/extensible.js new file mode 100644 index 000000000000..ef0fab085dc4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/extensible.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Temporal.Now.zonedDateTime is extensible. +features: [Temporal] +---*/ + +assert( + Object.isExtensible(Temporal.Now.zonedDateTime), + 'Object.isExtensible(Temporal.Now.zonedDateTime) must return true' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/length.js new file mode 100644 index 000000000000..cc53b524b897 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: The `length` property of Temporal.Now.zonedDateTime +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Now.zonedDateTime, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/name.js new file mode 100644 index 000000000000..a703b6878ee3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/name.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Temporal.Now.zonedDateTime.name is "zonedDateTime". +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + Temporal.Now.zonedDateTime.name, + 'zonedDateTime', + 'The value of Temporal.Now.zonedDateTime.name is expected to be "zonedDateTime"' +); + +verifyProperty(Temporal.Now.zonedDateTime, 'name', { + enumerable: false, + writable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/not-a-constructor.js new file mode 100644 index 000000000000..e286870238ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/not-a-constructor.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Temporal.Now.zonedDateTime does not implement [[Construct]] +includes: [isConstructor.js] +features: [Reflect.construct, Temporal, arrow-function] +---*/ + +assert.sameValue(isConstructor(Temporal.Now.zonedDateTime), false, 'isConstructor(Temporal.Now.zonedDateTime) must return false'); + +assert.throws(TypeError, () => { + new Temporal.Now.zonedDateTime(); +}, 'new Temporal.Now.zonedDateTime() throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/prop-desc.js new file mode 100644 index 000000000000..33f41eb2d3b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: The "zonedDateTime" property of Temporal.Now +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Now.zonedDateTime, "function", "typeof is function"); + +verifyProperty(Temporal.Now, 'zonedDateTime', { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/time-zone-undefined.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/time-zone-undefined.js new file mode 100644 index 000000000000..883df3c0292a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/time-zone-undefined.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: Functions when time zone argument is omitted +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = []; + +Object.defineProperty(Temporal.TimeZone, "from", { + get() { + actual.push("get Temporal.TimeZone.from"); + return undefined; + }, +}); + +const systemTimeZone = Temporal.Now.timeZone(); + +const resultExplicit = Temporal.Now.zonedDateTime('iso8601', undefined); +assert.sameValue(resultExplicit.timeZone.id, systemTimeZone.id); + +assert.compareArray(actual, expected, "Temporal.TimeZone.from should not be called"); + +const resultImplicit = Temporal.Now.zonedDateTime('iso8601'); +assert.sameValue(resultImplicit.timeZone.id, systemTimeZone.id); + +assert.compareArray(actual, expected, "Temporal.TimeZone.from should not be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-call-tostring.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-call-tostring.js new file mode 100644 index 000000000000..b9f08093c8a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-call-tostring.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Forwards error thrown by invoking "toString" property +features: [Temporal] +---*/ + +var timeZone = { + timeZone: { + timeZone: true, + toString: function() { + throw new Test262Error(); + }, + } +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTime("iso8601", timeZone); +}, 'Temporal.Now.zonedDateTime("iso8601", timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-get-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-get-timezone.js new file mode 100644 index 000000000000..91297d44fe4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-get-timezone.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Forwards error thrown by retrieving value of "timeZone" property +features: [Temporal] +---*/ + +var timeZone = { + get timeZone() { + throw new Test262Error(); + }, +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTime("iso8601", timeZone); +}, 'Temporal.Now.zonedDateTime("iso8601", timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-has-nested-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-has-nested-timezone.js new file mode 100644 index 000000000000..3383fa0dde9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-has-nested-timezone.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Forwards error thrown by checking presence of nested "timeZone" property +features: [Proxy, Temporal] +---*/ + +var timeZone = { + timeZone: new Proxy({}, { + has: function(target, property) { + if (property === 'timeZone') { + throw new Test262Error(); + } + }, + }) +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTime("iso8601", timeZone); +}, 'Temporal.Now.zonedDateTime("iso8601", timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-has-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-has-timezone.js new file mode 100644 index 000000000000..d135da4272c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object-fail-has-timezone.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Forwards error thrown by checking presence of "timeZone" property +features: [Proxy, Temporal] +---*/ + +var timeZone = new Proxy({}, { + has: function(target, property) { + if (property === 'timeZone') { + throw new Test262Error(); + } + }, +}); + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTime("iso8601", timeZone); +}, 'Temporal.Now.zonedDateTime("iso8601", timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object.js new file mode 100644 index 000000000000..48b5f0b17299 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-object.js @@ -0,0 +1,78 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Observable interactions with the provided timezone-like object +includes: [compareArray.js] +features: [BigInt, Proxy, Temporal] +---*/ +const actual = []; + +const expected = [ + 'has timeZone.timeZone', + 'get timeZone.timeZone', + 'has nestedTimeZone.timeZone' +]; + +const nestedTimeZone = new Proxy({ + getOffsetNanosecondsFor(instant) { + actual.push('call nestedTimeZone.getOffsetNanosecondsFor'); + + assert.sameValue( + instant instanceof Temporal.Instant, + true, + 'The result of evaluating (instant instanceof Temporal.Instant) is expected to be true' + ); + + return -Number(instant.epochNanoseconds % 86400000000000n); + } +}, { + has(target, property) { + actual.push(`has nestedTimeZone.${String(property)}`); + return property in target; + }, + + get(target, property) { + actual.push(`get nestedTimeZone.${String(property)}`); + return target[property]; + } +}); + +const timeZone = new Proxy({ + timeZone: nestedTimeZone, + + getOffsetNanosecondsFor(instant) { + actual.push('call timeZone.getOffsetNanosecondsFor'); + + assert.sameValue( + instant instanceof Temporal.Instant, + true, + 'The result of evaluating (instant instanceof Temporal.Instant) is expected to be true' + ); + + return -Number(instant.epochNanoseconds % 86400000000000n); + } +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + } +}); + +Object.defineProperty(Temporal.TimeZone, 'from', { + get() { + actual.push('get Temporal.TimeZone.from'); + return undefined; + } +}); + +Temporal.Now.zonedDateTime('iso8601', timeZone); +assert.compareArray(actual, expected, 'The value of actual is expected to equal the value of expected'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..02420ec2d772 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-string-datetime.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Now.zonedDateTime("iso8601", timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Now.zonedDateTime("iso8601", { timeZone }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..7864d72556d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTime/timezone-string-multiple-offsets.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/browser.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/extensible.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/extensible.js new file mode 100644 index 000000000000..ca39070bea4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/extensible.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Temporal.Now.zonedDateTimeISO is extensible. +features: [Temporal] +---*/ + +assert( + Object.isExtensible(Temporal.Now.zonedDateTimeISO), + 'Object.isExtensible(Temporal.Now.zonedDateTimeISO) must return true' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/length.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/length.js new file mode 100644 index 000000000000..1d50c5801ca3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: The `length` property of Temporal.Now.zonedDateTimeISO +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Now.zonedDateTimeISO, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/name.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/name.js new file mode 100644 index 000000000000..90f3f90c0c43 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/name.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Temporal.Now.zonedDateTimeISO.name is "zonedDateTimeISO". +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + Temporal.Now.zonedDateTimeISO.name, + 'zonedDateTimeISO', + 'The value of Temporal.Now.zonedDateTimeISO.name is expected to be "zonedDateTimeISO"' +); + +verifyProperty(Temporal.Now.zonedDateTimeISO, 'name', { + enumerable: false, + writable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/not-a-constructor.js new file mode 100644 index 000000000000..c9a92e6f8480 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/not-a-constructor.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Temporal.Now.zonedDateTimeISO does not implement [[Construct]] +includes: [isConstructor.js] +features: [Reflect.construct, Temporal, arrow-function] +---*/ + +assert.sameValue(isConstructor(Temporal.Now.zonedDateTimeISO), false, 'isConstructor(Temporal.Now.zonedDateTimeISO) must return false'); + +assert.throws(TypeError, () => { + new Temporal.Now.zonedDateTimeISO(); +}, 'new Temporal.Now.zonedDateTimeISO() throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/prop-desc.js new file mode 100644 index 000000000000..2ef3a9b056a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: The "zonedDateTimeISO" property of Temporal.Now +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Now.zonedDateTimeISO, "function", "typeof is function"); + +verifyProperty(Temporal.Now, 'zonedDateTimeISO', { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/return-value.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/return-value.js new file mode 100644 index 000000000000..46231d35ad69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/return-value.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Functions when time zone argument is omitted +features: [Temporal] +---*/ + +const zdt = Temporal.Now.zonedDateTimeISO(); +const tz = Temporal.Now.timeZone(); +assert(zdt instanceof Temporal.ZonedDateTime); +assert(zdt.calendar instanceof Temporal.Calendar); +assert.sameValue(zdt.calendar.id, "iso8601"); +assert(zdt.timeZone instanceof Temporal.TimeZone); +assert.sameValue(zdt.timeZone.id, tz.id); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/shell.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/time-zone-undefined.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/time-zone-undefined.js new file mode 100644 index 000000000000..0d120726d624 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/time-zone-undefined.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Functions when time zone argument is omitted +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = []; + +Object.defineProperty(Temporal.TimeZone, "from", { + get() { + actual.push("get Temporal.TimeZone.from"); + return undefined; + }, +}); + +const systemTimeZone = Temporal.Now.timeZone(); + +const resultExplicit = Temporal.Now.zonedDateTimeISO(undefined); +assert.sameValue(resultExplicit.timeZone.id, systemTimeZone.id); + +assert.compareArray(actual, expected, "Temporal.TimeZone.from should not be called"); + +const resultImplicit = Temporal.Now.zonedDateTimeISO(); +assert.sameValue(resultImplicit.timeZone.id, systemTimeZone.id); + +assert.compareArray(actual, expected, "Temporal.TimeZone.from should not be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-call-tostring.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-call-tostring.js new file mode 100644 index 000000000000..4162cf8b014e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-call-tostring.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Forwards error thrown by invoking "toString" property +features: [Temporal] +---*/ + +var timeZone = { + timeZone: { + timeZone: true, + toString: function() { + throw new Test262Error(); + }, + } +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTimeISO(timeZone); +}, 'Temporal.Now.zonedDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-get-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-get-timezone.js new file mode 100644 index 000000000000..77bbe0a758e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-get-timezone.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Forwards error thrown by retrieving value of "timeZone" property +features: [Temporal] +---*/ + +var timeZone = { + get timeZone() { + throw new Test262Error(); + }, +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTimeISO(timeZone); +}, 'Temporal.Now.zonedDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-has-nested-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-has-nested-timezone.js new file mode 100644 index 000000000000..17693c8cf7cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-has-nested-timezone.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Forwards error thrown by checking presence of nested "timeZone" property +features: [Proxy, Temporal] +---*/ + +var timeZone = { + timeZone: new Proxy({}, { + has: function(target, property) { + if (property === 'timeZone') { + throw new Test262Error(); + } + }, + }) +}; + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTimeISO(timeZone); +}, 'Temporal.Now.zonedDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-has-timezone.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-has-timezone.js new file mode 100644 index 000000000000..88d1bf5fc4f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object-fail-has-timezone.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Forwards error thrown by checking presence of "timeZone" property +features: [Proxy, Temporal] +---*/ + +var timeZone = new Proxy({}, { + has: function(target, property) { + if (property === 'timeZone') { + throw new Test262Error(); + } + }, +}); + +assert.throws(Test262Error, function() { + Temporal.Now.zonedDateTimeISO(timeZone); +}, 'Temporal.Now.zonedDateTimeISO(timeZone) throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object.js new file mode 100644 index 000000000000..9524d8d31865 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object.js @@ -0,0 +1,78 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.zoneddatetime +description: Observable interactions with the provided timezone-like object +includes: [compareArray.js] +features: [BigInt, Proxy, Temporal] +---*/ +const actual = []; + +const expected = [ + 'has timeZone.timeZone', + 'get timeZone.timeZone', + 'has nestedTimeZone.timeZone' +]; + +const nestedTimeZone = new Proxy({ + getOffsetNanosecondsFor(instant) { + actual.push('call nestedTimeZone.getOffsetNanosecondsFor'); + + assert.sameValue( + instant instanceof Temporal.Instant, + true, + 'The result of evaluating (instant instanceof Temporal.Instant) is expected to be true' + ); + + return -Number(instant.epochNanoseconds % 86400000000000n); + } +}, { + has(target, property) { + actual.push(`has nestedTimeZone.${String(property)}`); + return property in target; + }, + + get(target, property) { + actual.push(`get nestedTimeZone.${String(property)}`); + return target[property]; + } +}); + +const timeZone = new Proxy({ + timeZone: nestedTimeZone, + + getOffsetNanosecondsFor(instant) { + actual.push('call timeZone.getOffsetNanosecondsFor'); + + assert.sameValue( + instant instanceof Temporal.Instant, + true, + 'The result of evaluating (instant instanceof Temporal.Instant) is expected to be true' + ); + + return -Number(instant.epochNanoseconds % 86400000000000n); + } +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + } +}); + +Object.defineProperty(Temporal.TimeZone, 'from', { + get() { + actual.push('get Temporal.TimeZone.from'); + return undefined; + } +}); + +Temporal.Now.zonedDateTimeISO(timeZone); +assert.compareArray(actual, expected, 'The value of actual is expected to equal the value of expected'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-string-datetime.js new file mode 100644 index 000000000000..ffb2dc3d0db3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-string-datetime.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Now.zonedDateTimeISO(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Now.zonedDateTimeISO({ timeZone }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..4c7cac55ff42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Now/zonedDateTimeISO/timezone-string-multiple-offsets.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/basic.js new file mode 100644 index 000000000000..bacbc7f8b095 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/basic.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: Basic tests for the PlainDate constructor. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +Object.defineProperty(Temporal.Calendar, "from", { + get() { + throw new Test262Error("Should not get Calendar.from"); + }, +}); + +const calendar = new Temporal.Calendar("iso8601"); +const plainDateWithObject = new Temporal.PlainDate(2020, 12, 24, calendar); +TemporalHelpers.assertPlainDate(plainDateWithObject, 2020, 12, "M12", 24, "with object"); +assert.sameValue(plainDateWithObject.calendar, calendar); + +const plainDateWithString = new Temporal.PlainDate(2020, 12, 24, "iso8601"); +TemporalHelpers.assertPlainDate(plainDateWithString, 2020, 12, "M12", 24, "with string"); +assert.sameValue(plainDateWithString.calendar.toString(), "iso8601"); +assert.notSameValue(plainDateWithString.calendar, calendar); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/builtin.js new file mode 100644 index 000000000000..94552d3d5f9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: Tests that Temporal.PlainDate meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.PlainDate.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/calendar-temporal-object.js new file mode 100644 index 000000000000..710e9bebef5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/calendar-temporal-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate step 5: + 5. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = new Temporal.PlainDate(2000, 5, 2, temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/calendar-undefined.js new file mode 100644 index 000000000000..22b6d93c5d2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/calendar-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: Calendar argument defaults to the built-in ISO 8601 calendar +features: [Temporal] +---*/ + +const args = [2020, 12, 24]; + +Object.defineProperty(Temporal.Calendar, "from", { + get() { + throw new Test262Error("Should not get Calendar.from"); + }, +}); + +const dateExplicit = new Temporal.PlainDate(...args, undefined); +assert.sameValue(dateExplicit.calendar.toString(), "iso8601"); + +const dateImplicit = new Temporal.PlainDate(...args); +assert.sameValue(dateImplicit.calendar.toString(), "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-object.js new file mode 100644 index 000000000000..14f4da70c109 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: basic object coercion in arguments +features: [Temporal] +---*/ + +const d1 = Temporal.PlainDate.from("1976-11-18"); +const d2 = Temporal.PlainDate.from("2019-06-30"); + +assert.sameValue(Temporal.PlainDate.compare({ year: 1976, month: 11, day: 18 }, d2), -1, "first argument"); +assert.sameValue(Temporal.PlainDate.compare({ year: 2019, month: 6, day: 30 }, d2), 0, "first argument"); +assert.sameValue(Temporal.PlainDate.compare({ year: 2024, month: 1, day: 12 }, d2), 1, "first argument"); + +assert.sameValue(Temporal.PlainDate.compare(d1, { year: 2024, month: 1, day: 12 }), -1, "second argument"); +assert.sameValue(Temporal.PlainDate.compare(d1, { year: 1976, month: 11, day: 18 }), 0, "second argument"); +assert.sameValue(Temporal.PlainDate.compare(d1, { year: 1926, month: 7, day: 7 }), 1, "second argument"); + +assert.throws(TypeError, () => Temporal.PlainDate.compare({ year: 1976 }, d2), "only year in first argument"); +assert.throws(TypeError, () => Temporal.PlainDate.compare(d1, { year: 2019 }), "only year in second argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-plaindatetime.js new file mode 100644 index 000000000000..e0609f3a4a01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-plaindatetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaindate.compare steps 1–2: + 1. Set _one_ to ? ToTemporalDate(_one_). + 2. Set _two_ to ? ToTemporalDate(_two_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const result = Temporal.PlainDate.compare(datetime, date); + assert.sameValue(result, 0, "comparison result"); +}); + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const result = Temporal.PlainDate.compare(date, datetime); + assert.sameValue(result, 0, "comparison result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js new file mode 100644 index 000000000000..fa556961550e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js @@ -0,0 +1,69 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a %%%conversion_target%%% +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const other = new Temporal.PlainDate(2020, 1, 1); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => Temporal.PlainDate.compare(arg, other), + `"${arg}" should not be a valid ISO string for a PlainDate (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainDate.compare(other, arg), + `"${arg}" should not be a valid ISO string for a PlainDate (second argument)` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..9ac0db498a66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string-with-utc-designator.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const plainDate = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainDate.compare(arg, plainDate), + "String with UTC designator should not be valid as a PlainDate (first argument)" + ); + assert.throws( + RangeError, + () => Temporal.PlainDate.compare(plainDate, arg), + "String with UTC designator should not be valid as a PlainDate (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string.js new file mode 100644 index 000000000000..14161b3d014c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-string.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: basic string coercion in arguments +features: [Temporal] +---*/ + +const d1 = Temporal.PlainDate.from("1976-11-18"); +const d2 = Temporal.PlainDate.from("2019-06-30"); + +assert.sameValue(Temporal.PlainDate.compare("1976-11-18", d2), -1, "first argument"); +assert.sameValue(Temporal.PlainDate.compare("2019-06-30", d2), 0, "first argument"); +assert.sameValue(Temporal.PlainDate.compare("2024-01-12", d2), 1, "first argument"); + +assert.sameValue(Temporal.PlainDate.compare(d1, "2019-06-30"), -1, "second argument"); +assert.sameValue(Temporal.PlainDate.compare(d1, "1976-11-18"), 0, "second argument"); +assert.sameValue(Temporal.PlainDate.compare(d1, "1926-07-07"), 1, "second argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..33f167bcc227 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, Infinity, -Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const date = new Temporal.PlainDate(2000, 5, 2); + + assert.throws(RangeError, () => Temporal.PlainDate.compare(datetime, date)); + assert.throws(RangeError, () => Temporal.PlainDate.compare(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..aa2f0fae0168 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const date = new Temporal.PlainDate(2000, 5, 2); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.PlainDate.compare(datetime, date), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); + assert.throws( + TypeError, + () => Temporal.PlainDate.compare(date, datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..881c14393975 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const date = new Temporal.PlainDate(2000, 5, 2); + + assert.throws(RangeError, () => Temporal.PlainDate.compare(datetime, date)); + assert.throws(RangeError, () => Temporal.PlainDate.compare(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..9691d512cb2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const date = new Temporal.PlainDate(2000, 5, 2); + + assert.throws(TypeError, () => Temporal.PlainDate.compare(datetime, date)); + assert.throws(TypeError, () => Temporal.PlainDate.compare(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/basic.js new file mode 100644 index 000000000000..0547f06fa5b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: basic tests +features: [Temporal] +---*/ + +const d1 = Temporal.PlainDate.from("1976-11-18"); +const d2 = Temporal.PlainDate.from("2019-06-30"); +const d3 = Temporal.PlainDate.from("2019-06-30"); +assert.sameValue(Temporal.PlainDate.compare(d1, d1), 0, "same object"); +assert.sameValue(Temporal.PlainDate.compare(d1, d2), -1, "earlier"); +assert.sameValue(Temporal.PlainDate.compare(d2, d1), 1, "later"); +assert.sameValue(Temporal.PlainDate.compare(d2, d3), 0, "same date"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/builtin.js new file mode 100644 index 000000000000..803e72845eda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: Tests that Temporal.PlainDate.compare meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.compare), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.compare), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.compare), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.compare.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..ea857260f83c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.compare +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +Temporal.PlainDate.compare({ year: 2000, month: 5, day: 2, calendar }, { year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-fields-iterable.js new file mode 100644 index 000000000000..ceefa7fdc24a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-fields-iterable.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.compare steps 1–2: + 1. Set _one_ to ? ToTemporalDate(_one_). + 2. Set _two_ to ? ToTemporalDate(_two_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +Temporal.PlainDate.compare( + { year: 2000, month: 5, day: 2, calendar: calendar1 }, + { year: 2001, month: 6, day: 3, calendar: calendar2 }, +); + +assert.sameValue(calendar1.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar1.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar1.iteratorExhausted[0], "iterated through the whole iterable"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-temporal-object.js new file mode 100644 index 000000000000..5bcb4f0b0bec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar-temporal-object.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.compare steps 1–2: + 1. Set _one_ to ? ToTemporalDate(_one_). + 2. Set _two_ to ? ToTemporalDate(_two_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + Temporal.PlainDate.compare( + { year: 2000, month: 5, day: 2, calendar: temporalObject }, + { year: 2001, month: 6, day: 3, calendar: temporalObject }, + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar.js new file mode 100644 index 000000000000..d08f8755b57a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/calendar.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: basic tests +features: [Temporal] +---*/ + +class CalendarTraceToString extends Temporal.Calendar { + constructor(id) { + super("iso8601"); + this.id_ = id; + this.calls = 0; + } + toString() { + ++this.calls; + return this.id_; + } +}; + +const calendar1 = new CalendarTraceToString("a"); +const date1 = new Temporal.PlainDate(1914, 2, 23, calendar1); + +const calendar2 = new CalendarTraceToString("a"); +const date2 = new Temporal.PlainDate(1914, 2, 23, calendar2); + +const calendar3 = new CalendarTraceToString("b"); +const date3 = new Temporal.PlainDate(1914, 2, 23, calendar3); + +assert.sameValue(Temporal.PlainDate.compare(date1, date1), 0, "same object"); +assert.sameValue(Temporal.PlainDate.compare(date1, date2), 0, "same date"); +assert.sameValue(Temporal.PlainDate.compare(date1, date3), 0, "same date, different calendar"); + +assert.sameValue(calendar1.calls, 0, "calendar1 toString() calls"); +assert.sameValue(calendar2.calls, 0, "calendar2 toString() calls"); +assert.sameValue(calendar3.calls, 0, "calendar3 toString() calls"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..a458c0800260 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.plaindate.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const other = new Temporal.PlainDate(2000, 5, 2); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => Temporal.PlainDate.compare({ ...base, [prop]: inf }, other), `${prop} property cannot be ${inf}`); + + assert.throws(RangeError, () => Temporal.PlainDate.compare(other, { ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, prop); + assert.throws(RangeError, () => Temporal.PlainDate.compare({ ...base, [prop]: obj1 }, other)); + assert.compareArray(calls1, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, prop); + assert.throws(RangeError, () => Temporal.PlainDate.compare(other, { ...base, [prop]: obj2 })); + assert.compareArray(calls2, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/length.js new file mode 100644 index 000000000000..2602c422e569 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: Temporal.PlainDate.compare.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.compare, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/name.js new file mode 100644 index 000000000000..d7bb9ddb63c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: Temporal.PlainDate.compare.name is "compare" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.compare, "name", { + value: "compare", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/not-a-constructor.js new file mode 100644 index 000000000000..8624c67432db --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: Temporal.PlainDate.compare does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.compare(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.compare), false, + "isConstructor(Temporal.PlainDate.compare)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/prop-desc.js new file mode 100644 index 000000000000..08b855ea282d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: The "compare" property of Temporal.PlainDate +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.compare, + "function", + "`typeof PlainDate.compare` is `function`" +); + +verifyProperty(Temporal.PlainDate, "compare", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/use-internal-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/use-internal-slots.js new file mode 100644 index 000000000000..0611e7bc24e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/use-internal-slots.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-compareisodate +description: compare() ignores the observable properties and uses internal slots +features: [Temporal] +---*/ + +function CustomError() {} + +class AvoidGettersDate extends Temporal.PlainDate { + get year() { + throw new CustomError(); + } + get month() { + throw new CustomError(); + } + get day() { + throw new CustomError(); + } +} + +const one = new AvoidGettersDate(2000, 5, 2); +const two = new AvoidGettersDate(2006, 3, 25); +assert.sameValue(Temporal.PlainDate.compare(one, two), -1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/year-zero.js new file mode 100644 index 000000000000..864f12679de8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/compare/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Negative zero, as an extended year, fails +esid: sec-temporal.plaindate.compare +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const bad = "-000000-08-24"; + +assert.throws(RangeError, + () => Temporal.PlainDate.compare(bad, instance), + "Minus zero is an invalid extended year (first argument)" +); + +assert.throws(RangeError, + () => Temporal.PlainDate.compare(instance, bad), + "Minus zero is an invalid extended year (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/constructor.js new file mode 100644 index 000000000000..a510781c6efb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: Temporal.PlainDate constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.PlainDate()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-number.js new file mode 100644 index 000000000000..50f5a7420018 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-number.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: various interesting string arguments. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const result = Temporal.PlainDate.from(19761118); +TemporalHelpers.assertPlainDate(result, 1976, 11, "M11", 18); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-object-invalid.js new file mode 100644 index 000000000000..af0eaf1173bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-object-invalid.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Property bag is correctly converted into PlainDate +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const badFields = { year: 2019, month: 1, day: 32 }; +assert.throws(RangeError, () => Temporal.PlainDate.from(badFields, { overflow: "reject" }), + "bad fields with reject"); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from(badFields), + 2019, 1, "M01", 31, "bad fields with missing overflow"); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from(badFields, { overflow: "constrain" }), + 2019, 1, "M01", 31, "bad fields with constrain"); + +assert.throws(RangeError, + () => Temporal.PlainDate.from({ year: 1976, month: 11, monthCode: "M12", day: 18 }), + "month and monthCode must agree"); + +assert.throws(TypeError, + () => Temporal.PlainDate.from({ year: 2019, day: 15 }), + "missing month"); + +assert.throws(TypeError, + () => Temporal.PlainDate.from({}), + "no properties"); + +assert.throws(TypeError, + () => Temporal.PlainDate.from({ month: 12 }), + "missing year, day"); + +assert.throws(TypeError, + () => Temporal.PlainDate.from({ year: 1976, months: 11, day: 18 }), + "misspelled month"); + +assert.throws(TypeError, + () => Temporal.PlainDate.from({ year: undefined, month: 11, day: 18 }), + "year undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-object-valid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-object-valid.js new file mode 100644 index 000000000000..f718a0de8ee6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-object-valid.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Property bag is correctly converted into PlainDate +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const valid = [ + [ + { year: 2019, month: 10, monthCode: "M10", day: 1, hour: 14, minute: 20, second: 36 }, + 2019, 10, "M10", 1 + ], + [ + { year: 1976, month: 11, day: 18 }, + 1976, 11, "M11", 18 + ], + [ + { year: 1976, monthCode: "M11", day: 18 }, + 1976, 11, "M11", 18 + ], + [ + { year: 1976, month: 11, day: 18, days: 15 }, + 1976, 11, "M11", 18 + ], +]; + +for (const [dateTimeFields, ...expected] of valid) { + const plainDate = Temporal.PlainDate.from(dateTimeFields); + TemporalHelpers.assertPlainDate(plainDate, ...expected, `from(${JSON.stringify(dateTimeFields)}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-plaindate.js new file mode 100644 index 000000000000..d04a718f7568 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-plaindate.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: A PlainDate object is copied, not returned directly +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(2000, 5, 2); +const result = Temporal.PlainDate.from(plainDate); +assert.notSameValue(result, plainDate); +TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-plaindatetime.js new file mode 100644 index 000000000000..c745bf4bb40e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-plaindatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaindate.from step 3: + 3. Return ? ToTemporalDate(_item_, _options_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime, calendar) => { + const result = Temporal.PlainDate.from(datetime); + TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2); + assert.sameValue(result.calendar, calendar, "calendar result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-invalid.js new file mode 100644 index 000000000000..6f6c69d13cb3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-invalid.js @@ -0,0 +1,63 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => Temporal.PlainDate.from(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-trailing-junk.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-trailing-junk.js new file mode 100644 index 000000000000..8888b509dae1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-trailing-junk.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: RangeError thrown if a string with trailing junk is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +assert.throws(RangeError, () => Temporal.PlainDate.from("1976-11-18junk"), + "String with trailing junk should not be valid as a PlainDate"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..400bc24cb685 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string-with-utc-designator.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainDate.from(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string.js new file mode 100644 index 000000000000..991fd4149211 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-string.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: various interesting string arguments. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const tests = [ + ["1976-11-18", 1976, 11, "M11", 18], + ["2019-06-30", 2019, 6, "M06", 30], + ["+000050-06-30", 50, 6, "M06", 30], + ["+010583-06-30", 10583, 6, "M06", 30], + ["-010583-06-30", -10583, 6, "M06", 30], + ["-000333-06-30", -333, 6, "M06", 30], + ["19761118", 1976, 11, "M11", 18], + ["+0019761118", 1976, 11, "M11", 18], + ["1976-11-18T152330.1+00:00", 1976, 11, "M11", 18], + ["19761118T15:23:30.1+00:00", 1976, 11, "M11", 18], + ["1976-11-18T15:23:30.1+0000", 1976, 11, "M11", 18], + ["1976-11-18T152330.1+0000", 1976, 11, "M11", 18], + ["19761118T15:23:30.1+0000", 1976, 11, "M11", 18], + ["19761118T152330.1+00:00", 1976, 11, "M11", 18], + ["19761118T152330.1+0000", 1976, 11, "M11", 18], + ["+001976-11-18T152330.1+00:00", 1976, 11, "M11", 18], + ["+0019761118T15:23:30.1+00:00", 1976, 11, "M11", 18], + ["+001976-11-18T15:23:30.1+0000", 1976, 11, "M11", 18], + ["+001976-11-18T152330.1+0000", 1976, 11, "M11", 18], + ["+0019761118T15:23:30.1+0000", 1976, 11, "M11", 18], + ["+0019761118T152330.1+00:00", 1976, 11, "M11", 18], + ["+0019761118T152330.1+0000", 1976, 11, "M11", 18], + ["2020-01-01[Asia/Kolkata]", 2020, 1, "M01", 1], +]; + +for (const [input, ...expected] of tests) { + const result = Temporal.PlainDate.from(input); + TemporalHelpers.assertPlainDate(result, ...expected, `from(${input})`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..af8e64bb6108 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => Temporal.PlainDate.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..a0f047b1ab6a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaindate.from +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.PlainDate.from(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..1a902c3a4756 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => Temporal.PlainDate.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..94ccb98994aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => Temporal.PlainDate.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/builtin.js new file mode 100644 index 000000000000..33958220b465 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Tests that Temporal.PlainDate.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/calendar-fields-iterable.js new file mode 100644 index 000000000000..709082b323f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/calendar-fields-iterable.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.from step 3: + 3. Return ? ToTemporalDate(_item_, _options_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +Temporal.PlainDate.from({ year: 2000, month: 5, day: 2, calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/calendar-temporal-object.js new file mode 100644 index 000000000000..2adbaad3f588 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.from step 3: + 3. Return ? ToTemporalDate(_item_, _options_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2, calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..3377d9ee9699 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainDate.from({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => Temporal.PlainDate.from({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/length.js new file mode 100644 index 000000000000..2cf8d0aa4937 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Temporal.PlainDate.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/limits.js new file mode 100644 index 000000000000..89c90bdfddd2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/limits.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: PlainDate.from enforces the supported range +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const tooEarly = { year: -271821, month: 4, day: 18 }; +const tooLate = { year: 275760, month: 9, day: 14 }; +["reject", "constrain"].forEach((overflow) => { + [tooEarly, tooLate, "-271821-04-18", "+275760-09-14"].forEach((value) => { + assert.throws(RangeError, () => Temporal.PlainDate.from(value, { overflow }), + `${JSON.stringify(value)} with ${overflow}`); + }); +}); + +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from({ year: -271821, month: 4, day: 19 }), + -271821, 4, "M04", 19, "min object"); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from({ year: 275760, month: 9, day: 13 }), + 275760, 9, "M09", 13, "max object"); + +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from("-271821-04-19"), + -271821, 4, "M04", 19, "min string"); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from("+275760-09-13"), + 275760, 9, "M09", 13, "max string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/name.js new file mode 100644 index 000000000000..237ff188470f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Temporal.PlainDate.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/not-a-constructor.js new file mode 100644 index 000000000000..e8947b9d2479 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Temporal.PlainDate.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.from), false, + "isConstructor(Temporal.PlainDate.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js new file mode 100644 index 000000000000..8ab3e4226cf6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: overflow property is extracted with ISO-invalid string argument. +info: | + 1. Perform ? ToTemporalOverflow(_options_). + + 1. If ! IsValidISODate(year, month, day) is false, throw a RangeError exception. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get overflow", + "get overflow.toString", + "call overflow.toString", +]; + +let actual = []; +const object = { + get overflow() { + actual.push("get overflow"); + return TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); + } +}; + +assert.throws(RangeError, () => Temporal.PlainDate.from("2020-13-34", object)); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string.js new file mode 100644 index 000000000000..0119387c0ae4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: overflow property is extracted with string argument. +info: | + 1. Perform ? ToTemporalOverflow(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get overflow", + "get overflow.toString", + "call overflow.toString", +]; + +let actual = []; +const object = { + get overflow() { + actual.push("get overflow"); + return TemporalHelpers.toPrimitiveObserver(actual, "reject", "overflow"); + } +}; + +const result = Temporal.PlainDate.from("2021-05-17", object); +assert.compareArray(actual, expected, "Successful call"); +TemporalHelpers.assertPlainDate(result, 2021, 5, "M05", 17); + +actual.splice(0, actual.length); // empty it for the next check +assert.throws(RangeError, () => Temporal.PlainDate.from(7, object)); +assert.compareArray(actual, expected, "Failing call"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/options-invalid.js new file mode 100644 index 000000000000..2fc5be0eb800 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/options-invalid.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const fields = { year: 2000, month: 11, day: 2 }; + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +for (const badOptions of values) { + assert.throws(TypeError, () => Temporal.PlainDate.from(fields, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/options-undefined.js new file mode 100644 index 000000000000..ed95434a74a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const fields = { year: 2000, month: 13, day: 2 }; + +const explicit = Temporal.PlainDate.from(fields, undefined); +assert.sameValue(explicit.month, 12, "default overflow is constrain"); + +const implicit = Temporal.PlainDate.from(fields); +assert.sameValue(implicit.month, 12, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/order-of-operations.js new file mode 100644 index 000000000000..3e08b01f05be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/order-of-operations.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Properties on an object passed to from() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get calendar", + "get day", + "get day.valueOf", + "call day.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; +const actual = []; +const fields = { + year: 1.7, + month: 1.7, + monthCode: "M01", + day: 1.7, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + if (key === "calendar") return Temporal.Calendar.from("iso8601"); + const result = target[key]; + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = Temporal.PlainDate.from(argument); +TemporalHelpers.assertPlainDate(result, 1, 1, "M01", 1); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js new file mode 100644 index 000000000000..31f2900ffbcc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporaldate steps 2–3: + 2. If Type(_item_) is Object, then + ... + g. Return ? DateFromFields(_calendar_, _fields_, _options_). + 3. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDate]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalDate(_item_, _options_). +features: [Temporal] +---*/ + +const validItems = [ + new Temporal.PlainDate(2000, 5, 2), + { year: 2000, month: 5, day: 2 }, + "2000-05-02", +]; +const invalidOverflow = [ + "", + "other string", + "balance", + "CONSTRAIN", + "constra\u0131n", +]; + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const item of validItems) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainDate.from(item, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-undefined.js new file mode 100644 index 000000000000..be9881c1a7a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-undefined.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporaldate steps 2–3: + 2. If Type(_item_) is Object, then + ... + g. Return ? DateFromFields(_calendar_, _fields_, _options_). + 3. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDate]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalDate(_item_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainDate(2000, 5, 2), + "2000-05-02", +]; +validValues.forEach((value) => { + const explicit = Temporal.PlainDate.from(value, { overflow: undefined }); + TemporalHelpers.assertPlainDate(explicit, 2000, 5, "M05", 2, "overflow is ignored"); + const implicit = Temporal.PlainDate.from(value, {}); + TemporalHelpers.assertPlainDate(implicit, 2000, 5, "M05", 2, "overflow is ignored"); + const lambda = Temporal.PlainDate.from(value, () => {}); + TemporalHelpers.assertPlainDate(lambda, 2000, 5, "M05", 2, "overflow is ignored"); +}); + +const propertyBag = { year: 2000, month: 13, day: 34 }; +const explicit = Temporal.PlainDate.from(propertyBag, { overflow: undefined }); +TemporalHelpers.assertPlainDate(explicit, 2000, 12, "M12", 31, "default overflow is constrain"); +const implicit = Temporal.PlainDate.from(propertyBag, {}); +TemporalHelpers.assertPlainDate(implicit, 2000, 12, "M12", 31, "default overflow is constrain"); +const lambda = Temporal.PlainDate.from(propertyBag, () => {}); +TemporalHelpers.assertPlainDate(lambda, 2000, 12, "M12", 31, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-wrong-type.js new file mode 100644 index 000000000000..b2ebcecdba7d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/overflow-wrong-type.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporaldate steps 2–3: + 2. If Type(_item_) is Object, then + ... + g. Return ? DateFromFields(_calendar_, _fields_, _options_). + 3. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDate]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalDate(_item_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainDate(2000, 5, 2), + { year: 2000, month: 5, day: 2 }, + "2000-05-02", +]; +validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => Temporal.PlainDate.from(value, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2, descr), +)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/prop-desc.js new file mode 100644 index 000000000000..64b018d2825d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: The "from" property of Temporal.PlainDate +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.from, + "function", + "`typeof PlainDate.from` is `function`" +); + +verifyProperty(Temporal.PlainDate, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/subclassing-ignored.js new file mode 100644 index 000000000000..8ae4709dc102 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/subclassing-ignored.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.PlainDate, + "from", + ["2000-05-02"], + (result) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/year-zero.js new file mode 100644 index 000000000000..6e671898cbb7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/from/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const arg = "-000000-10-31"; + +assert.throws( + RangeError, + () => { Temporal.PlainDate.from(arg); }, + "reject minus zero as extended year" +); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..2338108bfc66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/infinity-throws-rangeerror.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate throws a RangeError if any value is Infinity +esid: sec-temporal.plaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainDate(Infinity, 1, 1)); +assert.throws(RangeError, () => new Temporal.PlainDate(1970, Infinity, 1)); +assert.throws(RangeError, () => new Temporal.PlainDate(1970, 1, Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite year", + [O(Infinity, "year"), O(1, "month"), O(1, "day")], + ["get year.valueOf", "call year.valueOf"] + ], + [ + "infinite month", + [O(2, "year"), O(Infinity, "month"), O(1, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf"] + ], + [ + "infinite day", + [O(2, "year"), O(1, "month"), O(Infinity, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainDate(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/length.js new file mode 100644 index 000000000000..136b4bdbed64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: Temporal.PlainDate.length is 3 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate, "length", { + value: 3, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/limits.js new file mode 100644 index 000000000000..0cab77edc2a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/limits.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: Limits for the PlainDate constructor. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainDate(-271821, 4, 18), "min"); +assert.throws(RangeError, () => new Temporal.PlainDate(275760, 9, 14), "max"); +TemporalHelpers.assertPlainDate(new Temporal.PlainDate(-271821, 4, 19), + -271821, 4, "M04", 19, "min"); +TemporalHelpers.assertPlainDate(new Temporal.PlainDate(275760, 9, 13), + 275760, 9, "M09", 13, "max"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/missing-arguments.js new file mode 100644 index 000000000000..4e2c70781533 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/missing-arguments.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: RangeError thrown when constructor invoked with no argument +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "valueOf year", + "valueOf month", +]; +const actual = []; +const args = [ + { valueOf() { actual.push("valueOf year"); return 1; } }, + { valueOf() { actual.push("valueOf month"); return 1; } }, +]; + +assert.throws(RangeError, () => new Temporal.PlainDate(...args)); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/name.js new file mode 100644 index 000000000000..94e03edea2c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: Temporal.PlainDate.name is "PlainDate" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate, "name", { + value: "PlainDate", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..07787c67b7e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/negative-infinity-throws-rangeerror.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate throws a RangeError if any value is -Infinity +esid: sec-temporal.plaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainDate(-Infinity, 1, 1)); +assert.throws(RangeError, () => new Temporal.PlainDate(1970, -Infinity, 1)); +assert.throws(RangeError, () => new Temporal.PlainDate(1970, 1, -Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite year", + [O(-Infinity, "year"), O(1, "month"), O(1, "day")], + ["get year.valueOf", "call year.valueOf"] + ], + [ + "infinite month", + [O(2, "year"), O(-Infinity, "month"), O(1, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf"] + ], + [ + "infinite day", + [O(2, "year"), O(1, "month"), O(-Infinity, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainDate(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prop-desc.js new file mode 100644 index 000000000000..a40119b3a88d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate +description: The "PlainDate" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate, + "function", + "`typeof PlainDate` is `function`" +); + +verifyProperty(Temporal, "PlainDate", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-invalid-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-invalid-duration.js new file mode 100644 index 000000000000..dcdeaed7991e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-invalid-duration.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: RangeError thrown when signs don't match in the duration +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarThrowEverything(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = { months: 1, days: -30 }; +for (const overflow of ["constrain", "reject"]) { + assert.throws(RangeError, () => date.add(duration, { overflow })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-missing-properties.js new file mode 100644 index 000000000000..991063821bdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-missing-properties.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: TypeError for missing properties +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const options = { + get overflow() { + TemporalHelpers.assertUnreachable("should not get overflow"); + } +}; +assert.throws(TypeError, () => date.add({}, options), "empty object"); +assert.throws(TypeError, () => date.add({ month: 12 }, options), "misspelled 'months'"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-not-object.js new file mode 100644 index 000000000000..dbbe929744bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Passing a primitive other than string to add() throws +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); +assert.throws(RangeError, () => instance.add(undefined), "undefined"); +assert.throws(RangeError, () => instance.add(null), "null"); +assert.throws(RangeError, () => instance.add(true), "boolean"); +assert.throws(RangeError, () => instance.add(""), "empty string"); +assert.throws(TypeError, () => instance.add(Symbol()), "Symbol"); +assert.throws(RangeError, () => instance.add(7), "number"); +assert.throws(RangeError, () => instance.add(7n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-singular-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-singular-units.js new file mode 100644 index 000000000000..a6c47c0dc46a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-singular-units.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Ignores singular properties +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = Temporal.PlainDate.from("2019-11-18"); +TemporalHelpers.assertPlainDate(date.add({ month: 1, days: 1 }), + 2019, 11, "M11", 19); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..a8b182dc93b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +const resultHours = instance.add("-PT24.567890123H"); +TemporalHelpers.assertPlainDate(resultHours, 2000, 5, "M05", 1, "negative fractional hours"); + +const resultMinutes = instance.add("-PT1440.567890123M"); +TemporalHelpers.assertPlainDate(resultMinutes, 2000, 5, "M05", 1, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-string.js new file mode 100644 index 000000000000..4b108d33eb74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); +const result = instance.add("P3D"); +TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/balance-smaller-units-basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/balance-smaller-units-basic.js new file mode 100644 index 000000000000..89499d920116 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/balance-smaller-units-basic.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Durations with units smaller than days are balanced +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(1976, 11, 18); + +// lower units that don't balance up to a day +TemporalHelpers.assertPlainDate(date.add({ hours: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.add({ minutes: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.add({ seconds: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.add({ milliseconds: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.add({ microseconds: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.add({ nanoseconds: 1 }), 1976, 11, "M11", 18); + +// lower units that balance up to a day or more +TemporalHelpers.assertPlainDate(date.add({ hours: 24 }), 1976, 11, "M11", 19); +TemporalHelpers.assertPlainDate(date.add({ hours: 36 }), 1976, 11, "M11", 19); +TemporalHelpers.assertPlainDate(date.add({ hours: 48 }), 1976, 11, "M11", 20); +TemporalHelpers.assertPlainDate(date.add({ minutes: 1440 }), 1976, 11, "M11", 19); +TemporalHelpers.assertPlainDate(date.add({ seconds: 86400 }), 1976, 11, "M11", 19); +TemporalHelpers.assertPlainDate(date.add({ milliseconds: 86400_000 }), 1976, 11, "M11", 19); +TemporalHelpers.assertPlainDate(date.add({ microseconds: 86400_000_000 }), 1976, 11, "M11", 19); +TemporalHelpers.assertPlainDate(date.add({ nanoseconds: 86400_000_000_000 }), 1976, 11, "M11", 19); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/balance-smaller-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/balance-smaller-units.js new file mode 100644 index 000000000000..a3cfb4cafc27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/balance-smaller-units.js @@ -0,0 +1,54 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Durations with units smaller than days are balanced before adding, in the calendar +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; + +class DateAddCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateAdd(date, duration, options) { + actual.push(duration); + return super.dateAdd(date, duration, options); + } +} + +const calendar = new DateAddCalendar(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = new Temporal.Duration(0, 0, 0, 1, 24, 1440, 86400, 86400_000, 86400_000_000, 86400_000_000_000); + +const result = date.add(duration); +TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 9, "units smaller than days are balanced"); + +assert.sameValue(actual.length, 1, "calendar.dateAdd called exactly once"); +assert.sameValue(actual[0], duration, "the duration is passed directly to the calendar"); + +const resultString = date.add("P1DT24H1440M86400S"); +TemporalHelpers.assertPlainDate(resultString, 2000, 5, "M05", 6, "units smaller than days are balanced"); + +assert.sameValue(actual.length, 2, "calendar.dateAdd called exactly once"); +TemporalHelpers.assertDuration(actual[1], 0, 0, 0, 1, 24, 1440, 86400, 0, 0, 0, "the duration is not balanced before passing to the calendar"); + +const resultPropBag = date.add({ days: 1, hours: 24, minutes: 1440, seconds: 86400, milliseconds: 86400_000, microseconds: 86400_000_000, nanoseconds: 86400_000_000_000 }); +TemporalHelpers.assertPlainDate(resultPropBag, 2000, 5, "M05", 9, "units smaller than days are balanced"); + +assert.sameValue(actual.length, 3, "calendar.dateAdd called exactly once"); +TemporalHelpers.assertDuration(actual[2], 0, 0, 0, 1, 24, 1440, 86400, 86400_000, 86400_000_000, 86400_000_000_000, "the duration is not balanced before passing to the calendar"); + +const negativeDuration = new Temporal.Duration(0, 0, 0, -1, -24, -1440, -86400, -86400_000, -86400_000_000, -86400_000_000_000); +const resultNegative = date.add(negativeDuration); +TemporalHelpers.assertPlainDate(resultNegative, 2000, 4, "M04", 25, "units smaller than days are balanced"); + +assert.sameValue(actual.length, 4, "calendar.dateAdd called exactly once"); +assert.sameValue(actual[3], negativeDuration, "the duration is passed directly to the calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/basic.js new file mode 100644 index 000000000000..050610cf7910 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/basic.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Basic tests +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = Temporal.PlainDate.from("1976-11-18"); +TemporalHelpers.assertPlainDate(date.add({ years: 43 }), + 2019, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.add({ months: 3 }), + 1977, 2, "M02", 18); +TemporalHelpers.assertPlainDate(date.add({ days: 20 }), + 1976, 12, "M12", 8); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from("2019-01-31").add({ months: 1 }), + 2019, 2, "M02", 28); +TemporalHelpers.assertPlainDate(date.add(Temporal.Duration.from('P43Y')), + 2019, 11, "M11", 18); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('2019-11-18').add({ years: -43 }), + 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('1977-02-18').add({ months: -3 }), + 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('1976-12-08').add({ days: -20 }), + 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('2019-02-28').add({ months: -1 }), + 2019, 1, "M01", 28); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/builtin.js new file mode 100644 index 000000000000..cf1126931cd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: > + Tests that Temporal.PlainDate.prototype.add + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.add), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.add), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.add), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.add.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f97746eff558 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate.prototype.add throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plaindate.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/length.js new file mode 100644 index 000000000000..7934309570aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Temporal.PlainDate.prototype.add.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.add, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/limits.js new file mode 100644 index 000000000000..03ad67be7922 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/limits.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate.prototype.add throws a RangeError if the calculation crosses a limit +esid: sec-temporal.plaindate.prototype.add +features: [Temporal] +---*/ + +const min = Temporal.PlainDate.from("-271821-04-19"); +const max = Temporal.PlainDate.from("+275760-09-13"); +["reject", "constrain"].forEach((overflow) => { + assert.throws(RangeError, () => min.add({ days: -1 }, { overflow }), `min with ${overflow}`); + assert.throws(RangeError, () => max.add({ days: 1 }, { overflow }), `max with ${overflow}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/name.js new file mode 100644 index 000000000000..e0007df09911 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Temporal.PlainDate.prototype.add.name is "add". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.add, "name", { + value: "add", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..238547a34f07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate.prototype.add throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plaindate.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..af17115a397f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.add({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/not-a-constructor.js new file mode 100644 index 000000000000..46fc31efe333 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: > + Temporal.PlainDate.prototype.add does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.add(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.add), false, + "isConstructor(Temporal.PlainDate.prototype.add)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/options-invalid.js new file mode 100644 index 000000000000..59e760c40683 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/options-invalid.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(2000, 1, 31); +const duration = { months: 1 }; + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +for (const badOptions of values) { + assert.throws(TypeError, () => plainDate.add(duration, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/options-undefined.js new file mode 100644 index 000000000000..24bb0d0a15b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 1, 31); +const duration = { months: 1 }; + +const explicit = date.add(duration, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = date.add(duration); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/order-of-operations.js new file mode 100644 index 000000000000..3d8893e1c406 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Properties on an object passed to add() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.add(argument); +TemporalHelpers.assertPlainDate(result, 2001, 6, "M06", 10); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-constrain.js new file mode 100644 index 000000000000..87dcb6605bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-constrain.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Constrains with overflow constrain +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const jan31 = Temporal.PlainDate.from("2020-01-31"); +TemporalHelpers.assertPlainDate(jan31.add({ months: 1 }), + 2020, 2, "M02", 29, "implicit"); +TemporalHelpers.assertPlainDate(jan31.add({ months: 1 }, { overflow: "constrain" }), + 2020, 2, "M02", 29, "explicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js new file mode 100644 index 000000000000..7f485ac7ec85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.add step 7: + 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _balancedDuration_, _options_). +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const duration = new Temporal.Duration(3, 3, 0, 3); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-reject.js new file mode 100644 index 000000000000..32e6ca8688e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-reject.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Throws with overflow reject +features: [Temporal] +---*/ + +const jan31 = Temporal.PlainDate.from("2020-01-31"); +assert.throws(RangeError, () => jan31.add({ months: 1 }, { overflow: "reject" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-undefined.js new file mode 100644 index 000000000000..6efc335755b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-undefined.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.add step 7: + 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _balancedDuration_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 31); +const duration = new Temporal.Duration(3, 1); + +const explicit = date.add(duration, { overflow: undefined }); +TemporalHelpers.assertPlainDate(explicit, 2003, 6, "M06", 30, "default overflow is constrain"); +const implicit = date.add(duration, {}); +TemporalHelpers.assertPlainDate(implicit, 2003, 6, "M06", 30, "default overflow is constrain"); +const lambda = date.add(duration, () => {}); +TemporalHelpers.assertPlainDate(lambda, 2003, 6, "M06", 30, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-wrong-type.js new file mode 100644 index 000000000000..e27b18172f7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/overflow-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.add step 7: + 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _balancedDuration_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const duration = new Temporal.Duration(3, 3, 0, 3); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => date.add(duration, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDate(result, 2003, 8, "M08", 5, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/prop-desc.js new file mode 100644 index 000000000000..34fe702263d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: The "add" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.add, + "function", + "`typeof PlainDate.prototype.add` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "add", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/subclassing-ignored.js new file mode 100644 index 000000000000..9f9c50d7cbc2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/add/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.add +description: Objects of a subclass are never created as return values for add() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDate, + [2000, 5, 2], + "add", + [{ days: 1 }], + (result) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 3), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/calendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/calendar/prop-desc.js new file mode 100644 index 000000000000..271a36c0429c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/calendar/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.calendar +description: The "calendar" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "calendar"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/day/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/day/calendar-returns-infinity.js new file mode 100644 index 000000000000..65a098538f39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/day/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.day +description: Getter throws if the calendar returns ±∞ from its day method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + day() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainDate(2000, 5, 2, pos); +assert.throws(RangeError, () => instance1.day); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainDate(2000, 5, 2, neg); +assert.throws(RangeError, () => instance2.day); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/day/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/day/prop-desc.js new file mode 100644 index 000000000000..10cf01f27162 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/day/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.day +description: The "day" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "day"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfWeek/basic.js new file mode 100644 index 000000000000..ebe5811f6adc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfWeek/basic.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.dayofweek +description: Basic tests for dayOfWeek(). +features: [Temporal] +---*/ + +for (let i = 1; i <= 7; ++i) { + const plainDate = new Temporal.PlainDate(1976, 11, 14 + i); + assert.sameValue(plainDate.dayOfWeek, i, `${plainDate} should be on day ${i}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfWeek/prop-desc.js new file mode 100644 index 000000000000..63c89ed3c84d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfWeek/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.dayofweek +description: The "dayOfWeek" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "dayOfWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfYear/basic.js new file mode 100644 index 000000000000..e43a5731ab1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfYear/basic.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.dayofyear +description: Basic tests for dayOfYear(). +features: [Temporal] +---*/ + +for (let i = 1; i <= 7; ++i) { + const plainDate = new Temporal.PlainDate(1976, 11, 14 + i); + assert.sameValue(plainDate.dayOfYear, 319 + i, `${plainDate} should be on day ${319 + i}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfYear/prop-desc.js new file mode 100644 index 000000000000..efe62172db1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/dayOfYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.dayofyear +description: The "dayOfYear" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "dayOfYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInMonth/prop-desc.js new file mode 100644 index 000000000000..751a01521018 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInMonth/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.daysinmonth +description: The "daysInMonth" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "daysInMonth"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInWeek/basic.js new file mode 100644 index 000000000000..decc5fa9329a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInWeek/basic.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.daysinweek +description: Basic tests for daysInWeek(). +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(1976, 11, 18); +assert.sameValue(plainDate.daysInWeek, 7); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInWeek/prop-desc.js new file mode 100644 index 000000000000..624a064e2e52 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInWeek/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.daysinweek +description: The "daysInWeek" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "daysInWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInYear/prop-desc.js new file mode 100644 index 000000000000..1d5feb63f565 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/daysInYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.daysinyear +description: The "daysInYear" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "daysInYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-object-invalid.js new file mode 100644 index 000000000000..70314439c5f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-object-invalid.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: Appropriate error thrown when object argument is invalid +features: [Temporal] +---*/ + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); + +// End up in ISODateFromFields with missing fields +assert.throws(TypeError, () => instance.equals({}), "plain object"); +assert.throws(TypeError, () => instance.equals({ year: 1972, month: 7 }), "only year, month"); +assert.throws(TypeError, () => instance.equals({ year: 1972, month: 7 }), "only year, month"); +assert.throws(TypeError, () => instance.equals({ year: 1972, day: 7 }), "only year, day"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainDate), "Temporal.PlainDate"); + +// Tries to get fields with an invalid receiver +assert.throws(TypeError, () => instance.equals(Temporal.PlainDate.prototype), "Temporal.PlainDate.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-object-valid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-object-valid.js new file mode 100644 index 000000000000..d595d86bc926 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-object-valid.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: equals with a valid property bag +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +assert.sameValue(instance.equals({ year: 2000, month: 5, day: 2 }), true, "same date"); +assert.sameValue(instance.equals({ year: 2000, month: 5, day: 4 }), false, "different date"); + +const calendar = { toString() { return "a" } }; +assert.sameValue(instance.withCalendar(calendar).equals({ year: 2000, month: 5, day: 2 }), + false, "different calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-plaindatetime.js new file mode 100644 index 000000000000..04b37dc83b7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-plaindatetime.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaindate.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const date = new Temporal.PlainDate(2000, 5, 2); + assert(date.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js new file mode 100644 index 000000000000..e3cb8fbdf988 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.equals(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..74f9c79caca1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string.js new file mode 100644 index 000000000000..96f50546001c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: equals with a valid string +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +assert.sameValue(instance.equals("2000-05-02"), true, "same date"); +assert.sameValue(instance.equals("2000-05-04"), false, "different date"); + +const calendar = { toString() { return "a" } }; +assert.sameValue(instance.withCalendar(calendar).equals("2000-05-02"), false, "different calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-wrong-type.js new file mode 100644 index 000000000000..caa70ef84dfe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-wrong-type.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: Appropriate error thrown when argument cannot be converted to a valid string +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); + +assert.throws(RangeError, () => instance.equals(undefined), "undefined"); +assert.throws(RangeError, () => instance.equals(null), "null"); +assert.throws(RangeError, () => instance.equals(true), "true"); +assert.throws(RangeError, () => instance.equals(""), "empty string"); +assert.throws(TypeError, () => instance.equals(Symbol()), "symbol"); +assert.throws(RangeError, () => instance.equals(1), "1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..74e5951513c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..afc0693d8efe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => date.equals(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..8129e5904dc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..dac583a9135b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => date.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/basic.js new file mode 100644 index 000000000000..eb4b5ddc480a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/basic.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.equals +description: basic tests +features: [Temporal] +---*/ + +const date1 = new Temporal.PlainDate(1976, 11, 18); +const date2 = new Temporal.PlainDate(1914, 2, 23); +const date3 = new Temporal.PlainDate(1914, 2, 23); +assert.sameValue(date1.equals(date2), false, "different dates"); +assert.sameValue(date2.equals(date3), true, "same dates"); +assert.sameValue(date2.equals(date2), true, "same objects"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/builtin.js new file mode 100644 index 000000000000..f110fcd00842 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: > + Tests that Temporal.PlainDate.prototype.equals + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.equals), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.equals), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.equals), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.equals.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-call-different.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-call-different.js new file mode 100644 index 000000000000..78ca456623a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-call-different.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.equals +description: test if the calendar is compared +features: [Temporal] +---*/ + +class CalendarTraceToString extends Temporal.Calendar { + constructor(id) { + super("iso8601"); + this.id_ = id; + this.calls = 0; + } + toString() { + ++this.calls; + return this.id_; + } +}; + +const calendar1 = new CalendarTraceToString("a"); +const date1 = new Temporal.PlainDate(1914, 2, 23, calendar1); + +const calendar2 = new CalendarTraceToString("b"); +const date2 = new Temporal.PlainDate(1914, 2, 23, calendar2); + +assert.sameValue(date1.equals(date2), false, "different calendars"); +assert.sameValue(calendar1.calls, 1, "calendar1 toString() calls"); +assert.sameValue(calendar2.calls, 1, "calendar2 toString() calls"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-call-same.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-call-same.js new file mode 100644 index 000000000000..33f68cc59827 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-call-same.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.equals +description: test if the calendar is compared +features: [Temporal] +---*/ + +class CalendarTraceToString extends Temporal.Calendar { + constructor(id) { + super("iso8601"); + this.id_ = id; + this.calls = 0; + } + toString() { + ++this.calls; + return this.id_; + } +}; + +const calendar1 = new CalendarTraceToString("a"); +const date1 = new Temporal.PlainDate(1914, 2, 23, calendar1); + +const calendar2 = new CalendarTraceToString("a"); +const date2 = new Temporal.PlainDate(1914, 2, 23, calendar2); + +assert.sameValue(date1.equals(date2), true, "same calendar id"); +assert.sameValue(calendar1.calls, 1, "calendar1 toString() calls"); +assert.sameValue(calendar2.calls, 1, "calendar2 toString() calls"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..eba0f61dacfb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.equals({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-fields-iterable.js new file mode 100644 index 000000000000..053a2d12b54a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-fields-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +date.equals({ year: 2005, month: 6, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-no-call.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-no-call.js new file mode 100644 index 000000000000..436a8fce622f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-no-call.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.equals +description: test if the calendar is compared +features: [Temporal] +---*/ + +class CalendarTraceToString extends Temporal.Calendar { + constructor(id) { + super("iso8601"); + this.id_ = id; + this.calls = 0; + } + toString() { + ++this.calls; + return this.id_; + } +}; + +const calendar1 = new CalendarTraceToString("a"); +const date1 = new Temporal.PlainDate(1914, 2, 23, calendar1); + +const calendar2 = new CalendarTraceToString("b"); +const date2 = new Temporal.PlainDate(1914, 2, 22, calendar2); + +assert.sameValue(date1.equals(date2), false, "different ISO dates"); +assert.sameValue(calendar1.calls, 0, "calendar1 toString() calls"); +assert.sameValue(calendar2.calls, 0, "calendar2 toString() calls"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-temporal-object.js new file mode 100644 index 000000000000..3dd17e40197b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const date = new Temporal.PlainDate(2000, 5, 2, temporalObject); + date.equals({ year: 2005, month: 6, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f12046af9add --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/length.js new file mode 100644 index 000000000000..26c6b45ee956 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: Temporal.PlainDate.prototype.equals.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.equals, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/name.js new file mode 100644 index 000000000000..cefe3f4b5e2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: Temporal.PlainDate.prototype.equals.name is "equals". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.equals, "name", { + value: "equals", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/not-a-constructor.js new file mode 100644 index 000000000000..d12ec4eacaa1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: > + Temporal.PlainDate.prototype.equals does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.equals(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.equals), false, + "isConstructor(Temporal.PlainDate.prototype.equals)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/prop-desc.js new file mode 100644 index 000000000000..527a124ae65c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: The "equals" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.equals, + "function", + "`typeof PlainDate.prototype.equals` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "equals", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/year-zero.js new file mode 100644 index 000000000000..ae3b8f3f9cef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/equals/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.PlainDate(2000, 5, 2); + +assert.throws( + RangeError, + () => { instance.equals(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/builtin.js new file mode 100644 index 000000000000..858cf92c97b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.getisofields +description: > + Tests that Temporal.PlainDate.prototype.getISOFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.getISOFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.getISOFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.getISOFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.getISOFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-names.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-names.js new file mode 100644 index 000000000000..ac5ab8d623bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-names.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.getisofields +description: Correct field names on the object returned from getISOFields +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); + +const result = date.getISOFields(); +assert.sameValue(result.isoYear, 2000, "isoYear result"); +assert.sameValue(result.isoMonth, 5, "isoMonth result"); +assert.sameValue(result.isoDay, 2, "isoDay result"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-prop-desc.js new file mode 100644 index 000000000000..c8ecfc65821a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-prop-desc.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.getisofields +description: Properties on the returned object have the correct descriptor +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoMonth", + "isoYear", +]; + +const date = new Temporal.PlainDate(2000, 5, 2); +const result = date.getISOFields(); + +for (const property of expected) { + verifyProperty(result, property, { + writable: true, + enumerable: true, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-traversal-order.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-traversal-order.js new file mode 100644 index 000000000000..c6649bc18dea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/field-traversal-order.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.getisofields +description: Properties added in correct order to object returned from getISOFields +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoMonth", + "isoYear", +]; + +const date = new Temporal.PlainDate(2000, 5, 2); +const result = date.getISOFields(); + +assert.compareArray(Object.keys(result), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/length.js new file mode 100644 index 000000000000..14935accf820 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.getisofields +description: Temporal.PlainDate.prototype.getISOFields.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.getISOFields, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/name.js new file mode 100644 index 000000000000..9729caceb125 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.getisofields +description: Temporal.PlainDate.prototype.getISOFields.name is "getISOFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.getISOFields, "name", { + value: "getISOFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/not-a-constructor.js new file mode 100644 index 000000000000..73f13d5a9a3b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.getisofields +description: > + Temporal.PlainDate.prototype.getISOFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.getISOFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.getISOFields), false, + "isConstructor(Temporal.PlainDate.prototype.getISOFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/prop-desc.js new file mode 100644 index 000000000000..ec47d40b8729 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.getisofields +description: The "getISOFields" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.getISOFields, + "function", + "`typeof PlainDate.prototype.getISOFields` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "getISOFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/getISOFields/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/inLeapYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/inLeapYear/prop-desc.js new file mode 100644 index 000000000000..e0f235e418ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/inLeapYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.inleapyear +description: The "inLeapYear" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "inLeapYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/month/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/month/calendar-returns-infinity.js new file mode 100644 index 000000000000..a3c09c2df4cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/month/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.month +description: Getter throws if the calendar returns ±∞ from its month method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + month() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainDate(2000, 5, 2, pos); +assert.throws(RangeError, () => instance1.month); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainDate(2000, 5, 2, neg); +assert.throws(RangeError, () => instance2.month); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/month/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/month/prop-desc.js new file mode 100644 index 000000000000..494f55217e23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/month/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.month +description: The "month" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "month"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthCode/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthCode/prop-desc.js new file mode 100644 index 000000000000..c30e9860c1b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthCode/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.monthcode +description: The "monthCode" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "monthCode"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthsInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthsInYear/basic.js new file mode 100644 index 000000000000..921c7cb91a7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthsInYear/basic.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.monthsinyear +description: Basic tests for monthsInYear(). +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(1976, 11, 18); +assert.sameValue(plainDate.monthsInYear, 12); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthsInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthsInYear/prop-desc.js new file mode 100644 index 000000000000..dc8d875d2664 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/monthsInYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.monthsinyear +description: The "monthsInYear" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "monthsInYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/prop-desc.js new file mode 100644 index 000000000000..73b41516fcc9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-plaindate-prototype +description: The "prototype" property of Temporal.PlainDate +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.PlainDate.prototype, "object"); +assert.notSameValue(Temporal.PlainDate.prototype, null); + +verifyProperty(Temporal.PlainDate, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-plaindatetime.js new file mode 100644 index 000000000000..9bfb967f6eec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-plaindatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.since +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaindate.prototype.since step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const date = new Temporal.PlainDate(2000, 5, 2); + const result = date.since(datetime); + assert.sameValue(result.total({ unit: "nanoseconds" }), 0, "time part dropped"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js new file mode 100644 index 000000000000..6ff020dc2382 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.since(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..37d4f6e12966 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..9271fe926bbd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..f854628761d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => date.since(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..5b21a8cf4206 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..7f7385432ccd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => date.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/basic.js new file mode 100644 index 000000000000..1a6b62db5267 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/basic.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Basic tests for since(). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(1969, 7, 24); +const plainDate2 = Temporal.PlainDate.from({ year: 1969, month: 10, day: 5 }); +TemporalHelpers.assertDuration(plainDate2.since(plainDate), 0, 0, 0, /* days = */ 73, 0, 0, 0, 0, 0, 0, "same year"); + +const earlier = new Temporal.PlainDate(1969, 7, 24); +const later = new Temporal.PlainDate(1996, 3, 3); +const duration = later.since(earlier); +TemporalHelpers.assertDuration(duration, 0, 0, 0, /* days = */ 9719, 0, 0, 0, 0, 0, 0, "different year"); + +TemporalHelpers.assertDuration(plainDate.since({ year: 2019, month: 7, day: 24 }), 0, 0, 0, /* days = */ -18262, 0, 0, 0, 0, 0, 0, "option bag"); +TemporalHelpers.assertDuration(plainDate.since("2019-07-24"), 0, 0, 0, /* days = */ -18262, 0, 0, 0, 0, 0, 0, "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/builtin.js new file mode 100644 index 000000000000..fbf19512eb76 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: > + Tests that Temporal.PlainDate.prototype.since + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.since), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.since), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.since), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.since.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..a00702d73ae0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.PlainDate(1970, 1, 1, calendar); +calendar.specificPlainDate = instance; +instance.since(new Temporal.PlainDate(2000, 5, 2, calendar), { smallestUnit: "month" }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..76fbfb9895b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.since({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..6d1c9bc93d10 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.plaindate.prototype.since steps 13–14: + 13. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _largestUnit_). + 14. Let _result_ be ? CalendarDateUntil(_temporalDate_.[[Calendar]], _other_, _temporalDate_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.PlainDate(2000, 5, 2, calendar); + const later = new Temporal.PlainDate(2001, 6, 3, calendar); + later.since(earlier, { largestUnit }); + }, + { + years: ["year"], + months: ["month"], + weeks: ["week"], + days: ["day"] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-fields-iterable.js new file mode 100644 index 000000000000..96237c3fdf90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-fields-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.prototype.since step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +date.since({ year: 2005, month: 6, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-id-match.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-id-match.js new file mode 100644 index 000000000000..062bd0d98b0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-id-match.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Calculation is performed if calendars' toString results match +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +class Calendar1 extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + return "A"; + } +} +class Calendar2 extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + return "A"; + } +} + +const plainDate1 = new Temporal.PlainDate(2000, 1, 1, new Calendar1()); +const plainDate2 = new Temporal.PlainDate(2000, 1, 2, new Calendar2()); +TemporalHelpers.assertDuration(plainDate2.since(plainDate1), 0, 0, 0, /* days = */ 1, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-mismatch.js new file mode 100644 index 000000000000..be267281603d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-mismatch.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown if calendars' toString results do not match +features: [Temporal] +---*/ + +const calendar1 = { toString() { return "A"; } }; +const calendar2 = { toString() { return "B"; } }; + +const plainDate1 = new Temporal.PlainDate(2000, 1, 1, calendar1); +const plainDate2 = new Temporal.PlainDate(2000, 1, 1, calendar2); +assert.throws(RangeError, () => plainDate1.since(plainDate2)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-temporal-object.js new file mode 100644 index 000000000000..d99e6f591b36 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.prototype.since step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const date = new Temporal.PlainDate(2000, 5, 2, temporalObject); + date.since({ year: 2005, month: 6, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/days-in-month.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/days-in-month.js new file mode 100644 index 000000000000..e2f209c705b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/days-in-month.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: since() should take length of month into account. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate1 = Temporal.PlainDate.from("2019-01-01"); +const plainDate2 = Temporal.PlainDate.from("2019-02-01"); +const plainDate3 = Temporal.PlainDate.from("2019-03-01"); +TemporalHelpers.assertDuration(plainDate2.since(plainDate1), 0, 0, 0, /* days = */ 31, 0, 0, 0, 0, 0, 0, "January 2019"); +TemporalHelpers.assertDuration(plainDate3.since(plainDate2), 0, 0, 0, /* days = */ 28, 0, 0, 0, 0, 0, 0, "February 2019"); + +const plainDate4 = Temporal.PlainDate.from("2020-02-01"); +const plainDate5 = Temporal.PlainDate.from("2020-03-01"); +TemporalHelpers.assertDuration(plainDate5.since(plainDate4), 0, 0, 0, /* days = */ 29, 0, 0, 0, 0, 0, 0, "February 2020"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/days-in-year.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/days-in-year.js new file mode 100644 index 000000000000..961964109a74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/days-in-year.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: since() should take length of year into account. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate1 = Temporal.PlainDate.from("2019-01-01"); +const plainDate2 = Temporal.PlainDate.from("2020-01-01"); +const plainDate3 = Temporal.PlainDate.from("2021-01-01"); +TemporalHelpers.assertDuration(plainDate2.since(plainDate1), 0, 0, 0, /* days = */ 365, 0, 0, 0, 0, 0, 0, "From January 2019"); +TemporalHelpers.assertDuration(plainDate3.since(plainDate2), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "From January 2020"); + +const plainDate4 = Temporal.PlainDate.from("2019-06-01"); +const plainDate5 = Temporal.PlainDate.from("2020-06-01"); +const plainDate6 = Temporal.PlainDate.from("2021-06-01"); +TemporalHelpers.assertDuration(plainDate5.since(plainDate4), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "From June 2019"); +TemporalHelpers.assertDuration(plainDate6.since(plainDate5), 0, 0, 0, /* days = */ 365, 0, 0, 0, 0, 0, 0, "From June 2020"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..040daa1e368b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.prototype.since +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.since({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.since({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-default.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-default.js new file mode 100644 index 000000000000..26942960236c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-default.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Default value for largestUnit option is days +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = Temporal.PlainDate.from("2020-02-01"); +const feb21 = Temporal.PlainDate.from("2021-02-01"); +TemporalHelpers.assertDuration(feb21.since(feb20), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no options"); +TemporalHelpers.assertDuration(feb21.since(feb20, undefined), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "undefined options"); +TemporalHelpers.assertDuration(feb21.since(feb20, {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no largestUnit"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: undefined }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "undefined largestUnit"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "days" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "auto" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "auto"); +TemporalHelpers.assertDuration(feb21.since(feb20, () => {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no largestUnit (function)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-higher-units.js new file mode 100644 index 000000000000..ba1c1804a899 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-higher-units.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Tests calculations with higher largestUnit than the default of 'days' +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(1969, 7, 24); +const later = Temporal.PlainDate.from({ year: 2019, month: 7, day: 24 }); +const duration = later.since(date, { largestUnit: "years" }); +TemporalHelpers.assertDuration(duration, /* years = */ 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, "crossing epoch"); + +const feb20 = Temporal.PlainDate.from("2020-02-01"); +const feb21 = Temporal.PlainDate.from("2021-02-01"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, years"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, months"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 2, 0, 0, 0, 0, 0, 0, 0, "start of February, weeks"); + +const lastFeb20 = Temporal.PlainDate.from("2020-02-29"); +const lastFeb21 = Temporal.PlainDate.from("2021-02-28"); +TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: "years" }), 0, /* months = */ 11, 0, /* days = */ 28, 0, 0, 0, 0, 0, 0, 0, "end of February, years"); +TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: "months" }), 0, /* months = */ 11, 0, /* days = */ 28, 0, 0, 0, 0, 0, 0, "end of February, months"); +TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 1, 0, 0, 0, 0, 0, 0, "end of February, weeks"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-invalid-string.js new file mode 100644 index 000000000000..4bec8f148112 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const values = ["era", "eraYear", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..82bd9a0571fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 12); +const validUnits = [ + "year", + "month", + "week", + "day", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => later.since(earlier, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..262317d2b0f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const units = ["years", "months", "weeks", "days"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => later.since(earlier, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-undefined.js new file mode 100644 index 000000000000..25c7885b2dc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); + +const explicit = later.since(earlier, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-wrong-type.js new file mode 100644 index 000000000000..1ba94b80040a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "year", + (largestUnit) => later.since(earlier, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit.js new file mode 100644 index 000000000000..48d8ce1206e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/largestunit.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Specify behavior of PlainDate.since when largest specified unit is years or months. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ +const pd1 = new Temporal.PlainDate(2020, 11, 1); +const pd2 = new Temporal.PlainDate(2021, 11, 30); +TemporalHelpers.assertDuration(pd2.since(pd1), 0, 0, 0, 394, 0, 0, 0, 0, 0, 0, 'does not include higher units than necessary (largest unit unspecified)'); +TemporalHelpers.assertDuration(pd2.since(pd1, { largestUnit: 'months' }), 0, 12, 0, 29, 0, 0, 0, 0, 0, 0, 'does not include higher units than necessary (largest unit is months)'); +TemporalHelpers.assertDuration(pd2.since(pd1, { largestUnit: 'years' }), 1, 0, 0, 29, 0, 0, 0, 0, 0, 0, 'does not include higher units than necessary (largest unit is years)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/length.js new file mode 100644 index 000000000000..be9422edb33b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Temporal.PlainDate.prototype.since.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.since, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/name.js new file mode 100644 index 000000000000..2f8f3a6f824b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Temporal.PlainDate.prototype.since.name is "since". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.since, "name", { + value: "since", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/not-a-constructor.js new file mode 100644 index 000000000000..8462c5482bd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: > + Temporal.PlainDate.prototype.since does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.since(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.since), false, + "isConstructor(Temporal.PlainDate.prototype.since)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/options-invalid.js new file mode 100644 index 000000000000..56623346c122 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/options-invalid.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const feb20 = Temporal.PlainDate.from("2020-02-01"); +const feb21 = Temporal.PlainDate.from("2021-02-01"); +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +for (const badOptions of values) { + assert.throws(TypeError, () => feb21.since(feb20, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/prop-desc.js new file mode 100644 index 000000000000..faefe05c16f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: The "since" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.since, + "function", + "`typeof PlainDate.prototype.since` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "since", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/rounding-relative.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/rounding-relative.js new file mode 100644 index 000000000000..827fbf62d67f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/rounding-relative.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Should round relative to the receiver. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date1 = Temporal.PlainDate.from("2019-01-01"); +const date2 = Temporal.PlainDate.from("2019-02-15"); + +TemporalHelpers.assertDuration( + date2.since(date1, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ 1, 0, 0, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration( + date1.since(date2, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ -2, 0, 0, 0, 0, 0, 0, 0, 0); + +const cases = [ + ["2019-03-01", "2019-01-29", 1, 3], + ["2019-01-29", "2019-03-01", -1, -1], + ["2019-03-29", "2019-01-30", 1, 29], + ["2019-01-30", "2019-03-29", -1, -29], + ["2019-03-30", "2019-01-31", 1, 28], + ["2019-01-31", "2019-03-30", -1, -30], + ["2019-03-31", "2019-01-31", 2, 0], + ["2019-01-31", "2019-03-31", -2, 0] +]; +for (const [end, start, months, days] of cases) { + const result = Temporal.PlainDate.from(end).since(start, { largestUnit: "months" }); + TemporalHelpers.assertDuration(result, 0, months, 0, days, 0, 0, 0, 0, 0, 0, `${end} - ${start}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-nan.js new file mode 100644 index 000000000000..b6b982b81a25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.since step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-non-integer.js new file mode 100644 index 000000000000..2f1688c04952 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +const result = later.since(earlier, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..274b12aa6e24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -1 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 0 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-undefined.js new file mode 100644 index 000000000000..ed0b109b1516 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.since step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); + +const explicit = later.since(earlier, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1"); + +// See options-undefined.js for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..45d7c7ef4fbd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.since step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => later.since(earlier, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js new file mode 100644 index 000000000000..2d768c8e3e19 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" }), + /* years = */ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingIncrement: 10, roundingMode: "halfExpand" }), + 0, /* months = */ 30, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "weeks", roundingIncrement: 12, roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ 144, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "days", roundingIncrement: 100, roundingMode: "halfExpand" }), + 0, 0, 0, /* days = */ 1000, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-ceil.js new file mode 100644 index 000000000000..11af95b382e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-ceil.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "ceil" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "years", roundingMode: "ceil" }), + /* years = */ -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "ceil" }), + 0, /* months = */ 32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "months", roundingMode: "ceil" }), + 0, /* months = */ -31, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "weeks", roundingMode: "ceil" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "weeks", roundingMode: "ceil" }), + 0, 0, /* weeks = */ -139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "days", roundingMode: "ceil" }), + 0, 0, 0, /* days = */ 973, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "days", roundingMode: "ceil" }), + 0, 0, 0, /* days = */ -973, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-floor.js new file mode 100644 index 000000000000..2ec20e9e70ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-floor.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "floor" }), + /* years = */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "years", roundingMode: "floor" }), + /* years = */ -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "floor" }), + 0, /* months = */ 31, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "months", roundingMode: "floor" }), + 0, /* months = */ -32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "weeks", roundingMode: "floor" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "weeks", roundingMode: "floor" }), + 0, 0, /* weeks = */ -139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "days", roundingMode: "floor" }), + 0, 0, 0, /* days = */ 973, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "days", roundingMode: "floor" }), + 0, 0, 0, /* days = */ -973, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-halfExpand.js new file mode 100644 index 000000000000..316fed98f734 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-halfExpand.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ 32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ -32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "weeks", roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "weeks", roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ -139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "days", roundingMode: "halfExpand" }), + 0, 0, 0, /* days = */ 973, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "days", roundingMode: "halfExpand" }), + 0, 0, 0, /* days = */ -973, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-invalid-string.js new file mode 100644 index 000000000000..4c3b40082e1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-trunc.js new file mode 100644 index 000000000000..a84069440ca8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-trunc.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "trunc" }), + /* years = */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "years", roundingMode: "trunc" }), + /* years = */ -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "trunc" }), + 0, /* months = */ 31, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "months", roundingMode: "trunc" }), + 0, /* months = */ -31, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "weeks", roundingMode: "trunc" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "weeks", roundingMode: "trunc" }), + 0, 0, /* weeks = */ -139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "days", roundingMode: "trunc" }), + 0, 0, 0, /* days = */ 973, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "days", roundingMode: "trunc" }), + 0, 0, 0, /* days = */ -973, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-undefined.js new file mode 100644 index 000000000000..a78c35a3f564 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 1, 1); + +const later1 = new Temporal.PlainDate(2005, 2, 20); +const explicit1 = later1.since(earlier, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit1 = later1.since(earlier, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +const later2 = new Temporal.PlainDate(2005, 12, 15); +const explicit2 = later2.since(earlier, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit2 = later2.since(earlier, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-wrong-type.js new file mode 100644 index 000000000000..35d8570a2265 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => later.since(earlier, { smallestUnit: "year", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-higher-units.js new file mode 100644 index 000000000000..1f54a1ab4543 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-higher-units.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Tests calculations with higher smallestUnit than the default of "days" +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ 32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "weeks", roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-invalid-string.js new file mode 100644 index 000000000000..84ec4be86000 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const values = ["era", "eraYear", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..72b8631c2d66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 12); +const validUnits = [ + "year", + "month", + "week", + "day", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => later.since(earlier, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-undefined.js new file mode 100644 index 000000000000..3502693574aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); + +const explicit = later.since(earlier, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-wrong-type.js new file mode 100644 index 000000000000..8866628c03bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year", + (smallestUnit) => later.since(earlier, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/weeks-months.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/weeks-months.js new file mode 100644 index 000000000000..d23b50bad3c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/weeks-months.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: since() should not return weeks and months together. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(1969, 7, 24); +const laterDate = new Temporal.PlainDate(1969, 9, 4); +TemporalHelpers.assertDuration(laterDate.since(date, { largestUnit: "weeks" }), + 0, 0, /* weeks = */ 6, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration(laterDate.since(date, { largestUnit: "months" }), + 0, /* months = */ 1, 0, 11, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/year-zero.js new file mode 100644 index 000000000000..e7914107c33c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/since/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.PlainDate(2000, 5, 2); + +assert.throws( + RangeError, + () => { instance.since(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-invalid-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-invalid-duration.js new file mode 100644 index 000000000000..c4d99f92fba0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-invalid-duration.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: RangeError thrown when signs don't match in the duration +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarThrowEverything(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = { months: 1, days: -30 }; +for (const overflow of ["constrain", "reject"]) { + assert.throws(RangeError, () => date.subtract(duration, { overflow })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-missing-properties.js new file mode 100644 index 000000000000..72359ee18a86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-missing-properties.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: TypeError for missing properties +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const options = { + get overflow() { + TemporalHelpers.assertUnreachable("should not get overflow"); + } +}; +assert.throws(TypeError, () => date.subtract({}, options), "empty object"); +assert.throws(TypeError, () => date.subtract({ month: 12 }, options), "misspelled 'months'"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-not-object.js new file mode 100644 index 000000000000..5aa8b85f1bdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Passing a primitive other than string to subtract() throws +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); +assert.throws(RangeError, () => instance.subtract(undefined), "undefined"); +assert.throws(RangeError, () => instance.subtract(null), "null"); +assert.throws(RangeError, () => instance.subtract(true), "boolean"); +assert.throws(RangeError, () => instance.subtract(""), "empty string"); +assert.throws(TypeError, () => instance.subtract(Symbol()), "Symbol"); +assert.throws(RangeError, () => instance.subtract(7), "number"); +assert.throws(RangeError, () => instance.subtract(7n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-singular-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-singular-units.js new file mode 100644 index 000000000000..dabbd7f7bb2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-singular-units.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Ignores singular properties +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = Temporal.PlainDate.from("2019-11-18"); +TemporalHelpers.assertPlainDate(date.subtract({ month: 1, days: 1 }), + 2019, 11, "M11", 17); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..8cc0af4364c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +const resultHours = instance.subtract("-PT24.567890123H"); +TemporalHelpers.assertPlainDate(resultHours, 2000, 5, "M05", 3, "negative fractional hours"); + +const resultMinutes = instance.subtract("-PT1440.567890123M"); +TemporalHelpers.assertPlainDate(resultMinutes, 2000, 5, "M05", 3, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-string.js new file mode 100644 index 000000000000..5382c562fddc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); +const result = instance.subtract("P3D"); +TemporalHelpers.assertPlainDate(result, 2000, 4, "M04", 29); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/balance-smaller-units-basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/balance-smaller-units-basic.js new file mode 100644 index 000000000000..8099023355a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/balance-smaller-units-basic.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Durations with units smaller than days are balanced +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(1976, 11, 18); + +// lower units that don't balance up to a day +TemporalHelpers.assertPlainDate(date.subtract({ hours: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.subtract({ minutes: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.subtract({ seconds: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.subtract({ milliseconds: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.subtract({ microseconds: 1 }), 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.subtract({ nanoseconds: 1 }), 1976, 11, "M11", 18); + +// lower units that balance up to a day or more +TemporalHelpers.assertPlainDate(date.subtract({ hours: 24 }), 1976, 11, "M11", 17); +TemporalHelpers.assertPlainDate(date.subtract({ hours: 36 }), 1976, 11, "M11", 17); +TemporalHelpers.assertPlainDate(date.subtract({ hours: 48 }), 1976, 11, "M11", 16); +TemporalHelpers.assertPlainDate(date.subtract({ minutes: 1440 }), 1976, 11, "M11", 17); +TemporalHelpers.assertPlainDate(date.subtract({ seconds: 86400 }), 1976, 11, "M11", 17); +TemporalHelpers.assertPlainDate(date.subtract({ milliseconds: 86400_000 }), 1976, 11, "M11", 17); +TemporalHelpers.assertPlainDate(date.subtract({ microseconds: 86400_000_000 }), 1976, 11, "M11", 17); +TemporalHelpers.assertPlainDate(date.subtract({ nanoseconds: 86400_000_000_000 }), 1976, 11, "M11", 17); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/balance-smaller-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/balance-smaller-units.js new file mode 100644 index 000000000000..ea7c32018617 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/balance-smaller-units.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Durations with units smaller than days are balanced before adding, in the calendar +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; + +class DateAddCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateAdd(date, duration, options) { + actual.push(duration); + return super.dateAdd(date, duration, options); + } +} + +const calendar = new DateAddCalendar(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = new Temporal.Duration(0, 0, 0, 1, 24, 1440, 86400, 86400_000, 86400_000_000, 86400_000_000_000); + +const result = date.subtract(duration); +TemporalHelpers.assertPlainDate(result, 2000, 4, "M04", 25, "units smaller than days are balanced"); + +assert.sameValue(actual.length, 1, "calendar.dateAdd called exactly once"); +TemporalHelpers.assertDuration(actual[0], 0, 0, 0, -1, -24, -1440, -86400, -86400_000, -86400_000_000, -86400_000_000_000, "the duration is negated but not balanced before passing to the calendar"); +assert.notSameValue(actual[0], duration, "the duration is not passed directly to the calendar"); + +const resultString = date.subtract("P1DT24H1440M86400S"); +TemporalHelpers.assertPlainDate(resultString, 2000, 4, "M04", 28, "units smaller than days are balanced"); + +assert.sameValue(actual.length, 2, "calendar.dateAdd called exactly once"); +TemporalHelpers.assertDuration(actual[1], 0, 0, 0, -1, -24, -1440, -86400, 0, 0, 0, "the duration is negated but not balanced before passing to the calendar"); + +const resultPropBag = date.subtract({ days: 1, hours: 24, minutes: 1440, seconds: 86400, milliseconds: 86400_000, microseconds: 86400_000_000, nanoseconds: 86400_000_000_000 }); +TemporalHelpers.assertPlainDate(resultPropBag, 2000, 4, "M04", 25, "units smaller than days are balanced"); + +assert.sameValue(actual.length, 3, "calendar.dateAdd called exactly once"); +TemporalHelpers.assertDuration(actual[2], 0, 0, 0, -1, -24, -1440, -86400, -86400_000, -86400_000_000, -86400_000_000_000, "the duration is not balanced before passing to the calendar"); + +const negativeDuration = new Temporal.Duration(0, 0, 0, -1, -24, -1440, -86400, -86400_000, -86400_000_000, -86400_000_000_000); +const resultNegative = date.subtract(negativeDuration); +TemporalHelpers.assertPlainDate(resultNegative, 2000, 5, "M05", 9, "units smaller than days are balanced"); + +assert.sameValue(actual.length, 4, "calendar.dateAdd called exactly once"); +TemporalHelpers.assertDuration(actual[3], 0, 0, 0, 1, 24, 1440, 86400, 86400_000, 86400_000_000, 86400_000_000_000, "the duration is negated but not balanced before passing to the calendar"); +assert.notSameValue(actual[3], negativeDuration, "the duration is not passed directly to the calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/basic.js new file mode 100644 index 000000000000..16f9b6cb5825 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/basic.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Basic tests +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = Temporal.PlainDate.from("2019-11-18"); +TemporalHelpers.assertPlainDate(date.subtract({ years: 43 }), + 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(date.subtract({ months: 11 }), + 2018, 12, "M12", 18); +TemporalHelpers.assertPlainDate(date.subtract({ days: 20 }), + 2019, 10, "M10", 29); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('2019-02-28').subtract({ months: 1 }), + 2019, 1, "M01", 28); +TemporalHelpers.assertPlainDate(date.subtract(Temporal.Duration.from('P43Y')), + 1976, 11, "M11", 18); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('1976-11-18').subtract({ years: -43 }), + 2019, 11, "M11", 18); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('2018-12-18').subtract({ months: -11 }), + 2019, 11, "M11", 18); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('2019-10-29').subtract({ days: -20 }), + 2019, 11, "M11", 18); +TemporalHelpers.assertPlainDate(Temporal.PlainDate.from('2019-01-28').subtract({ months: -1 }), + 2019, 2, "M02", 28); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/builtin.js new file mode 100644 index 000000000000..1e6e023d38aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: > + Tests that Temporal.PlainDate.prototype.subtract + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.subtract), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.subtract), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.subtract), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.subtract.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f80a65be94ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate.prototype.subtract throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plaindate.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/length.js new file mode 100644 index 000000000000..72bedcda0068 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Temporal.PlainDate.prototype.subtract.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.subtract, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/limits.js new file mode 100644 index 000000000000..ad8665d5f0a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/limits.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate.prototype.subtract throws a RangeError if the calculation crosses a limit +esid: sec-temporal.plaindate.prototype.subtract +features: [Temporal] +---*/ + +const min = Temporal.PlainDate.from("-271821-04-19"); +const max = Temporal.PlainDate.from("+275760-09-13"); +["reject", "constrain"].forEach((overflow) => { + assert.throws(RangeError, () => min.subtract({ days: 1 }, { overflow }), `min with ${overflow}`); + assert.throws(RangeError, () => max.subtract({ days: -1 }, { overflow }), `max with ${overflow}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/name.js new file mode 100644 index 000000000000..0b8824fc1f70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Temporal.PlainDate.prototype.subtract.name is "subtract". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.subtract, "name", { + value: "subtract", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..ac2b0a203414 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate.prototype.subtract throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plaindate.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainDate.from({ year: 2000, month: 5, day: 2 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..c21aaf76759f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.subtract({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/not-a-constructor.js new file mode 100644 index 000000000000..0f20ab4a0747 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: > + Temporal.PlainDate.prototype.subtract does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.subtract(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.subtract), false, + "isConstructor(Temporal.PlainDate.prototype.subtract)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/options-invalid.js new file mode 100644 index 000000000000..7363bed0de95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/options-invalid.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(2000, 3, 31); +const duration = { months: 1 }; + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +for (const badOptions of values) { + assert.throws(TypeError, () => plainDate.subtract(duration, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/options-undefined.js new file mode 100644 index 000000000000..69d0c01478c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 3, 31); +const duration = { months: 1 }; + +const explicit = date.subtract(duration, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = date.subtract(duration); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/order-of-operations.js new file mode 100644 index 000000000000..c62070a3c8aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Properties on an object passed to subtract() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.subtract(argument); +TemporalHelpers.assertPlainDate(result, 1999, 3, "M03", 25); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-constrain.js new file mode 100644 index 000000000000..ce81cc019665 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-constrain.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Constrains with overflow constrain +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const mar31 = Temporal.PlainDate.from("2020-03-31"); +TemporalHelpers.assertPlainDate(mar31.subtract({ months: 1 }), + 2020, 2, "M02", 29, "implicit"); +TemporalHelpers.assertPlainDate(mar31.subtract({ months: 1 }, { overflow: "constrain" }), + 2020, 2, "M02", 29, "explicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js new file mode 100644 index 000000000000..4f39bef19cc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.subtract step 7: + 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _negatedDuration_, _options_). +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const duration = new Temporal.Duration(3, 3, 0, 3); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-reject.js new file mode 100644 index 000000000000..4afba729c10a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-reject.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Throws with overflow reject +features: [Temporal] +---*/ + +const mar31 = Temporal.PlainDate.from("2020-03-31"); +assert.throws(RangeError, () => mar31.subtract({ months: 1 }, { overflow: "reject" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-undefined.js new file mode 100644 index 000000000000..dc7b6f46c76d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-undefined.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.subtract step 7: + 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _negatedDuration_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 31); +const duration = new Temporal.Duration(3, 1); + +const explicit = date.subtract(duration, { overflow: undefined }); +TemporalHelpers.assertPlainDate(explicit, 1997, 4, "M04", 30, "default overflow is constrain"); +const implicit = date.subtract(duration, {}); +TemporalHelpers.assertPlainDate(implicit, 1997, 4, "M04", 30, "default overflow is constrain"); +const lambda = date.subtract(duration, {}); +TemporalHelpers.assertPlainDate(lambda, 1997, 4, "M04", 30, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-wrong-type.js new file mode 100644 index 000000000000..44deb4726308 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/overflow-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.subtract step 7: + 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _negatedDuration_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const duration = new Temporal.Duration(3, 3, 0, 3); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => date.subtract(duration, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDate(result, 1997, 1, "M01", 30, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/prop-desc.js new file mode 100644 index 000000000000..2488dc1b9d2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: The "subtract" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.subtract, + "function", + "`typeof PlainDate.prototype.subtract` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "subtract", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/subclassing-ignored.js new file mode 100644 index 000000000000..eab6d10bd002 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/subtract/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Objects of a subclass are never created as return values for subtract() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDate, + [2000, 5, 2], + "subtract", + [{ days: 1 }], + (result) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 1), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..95d78b21432d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tojson +description: > + Tests that Temporal.PlainDate.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/length.js new file mode 100644 index 000000000000..c92cb4204db8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tojson +description: Temporal.PlainDate.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/name.js new file mode 100644 index 000000000000..388764612e36 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tojson +description: Temporal.PlainDate.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..0ffe390a6379 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tojson +description: > + Temporal.PlainDate.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.toJSON), false, + "isConstructor(Temporal.PlainDate.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..eebff96d3934 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tojson +description: The "toJSON" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.toJSON, + "function", + "`typeof PlainDate.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/year-format.js new file mode 100644 index 000000000000..572da018d842 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toJSON/year-format.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainDate(-100000, 12, 3); +assert.sameValue(instance.toJSON(), "-100000-12-03", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-10000, 4, 5); +assert.sameValue(instance.toJSON(), "-010000-04-05", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-9999, 6, 7); +assert.sameValue(instance.toJSON(), "-009999-06-07", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-1000, 8, 9); +assert.sameValue(instance.toJSON(), "-001000-08-09", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-999, 10, 9); +assert.sameValue(instance.toJSON(), "-000999-10-09", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-1, 8, 7); +assert.sameValue(instance.toJSON(), "-000001-08-07", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainDate(0, 6, 5); +assert.sameValue(instance.toJSON(), "0000-06-05", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainDate(1, 4, 3); +assert.sameValue(instance.toJSON(), "0001-04-03", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainDate(999, 2, 10); +assert.sameValue(instance.toJSON(), "0999-02-10", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(1000, 1, 23); +assert.sameValue(instance.toJSON(), "1000-01-23", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(9999, 4, 5); +assert.sameValue(instance.toJSON(), "9999-04-05", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(10000, 6, 7); +assert.sameValue(instance.toJSON(), "+010000-06-07", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainDate(100000, 8, 9); +assert.sameValue(instance.toJSON(), "+100000-08-09", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/builtin.js new file mode 100644 index 000000000000..f5e39dfe81ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: > + Tests that Temporal.PlainDate.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/length.js new file mode 100644 index 000000000000..98db262c6ba7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: Temporal.PlainDate.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/name.js new file mode 100644 index 000000000000..bb9230ce1cda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: Temporal.PlainDate.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 000000000000..4877c5069d4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: > + Temporal.PlainDate.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.toLocaleString), false, + "isConstructor(Temporal.PlainDate.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/prop-desc.js new file mode 100644 index 000000000000..1e19af79b801 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.toLocaleString, + "function", + "`typeof PlainDate.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/return-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/return-string.js new file mode 100644 index 000000000000..dd7c90772845 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/return-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: > + toLocaleString return a string. +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); + +assert.sameValue(typeof date.toLocaleString("en", { dateStyle: "short" }), "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..1ad27a93f8c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainDate(2000, 5, 2); +assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..631bb87251c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + `${string} is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.toPlainDateTime(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + 'space is not accepted as a substitute for T prefix' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => instance.toPlainDateTime(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-with-time-designator.js new file mode 100644 index 000000000000..41d75e3d4caf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-with-time-designator.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDate(2000, 1, 1); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.toPlainDateTime(arg); + TemporalHelpers.assertPlainDateTime(result, 2000, 1, "M01", 1, 0, 30, 0, 0, 0, 0, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..2350583a2506 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..875c590efa88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaindate.prototype.toplaindatetime step 4: + 4. Set _temporalTime_ to ? ToTemporalTime(_temporalTime_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const date = new Temporal.PlainDate(2000, 5, 2); +const pdt = date.toPlainDateTime(datetime); + +TemporalHelpers.assertPlainDateTime(pdt, 2000, 5, "M05", 2, 1, 1, 1, 1, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..bec3922f18a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainDate(2000, 5, 2); +const result = instance.toPlainDateTime(datetime); +TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 16, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..01f5e2e8d790 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..6a30c886da2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => date.toPlainDateTime(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..d610ceb1b03d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..5b7c50867492 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => date.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/basic.js new file mode 100644 index 000000000000..9080fff6d60a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/basic.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: Basic tests for toPlainDateTime(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); + +const string = date.toPlainDateTime("11:30:23"); +TemporalHelpers.assertPlainDateTime(string, 2000, 5, "M05", 2, 11, 30, 23, 0, 0, 0, "string"); + +const optionBag = date.toPlainDateTime({ hour: 11, minute: 30, second: 23 }); +TemporalHelpers.assertPlainDateTime(optionBag, 2000, 5, "M05", 2, 11, 30, 23, 0, 0, 0, "option bag"); + +const plainTime = date.toPlainDateTime(Temporal.PlainTime.from("11:30:23")); +TemporalHelpers.assertPlainDateTime(plainTime, 2000, 5, "M05", 2, 11, 30, 23, 0, 0, 0, "PlainTime"); + +const plainDateTime = date.toPlainDateTime(Temporal.PlainDateTime.from("1999-07-14T11:30:23")); +TemporalHelpers.assertPlainDateTime(plainDateTime, 2000, 5, "M05", 2, 11, 30, 23, 0, 0, 0, "PlainTime"); + +const zonedDateTime = date.toPlainDateTime(Temporal.ZonedDateTime.from("1999-07-14T11:30:23Z[UTC]")); +TemporalHelpers.assertPlainDateTime(zonedDateTime, 2000, 5, "M05", 2, 11, 30, 23, 0, 0, 0, "PlainTime"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/builtin.js new file mode 100644 index 000000000000..e571f6b1cdbe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: > + Tests that Temporal.PlainDate.prototype.toPlainDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.toPlainDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.toPlainDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.toPlainDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.toPlainDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/calendar-temporal-object.js new file mode 100644 index 000000000000..963b4d5be71e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/calendar-temporal-object.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.prototype.toplaindatetime step 4: + 4. Set _temporalTime_ to ? ToTemporalTime(_temporalTime_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const date = new Temporal.PlainDate(2000, 5, 2); + assert.throws(RangeError, () => date.toPlainDateTime({ hour: 12, minute: 30, calendar: temporalObject })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/length.js new file mode 100644 index 000000000000..619fb7a38a1f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: Temporal.PlainDate.prototype.toPlainDateTime.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toPlainDateTime, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/name.js new file mode 100644 index 000000000000..53006e49bba4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: Temporal.PlainDate.prototype.toPlainDateTime.name is "toPlainDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toPlainDateTime, "name", { + value: "toPlainDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/not-a-constructor.js new file mode 100644 index 000000000000..f10919aa7372 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: > + Temporal.PlainDate.prototype.toPlainDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.toPlainDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.toPlainDateTime), false, + "isConstructor(Temporal.PlainDate.prototype.toPlainDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/plaintime-propertybag-no-time-units.js new file mode 100644 index 000000000000..821e8c877351 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/plaintime-propertybag-no-time-units.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: Missing time units in property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 1, 1); + +const props = {}; +assert.throws(TypeError, () => instance.toPlainDateTime(props), "TypeError if at least one property is not present"); + +props.minute = 30; +const result = instance.toPlainDateTime(props); +TemporalHelpers.assertPlainDateTime(result, 2000, 1, "M01", 1, 0, 30, 0, 0, 0, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/prop-desc.js new file mode 100644 index 000000000000..b133f7aed365 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: The "toPlainDateTime" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.toPlainDateTime, + "function", + "`typeof PlainDate.prototype.toPlainDateTime` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "toPlainDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/time-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/time-invalid.js new file mode 100644 index 000000000000..3ab7c8c8c327 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/time-invalid.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: TypeError thrown if an invalid property bag passed +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(2000, 5, 2); +assert.throws(TypeError, () => plainDate.toPlainDateTime({}), "empty object"); +assert.throws(TypeError, () => plainDate.toPlainDateTime({ minutes: 30 }), "plural property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/time-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/time-undefined.js new file mode 100644 index 000000000000..75460f696275 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/time-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: The time is assumed to be midnight if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); + +const explicit = date.toPlainDateTime(undefined); +TemporalHelpers.assertPlainDateTime(explicit, 2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0, "default time is midnight - explicit"); + +const implicit = date.toPlainDateTime(); +TemporalHelpers.assertPlainDateTime(implicit, 2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0, "default time is midnight - implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/year-zero.js new file mode 100644 index 000000000000..9fa9ac163458 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainDateTime/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplaindatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-12-07T03:24:30', + '-000000-12-07T03:24:30+01:00[UTC]' +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/builtin.js new file mode 100644 index 000000000000..fc3a0f82e63b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainmonthday +description: > + Tests that Temporal.PlainDate.prototype.toPlainMonthDay + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.toPlainMonthDay), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.toPlainMonthDay), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.toPlainMonthDay), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.toPlainMonthDay.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-arguments.js new file mode 100644 index 000000000000..ec7437ad473b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-arguments.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainmonthday +description: Correct options value is passed to calendar method +info: | + MonthDayFromFields ( calendar, fields [ , options ] ) + + 3. If options is not present, then + a. Set options to undefined. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + monthDayFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.sameValue(args[1], undefined, "args[1]"); + return super.monthDayFromFields(...args); + } +} +const plainDate = new Temporal.PlainDate(2000, 5, 2, new CustomCalendar()); +const result = plainDate.toPlainMonthDay(); +TemporalHelpers.assertPlainMonthDay(result, "M05", 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-fields-iterable.js new file mode 100644 index 000000000000..0cf48176ae98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-fields-iterable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainmonthday +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.prototype.toplainmonthday step 4: + 4. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"monthCode"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "monthCode", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +date.toPlainMonthDay(); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..7507037adb13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainmonthday +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.toPlainMonthDay(); +assert.sameValue(calendar.monthDayFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/length.js new file mode 100644 index 000000000000..44f54917dff3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainmonthday +description: Temporal.PlainDate.prototype.toPlainMonthDay.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toPlainMonthDay, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/name.js new file mode 100644 index 000000000000..55a906e40b59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainmonthday +description: Temporal.PlainDate.prototype.toPlainMonthDay.name is "toPlainMonthDay". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toPlainMonthDay, "name", { + value: "toPlainMonthDay", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/not-a-constructor.js new file mode 100644 index 000000000000..66604dce1370 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainmonthday +description: > + Temporal.PlainDate.prototype.toPlainMonthDay does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.toPlainMonthDay(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.toPlainMonthDay), false, + "isConstructor(Temporal.PlainDate.prototype.toPlainMonthDay)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/prop-desc.js new file mode 100644 index 000000000000..1c60afe7ca33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainmonthday +description: The "toPlainMonthDay" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.toPlainMonthDay, + "function", + "`typeof PlainDate.prototype.toPlainMonthDay` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "toPlainMonthDay", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/builtin.js new file mode 100644 index 000000000000..040956ee1de5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: > + Tests that Temporal.PlainDate.prototype.toPlainYearMonth + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.toPlainYearMonth), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.toPlainYearMonth), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.toPlainYearMonth), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.toPlainYearMonth.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-arguments.js new file mode 100644 index 000000000000..56efd4fbd00e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-arguments.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: Correct options value is passed to calendar method +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 3. If options is not present, then + a. Set options to undefined. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + yearMonthFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.sameValue(args[1], undefined, "args[1]"); + return super.yearMonthFromFields(...args); + } +} +const plainDate = new Temporal.PlainDate(2000, 5, 2, new CustomCalendar()); +const result = plainDate.toPlainYearMonth(); +TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-fields-iterable.js new file mode 100644 index 000000000000..e99f5490abc7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-fields-iterable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.prototype.toplainyearmonth step 4: + 4. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +date.toPlainYearMonth(); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..8843493d8fdf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.toPlainYearMonth(); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/length.js new file mode 100644 index 000000000000..fd40a056646d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: Temporal.PlainDate.prototype.toPlainYearMonth.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toPlainYearMonth, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/limits.js new file mode 100644 index 000000000000..e1f04565dd9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/limits.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: toPlainYearMonth works within the supported range +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const min = Temporal.PlainDate.from('-271821-04-19'); +TemporalHelpers.assertPlainYearMonth(min.toPlainYearMonth(), + -271821, 4, "M04", "min"); + +const max = Temporal.PlainDate.from('+275760-09-13'); +TemporalHelpers.assertPlainYearMonth(max.toPlainYearMonth(), + 275760, 9, "M09", "max"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/name.js new file mode 100644 index 000000000000..8e4b8c4f5080 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: Temporal.PlainDate.prototype.toPlainYearMonth.name is "toPlainYearMonth". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toPlainYearMonth, "name", { + value: "toPlainYearMonth", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/not-a-constructor.js new file mode 100644 index 000000000000..9d77a7cc089b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: > + Temporal.PlainDate.prototype.toPlainYearMonth does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.toPlainYearMonth(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.toPlainYearMonth), false, + "isConstructor(Temporal.PlainDate.prototype.toPlainYearMonth)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/prop-desc.js new file mode 100644 index 000000000000..1514afcb8b13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.toplainyearmonth +description: The "toPlainYearMonth" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.toPlainYearMonth, + "function", + "`typeof PlainDate.prototype.toPlainYearMonth` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "toPlainYearMonth", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/basic.js new file mode 100644 index 000000000000..40c2bb3deae4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/basic.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.tostring +description: basic tests +features: [Temporal] +---*/ + +const date1 = new Temporal.PlainDate(1976, 11, 18); +assert.sameValue(date1.toString(), "1976-11-18"); + +const date2 = new Temporal.PlainDate(1914, 2, 23); +assert.sameValue(date2.toString(), "1914-02-23"); + +const date3 = new Temporal.PlainDate(1996, 2, 29); +assert.sameValue(date3.toString(), "1996-02-29"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/builtin.js new file mode 100644 index 000000000000..6007e36d4bae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tostring +description: > + Tests that Temporal.PlainDate.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-always.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-always.js new file mode 100644 index 000000000000..4ebe6ca73ae5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-always.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.tostring +description: always value for calendarName option +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const date1 = new Temporal.PlainDate(2000, 5, 2); +const date2 = new Temporal.PlainDate(2000, 5, 2, calendar); + +[ + [date1, "2000-05-02[u-ca=iso8601]"], + [date2, "2000-05-02[u-ca=custom]"], +].forEach(([date, expected]) => { + const result = date.toString({ calendarName: "always" }); + assert.sameValue(result, expected, "expected " + expected); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-auto.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-auto.js new file mode 100644 index 000000000000..35ba06feb7e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-auto.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.tostring +description: auto value for calendarName option +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const date1 = new Temporal.PlainDate(2000, 5, 2); +const date2 = new Temporal.PlainDate(2000, 5, 2, calendar); + +[ + [date1, "2000-05-02"], + [date2, "2000-05-02[u-ca=custom]"], +].forEach(([date, expected]) => { + const result = date.toString({ calendarName: "auto" }); + assert.sameValue(result, expected, "expected " + expected); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-invalid-string.js new file mode 100644 index 000000000000..01207bcbc3fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-invalid-string.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.tostring +description: RangeError thrown when calendarName option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plaindate.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const values = ["ALWAYS", "sometimes", "other string"]; + +for (const calendarName of values) { + assert.throws(RangeError, () => date.toString({ calendarName })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-never.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-never.js new file mode 100644 index 000000000000..a34d475c4961 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-never.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.tostring +description: never value for calendarName option +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const date1 = new Temporal.PlainDate(2000, 5, 2); +const date2 = new Temporal.PlainDate(2000, 5, 2, calendar); + +[ + [date1, "2000-05-02"], + [date2, "2000-05-02"], +].forEach(([date, expected]) => { + const result = date.toString({ calendarName: "never" }); + assert.sameValue(result, expected, "expected " + expected); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-undefined.js new file mode 100644 index 000000000000..9e570ceb41e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-undefined.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.tostring +description: Fallback value for calendarName option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plaindate.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const date1 = new Temporal.PlainDate(2000, 5, 2); +const date2 = new Temporal.PlainDate(2000, 5, 2, calendar); + +[ + [date1, "2000-05-02"], + [date2, "2000-05-02[u-ca=custom]"], +].forEach(([date, expected]) => { + const explicit = date.toString({ calendarName: undefined }); + assert.sameValue(explicit, expected, "default calendarName option is auto"); + + const implicit = date.toString({}); + assert.sameValue(implicit, expected, "default calendarName option is auto"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-wrong-type.js new file mode 100644 index 000000000000..1bc68faa4237 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/calendarname-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.protoype.tostring +description: Type conversions for calendarName option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plaindate.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const date = new Temporal.PlainDate(2000, 5, 2, calendar); + +TemporalHelpers.checkStringOptionWrongType("calendarName", "auto", + (calendarName) => date.toString({ calendarName }), + (result, descr) => assert.sameValue(result, "2000-05-02[u-ca=custom]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/length.js new file mode 100644 index 000000000000..f8190ca59ccb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tostring +description: Temporal.PlainDate.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/name.js new file mode 100644 index 000000000000..5768a60ead28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tostring +description: Temporal.PlainDate.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..85d35dbcf2fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tostring +description: > + Temporal.PlainDate.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.toString), false, + "isConstructor(Temporal.PlainDate.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/options-undefined.js new file mode 100644 index 000000000000..083bdc4d72c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/options-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tostring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const date1 = new Temporal.PlainDate(2000, 5, 2); +const date2 = new Temporal.PlainDate(2000, 5, 2, calendar); + +[ + [date1, "2000-05-02"], + [date2, "2000-05-02[u-ca=custom]"], +].forEach(([date, expected]) => { + const explicit = date.toString(undefined); + assert.sameValue(explicit, expected, "default calendarName option is auto"); + + const implicit = date.toString(); + assert.sameValue(implicit, expected, "default calendarName option is auto"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..591b3b731aa0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tostring +description: The "toString" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.toString, + "function", + "`typeof PlainDate.prototype.toString` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/year-format.js new file mode 100644 index 000000000000..82e796545581 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toString/year-format.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainDate(-100000, 12, 3); +assert.sameValue(instance.toString(), "-100000-12-03", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-10000, 4, 5); +assert.sameValue(instance.toString(), "-010000-04-05", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-9999, 6, 7); +assert.sameValue(instance.toString(), "-009999-06-07", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-1000, 8, 9); +assert.sameValue(instance.toString(), "-001000-08-09", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-999, 10, 9); +assert.sameValue(instance.toString(), "-000999-10-09", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-1, 8, 7); +assert.sameValue(instance.toString(), "-000001-08-07", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainDate(0, 6, 5); +assert.sameValue(instance.toString(), "0000-06-05", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainDate(1, 4, 3); +assert.sameValue(instance.toString(), "0001-04-03", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainDate(999, 2, 10); +assert.sameValue(instance.toString(), "0999-02-10", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(1000, 1, 23); +assert.sameValue(instance.toString(), "1000-01-23", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(9999, 4, 5); +assert.sameValue(instance.toString(), "9999-04-05", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(10000, 6, 7); +assert.sameValue(instance.toString(), "+010000-06-07", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainDate(100000, 8, 9); +assert.sameValue(instance.toString(), "+100000-08-09", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..75ed2d897994 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainDate(2000, 5, 2); +assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainTime: arg, timeZone: "UTC" }), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..9afb3241fe64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainTime: arg, timeZone: "UTC" }), + `${string} is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.toZonedDateTime({ plainTime: arg, timeZone: "UTC" }); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainTime: arg, timeZone: "UTC" }), + 'space is not accepted as a substitute for T prefix' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => instance.toZonedDateTime({ plainTime: arg, timeZone: "UTC" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-with-time-designator.js new file mode 100644 index 000000000000..df4fe9ee003f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-with-time-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDate(2000, 1, 1); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.toZonedDateTime({ plainTime: arg, timeZone: "UTC" }); + assert.sameValue(result.epochNanoseconds, 946686600_000_000_000n, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..742c2ae72928 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainTime: arg, timeZone: "UTC" }), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..f82fcba2e615 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainDate(2000, 5, 2); +const result = instance.toZonedDateTime({ plainTime: datetime, timeZone: "UTC" }); +assert.sameValue(result.epochNanoseconds, 957286235_000_000_001n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/basic.js new file mode 100644 index 000000000000..d39a305784e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/basic.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Basic tests for toZonedDateTime(). +features: [Temporal] +---*/ + +const plainDate = Temporal.PlainDate.from("2020-01-01"); +const timeZone = Temporal.TimeZone.from("UTC"); +const plainTime = Temporal.PlainTime.from("12:00"); + +let result = plainDate.toZonedDateTime({ timeZone, plainTime }); +assert.sameValue(result.toString(), "2020-01-01T12:00:00+00:00[UTC]", "objects passed"); + +result = plainDate.toZonedDateTime(timeZone); +assert.sameValue(result.toString(), "2020-01-01T00:00:00+00:00[UTC]", "time zone object argument"); + +result = plainDate.toZonedDateTime("UTC"); +assert.sameValue(result.toString(), "2020-01-01T00:00:00+00:00[UTC]", "time zone string argument"); + +result = plainDate.toZonedDateTime({ timeZone }); +assert.sameValue(result.toString(), "2020-01-01T00:00:00+00:00[UTC]", "time zone object property"); + +result = plainDate.toZonedDateTime({ timeZone: "UTC", plainTime }); +assert.sameValue(result.toString(), "2020-01-01T12:00:00+00:00[UTC]", "time zone string property"); + +result = plainDate.toZonedDateTime({ timeZone, plainTime: "12:00" }); +assert.sameValue(result.toString(), "2020-01-01T12:00:00+00:00[UTC]", "time string property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/builtin.js new file mode 100644 index 000000000000..97b2d4867e36 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: > + Tests that Temporal.PlainDate.prototype.toZonedDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.toZonedDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.toZonedDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.toZonedDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.toZonedDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..0995f43c5090 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.PlainDate(1970, 1, 1, calendar); +instance.toZonedDateTime({ timeZone }); +assert.sameValue(calendar.dateAddCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/calendar-temporal-object.js new file mode 100644 index 000000000000..1438237c7c59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/calendar-temporal-object.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.prototype.tozoneddatetime step 6.a: + a. Set _temporalTime_ to ? ToTemporalTime(_temporalTime_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const date = new Temporal.PlainDate(2000, 5, 2); + assert.throws(RangeError, () => date.toZonedDateTime({ timeZone: "UTC", plainTime: { hour: 12, minute: 30, calendar: temporalObject } })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/length.js new file mode 100644 index 000000000000..b0cadc78f515 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Temporal.PlainDate.prototype.toZonedDateTime.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toZonedDateTime, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/name.js new file mode 100644 index 000000000000..12b36d0a5e07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Temporal.PlainDate.prototype.toZonedDateTime.name is "toZonedDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.toZonedDateTime, "name", { + value: "toZonedDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/not-a-constructor.js new file mode 100644 index 000000000000..131562d88de4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: > + Temporal.PlainDate.prototype.toZonedDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.toZonedDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.toZonedDateTime), false, + "isConstructor(Temporal.PlainDate.prototype.toZonedDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..b7c7f609e327 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Negative time fields are balanced upwards in a ZonedDateTime given as plainTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaindate.prototype.tozoneddatetime step 6.a: + a. Set _temporalTime_ to ? ToTemporalTime(_temporalTime_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const otherTimeZone = new Temporal.TimeZone("UTC"); // should not be used to convert datetime to PlainTime +const date = new Temporal.PlainDate(2000, 5, 2); +const zdt = date.toZonedDateTime({ timeZone: otherTimeZone, plainTime: datetime }); + +assert.sameValue(zdt.microsecond, 0); +assert.sameValue(zdt.nanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..b553a72e1ad0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.toZonedDateTime({ plainTime: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..5b2b74a0a7e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => date.toZonedDateTime({ plainTime: datetime, timeZone: "UTC" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..949dcc073e29 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.toZonedDateTime({ plainTime: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..ea53e49a80a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => date.toZonedDateTime({ plainTime: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-propertybag-no-time-units.js new file mode 100644 index 000000000000..b71730b466b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/plaintime-propertybag-no-time-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Missing time units in property bag default to 0 +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 1, 1); + +const props = {}; +assert.throws(TypeError, () => instance.toZonedDateTime({ plainTime: props, timeZone: "UTC" }), "TypeError if at least one property is not present"); + +props.minute = 30; +const result = instance.toZonedDateTime({ plainTime: props, timeZone: "UTC" }); +assert.sameValue(result.epochNanoseconds, 946686600_000_000_000n, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/prop-desc.js new file mode 100644 index 000000000000..4797ae5a5e00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: The "toZonedDateTime" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.toZonedDateTime, + "function", + "`typeof PlainDate.prototype.toZonedDateTime` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "toZonedDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..1d61286c8655 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const plainTime = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => date.toZonedDateTime({ plainTime, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..a07ac7d09797 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const date = new Temporal.PlainDate(2000, 5, 2); + const plainTime = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + timeZone.getPossibleInstantsFor = function () { + return []; + }; + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => date.toZonedDateTime({ plainTime, timeZone }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..55db38958973 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const plainTime = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => date.toZonedDateTime({ plainTime, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..e2308330ddaa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const plainTime = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(TypeError, () => date.toZonedDateTime({ plainTime, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..058c02dcacdb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.plaindate.prototype.tozoneddatetime step 7: + 7. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "2000-05-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const date = new Temporal.PlainDate(2000, 5, 2); + date.toZonedDateTime(timeZone); +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:30:00", + "2030-01-01T01:30:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const date = new Temporal.PlainDate(2030, 1, 1); + date.toZonedDateTime({ plainTime: new Temporal.PlainTime(0, 30), timeZone }); +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..aa9f074e8145 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.toZonedDateTime(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = instance.toZonedDateTime(timeZone); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = instance.toZonedDateTime(timeZone); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = instance.toZonedDateTime(timeZone); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = instance.toZonedDateTime(timeZone); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = instance.toZonedDateTime(timeZone); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..8ff2e43bc77d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = instance.toZonedDateTime(timeZone); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/year-zero.js new file mode 100644 index 000000000000..419a55765201 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/toZonedDateTime/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-12-07T03:24:30', + '-000000-12-07T03:24:30+01:00[UTC]' +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainTime: arg, timeZone: "UTC" }), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-plaindatetime.js new file mode 100644 index 000000000000..4087b42c02a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-plaindatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.until +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaindate.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const date = new Temporal.PlainDate(2000, 5, 2); + const result = date.until(datetime); + assert.sameValue(result.total({ unit: "nanoseconds" }), 0, "time part dropped"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js new file mode 100644 index 000000000000..5d87523c04a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.until(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..aabcdd88792b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..40771d29e389 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..de50f0eb0daf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => date.until(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..7d8fa02e0e8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..a20cf636d44d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => date.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/basic.js new file mode 100644 index 000000000000..f6288381d0c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/basic.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Basic tests for until(). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(1969, 7, 24); +const plainDate2 = Temporal.PlainDate.from({ year: 1969, month: 10, day: 5 }); +TemporalHelpers.assertDuration(plainDate.until(plainDate2), 0, 0, 0, /* days = */ 73, 0, 0, 0, 0, 0, 0, "same year"); + +const earlier = new Temporal.PlainDate(1969, 7, 24); +const later = new Temporal.PlainDate(1996, 3, 3); +TemporalHelpers.assertDuration(earlier.until(later), 0, 0, 0, /* days = */ 9719, 0, 0, 0, 0, 0, 0, "different year"); + +TemporalHelpers.assertDuration(plainDate.until({ year: 2019, month: 7, day: 24 }), 0, 0, 0, /* days = */ 18262, 0, 0, 0, 0, 0, 0, "option bag"); +TemporalHelpers.assertDuration(plainDate.until("2019-07-24"), 0, 0, 0, /* days = */ 18262, 0, 0, 0, 0, 0, 0, "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin.js new file mode 100644 index 000000000000..2375a8a660b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Tests that Temporal.PlainDate.prototype.until + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.until), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.until), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.until), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.until.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..15b4b8a744b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.PlainDate(1970, 1, 1, calendar); +calendar.specificPlainDate = instance; +instance.until(new Temporal.PlainDate(2000, 5, 2, calendar), { smallestUnit: "month" }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..1f3b80b03119 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.until({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..afaa92d1688b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.plaindate.prototype.until steps 12–13: + 13. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _largestUnit_). + 14. Let _result_ be ? CalendarDateUntil(_temporalDate_.[[Calendar]], _temporalDate_, _other_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.PlainDate(2000, 5, 2, calendar); + const later = new Temporal.PlainDate(2001, 6, 3, calendar); + earlier.until(later, { largestUnit }); + }, + { + years: ["year"], + months: ["month"], + weeks: ["week"], + days: ["day"] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-fields-iterable.js new file mode 100644 index 000000000000..c7318cb8bb8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-fields-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +date.until({ year: 2005, month: 6, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-id-match.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-id-match.js new file mode 100644 index 000000000000..4794765e7e1b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-id-match.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Calculation is performed if calendars' toString results match +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +class Calendar1 extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + return "A"; + } +} +class Calendar2 extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + return "A"; + } +} + +const plainDate1 = new Temporal.PlainDate(2000, 1, 1, new Calendar1()); +const plainDate2 = new Temporal.PlainDate(2000, 1, 2, new Calendar2()); +TemporalHelpers.assertDuration(plainDate1.until(plainDate2), 0, 0, 0, /* days = */ 1, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-mismatch.js new file mode 100644 index 000000000000..3b71261a8213 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-mismatch.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown if calendars' toString results do not match +features: [Temporal] +---*/ + +const calendar1 = { toString() { return "A"; } }; +const calendar2 = { toString() { return "B"; } }; + +const plainDate1 = new Temporal.PlainDate(2000, 1, 1, calendar1); +const plainDate2 = new Temporal.PlainDate(2000, 1, 1, calendar2); +assert.throws(RangeError, () => plainDate1.until(plainDate2)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-temporal-object.js new file mode 100644 index 000000000000..4959b40cf1a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const date = new Temporal.PlainDate(2000, 5, 2, temporalObject); + date.until({ year: 2005, month: 6, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-month.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-month.js new file mode 100644 index 000000000000..7c22d07b7ce3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-month.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: until() should take length of month into account. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate1 = Temporal.PlainDate.from("2019-01-01"); +const plainDate2 = Temporal.PlainDate.from("2019-02-01"); +const plainDate3 = Temporal.PlainDate.from("2019-03-01"); +TemporalHelpers.assertDuration(plainDate1.until(plainDate2), 0, 0, 0, /* days = */ 31, 0, 0, 0, 0, 0, 0, "January 2019"); +TemporalHelpers.assertDuration(plainDate2.until(plainDate3), 0, 0, 0, /* days = */ 28, 0, 0, 0, 0, 0, 0, "February 2019"); + +const plainDate4 = Temporal.PlainDate.from("2020-02-01"); +const plainDate5 = Temporal.PlainDate.from("2020-03-01"); +TemporalHelpers.assertDuration(plainDate4.until(plainDate5), 0, 0, 0, /* days = */ 29, 0, 0, 0, 0, 0, 0, "February 2020"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-year.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-year.js new file mode 100644 index 000000000000..7ab38e456716 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-year.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: until() should take length of year into account. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate1 = Temporal.PlainDate.from("2019-01-01"); +const plainDate2 = Temporal.PlainDate.from("2020-01-01"); +const plainDate3 = Temporal.PlainDate.from("2021-01-01"); +TemporalHelpers.assertDuration(plainDate1.until(plainDate2), 0, 0, 0, /* days = */ 365, 0, 0, 0, 0, 0, 0, "From January 2019"); +TemporalHelpers.assertDuration(plainDate2.until(plainDate3), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "From January 2020"); + +const plainDate4 = Temporal.PlainDate.from("2019-06-01"); +const plainDate5 = Temporal.PlainDate.from("2020-06-01"); +const plainDate6 = Temporal.PlainDate.from("2021-06-01"); +TemporalHelpers.assertDuration(plainDate4.until(plainDate5), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "From June 2019"); +TemporalHelpers.assertDuration(plainDate5.until(plainDate6), 0, 0, 0, /* days = */ 365, 0, 0, 0, 0, 0, 0, "From June 2020"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..44783d82248e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.until({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.until({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js new file mode 100644 index 000000000000..c087087eb22d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Default value for largestUnit option is days +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = Temporal.PlainDate.from("2020-02-01"); +const feb21 = Temporal.PlainDate.from("2021-02-01"); +TemporalHelpers.assertDuration(feb20.until(feb21), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no options"); +TemporalHelpers.assertDuration(feb20.until(feb21, undefined), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "undefined options"); +TemporalHelpers.assertDuration(feb20.until(feb21, {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no largestUnit"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: undefined }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "undefined largestUnit"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "days" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "auto" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "auto"); +TemporalHelpers.assertDuration(feb20.until(feb21, () => {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no largestUnit (function)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js new file mode 100644 index 000000000000..5f68a47561f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with higher largestUnit than the default of 'days' +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(1969, 7, 24); +const later = Temporal.PlainDate.from({ year: 2019, month: 7, day: 24 }); +const duration = date.until(later, { largestUnit: "years" }); +TemporalHelpers.assertDuration(duration, /* years = */ 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, "crossing epoch"); + +const feb20 = Temporal.PlainDate.from("2020-02-01"); +const feb21 = Temporal.PlainDate.from("2021-02-01"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, years"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, months"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 2, 0, 0, 0, 0, 0, 0, 0, "start of February, weeks"); + +const lastFeb20 = Temporal.PlainDate.from("2020-02-29"); +const lastFeb21 = Temporal.PlainDate.from("2021-02-28"); +TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "end of February, years"); +TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "end of February, months"); +TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 1, 0, 0, 0, 0, 0, 0, "end of February, weeks"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js new file mode 100644 index 000000000000..ddb3605a02cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const values = ["era", "eraYear", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..da6fd58154e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 12); +const validUnits = [ + "year", + "month", + "week", + "day", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => earlier.until(later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..1076456ec532 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const units = ["years", "months", "weeks", "days"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => earlier.until(later, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-undefined.js new file mode 100644 index 000000000000..466889d84b55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); + +const explicit = earlier.until(later, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-wrong-type.js new file mode 100644 index 000000000000..845670d0c3fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "year", + (largestUnit) => earlier.until(later, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/length.js new file mode 100644 index 000000000000..afde3474e51d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Temporal.PlainDate.prototype.until.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.until, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/name.js new file mode 100644 index 000000000000..7206168d5bc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Temporal.PlainDate.prototype.until.name is "until". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.until, "name", { + value: "until", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/not-a-constructor.js new file mode 100644 index 000000000000..12411162c518 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Temporal.PlainDate.prototype.until does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.until(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.until), false, + "isConstructor(Temporal.PlainDate.prototype.until)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-invalid.js new file mode 100644 index 000000000000..31a0678c0a54 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-invalid.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const feb20 = Temporal.PlainDate.from("2020-02-01"); +const feb21 = Temporal.PlainDate.from("2021-02-01"); +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +for (const badOptions of values) { + assert.throws(TypeError, () => feb20.until(feb21, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/prop-desc.js new file mode 100644 index 000000000000..8ba7869b13fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: The "until" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.until, + "function", + "`typeof PlainDate.prototype.until` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "until", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-relative.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-relative.js new file mode 100644 index 000000000000..2fe40ac01b37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-relative.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Should round relative to the receiver. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date1 = Temporal.PlainDate.from("2019-01-01"); +const date2 = Temporal.PlainDate.from("2019-02-15"); + +TemporalHelpers.assertDuration( + date1.until(date2, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ 2, 0, 0, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration( + date2.until(date1, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ -1, 0, 0, 0, 0, 0, 0, 0, 0); + +const cases = [ + ["2019-03-01", "2019-01-29", 1, 1], + ["2019-01-29", "2019-03-01", -1, -3], + ["2019-03-29", "2019-01-30", 1, 29], + ["2019-01-30", "2019-03-29", -1, -29], + ["2019-03-30", "2019-01-31", 1, 30], + ["2019-01-31", "2019-03-30", -1, -28], + ["2019-03-31", "2019-01-31", 2, 0], + ["2019-01-31", "2019-03-31", -2, 0] +]; +for (const [end, start, months, days] of cases) { + const result = Temporal.PlainDate.from(start).until(end, { largestUnit: "months" }); + TemporalHelpers.assertDuration(result, 0, months, 0, days, 0, 0, 0, 0, 0, 0, `${end} - ${start}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-nan.js new file mode 100644 index 000000000000..d446fd477f92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-non-integer.js new file mode 100644 index 000000000000..ddddab187572 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +const result = earlier.until(later, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..a8bd7cea5057 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-undefined.js new file mode 100644 index 000000000000..9c12127ad762 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); + +const explicit = earlier.until(later, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1"); + +// See options-undefined.js for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..c3904b787b08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => earlier.until(later, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement.js new file mode 100644 index 000000000000..898e5dcf34bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" }), + /* years = */ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingIncrement: 10, roundingMode: "halfExpand" }), + 0, /* months = */ 30, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "weeks", roundingIncrement: 12, roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ 144, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "days", roundingIncrement: 100, roundingMode: "halfExpand" }), + 0, 0, 0, /* days = */ 1000, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-ceil.js new file mode 100644 index 000000000000..66551064d3fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-ceil.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "ceil" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "years", roundingMode: "ceil" }), + /* years = */ -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "ceil" }), + 0, /* months = */ 32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "months", roundingMode: "ceil" }), + 0, /* months = */ -31, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "weeks", roundingMode: "ceil" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "weeks", roundingMode: "ceil" }), + 0, 0, /* weeks = */ -139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "days", roundingMode: "ceil" }), + 0, 0, 0, /* days = */ 973, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "days", roundingMode: "ceil" }), + 0, 0, 0, /* days = */ -973, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-floor.js new file mode 100644 index 000000000000..5d7c1e866bac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-floor.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "floor" }), + /* years = */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "years", roundingMode: "floor" }), + /* years = */ -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "floor" }), + 0, /* months = */ 31, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "months", roundingMode: "floor" }), + 0, /* months = */ -32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "weeks", roundingMode: "floor" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "weeks", roundingMode: "floor" }), + 0, 0, /* weeks = */ -139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "days", roundingMode: "floor" }), + 0, 0, 0, /* days = */ 973, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "days", roundingMode: "floor" }), + 0, 0, 0, /* days = */ -973, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfExpand.js new file mode 100644 index 000000000000..5dcc7effb060 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfExpand.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ 32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ -32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "weeks", roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "weeks", roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ -139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "days", roundingMode: "halfExpand" }), + 0, 0, 0, /* days = */ 973, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "days", roundingMode: "halfExpand" }), + 0, 0, 0, /* days = */ -973, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js new file mode 100644 index 000000000000..696d755ee04a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-trunc.js new file mode 100644 index 000000000000..1540ad9c79e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-trunc.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "trunc" }), + /* years = */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "years", roundingMode: "trunc" }), + /* years = */ -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "trunc" }), + 0, /* months = */ 31, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "months", roundingMode: "trunc" }), + 0, /* months = */ -31, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "weeks", roundingMode: "trunc" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "weeks", roundingMode: "trunc" }), + 0, 0, /* weeks = */ -139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "days", roundingMode: "trunc" }), + 0, 0, 0, /* days = */ 973, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "days", roundingMode: "trunc" }), + 0, 0, 0, /* days = */ -973, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-undefined.js new file mode 100644 index 000000000000..678f953ddba1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 1, 1); + +const later1 = new Temporal.PlainDate(2005, 2, 20); +const explicit1 = earlier.until(later1, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit1 = earlier.until(later1, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +const later2 = new Temporal.PlainDate(2005, 12, 15); +const explicit2 = earlier.until(later2, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit2 = earlier.until(later2, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-wrong-type.js new file mode 100644 index 000000000000..c5b2e8862356 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => earlier.until(later, { smallestUnit: "year", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-higher-units.js new file mode 100644 index 000000000000..4918ffe7237d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-higher-units.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with higher smallestUnit than the default of "days" +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ 32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "weeks", roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js new file mode 100644 index 000000000000..005e5a9b0ecc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const values = ["era", "eraYear", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..b013e0910732 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 12); +const validUnits = [ + "year", + "month", + "week", + "day", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => earlier.until(later, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-undefined.js new file mode 100644 index 000000000000..3617ceeeb234 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); + +const explicit = earlier.until(later, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-wrong-type.js new file mode 100644 index 000000000000..b9e1a3d2a923 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year", + (smallestUnit) => earlier.until(later, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/weeks-months.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/weeks-months.js new file mode 100644 index 000000000000..c1f0ab3e6443 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/weeks-months.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: until() should not return weeks and months together. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(1969, 7, 24); +const laterDate = new Temporal.PlainDate(1969, 9, 4); +TemporalHelpers.assertDuration(date.until(laterDate, { largestUnit: "weeks" }), + 0, 0, /* weeks = */ 6, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration(date.until(laterDate, { largestUnit: "months" }), + 0, /* months = */ 1, 0, 11, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/year-zero.js new file mode 100644 index 000000000000..87a320654da9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.PlainDate(2000, 5, 2); + +assert.throws( + RangeError, + () => { instance.until(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/basic.js new file mode 100644 index 000000000000..25b52ab089dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/basic.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.valueof +description: Basic tests for valueOf(). +features: [Temporal] +---*/ + +const plainDate = Temporal.PlainDate.from("1963-02-13"); +const plainDate2 = Temporal.PlainDate.from("1963-02-13"); + +assert.throws(TypeError, () => plainDate.valueOf(), "valueOf"); +assert.throws(TypeError, () => plainDate < plainDate, "<"); +assert.throws(TypeError, () => plainDate <= plainDate, "<="); +assert.throws(TypeError, () => plainDate > plainDate, ">"); +assert.throws(TypeError, () => plainDate >= plainDate, ">="); +assert.sameValue(plainDate === plainDate, true, "==="); +assert.sameValue(plainDate === plainDate2, false, "==="); +assert.sameValue(plainDate !== plainDate, false, "!=="); +assert.sameValue(plainDate !== plainDate2, true, "!=="); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/builtin.js new file mode 100644 index 000000000000..ee9d42b6ecfe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.valueof +description: > + Tests that Temporal.PlainDate.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/length.js new file mode 100644 index 000000000000..79847d291833 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.valueof +description: Temporal.PlainDate.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/name.js new file mode 100644 index 000000000000..16deae4d4d1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.valueof +description: Temporal.PlainDate.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/not-a-constructor.js new file mode 100644 index 000000000000..c1951c53d3fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.valueof +description: > + Temporal.PlainDate.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.valueOf), false, + "isConstructor(Temporal.PlainDate.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/prop-desc.js new file mode 100644 index 000000000000..99d5a55dc374 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.valueof +description: The "valueOf" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.valueOf, + "function", + "`typeof PlainDate.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/valueOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/weekOfYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/weekOfYear/basic.js new file mode 100644 index 000000000000..73390183df48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/weekOfYear/basic.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.weekofyear +description: Basic tests for weekOfYear(). +features: [Temporal] +---*/ + +for (let i = 29; i <= 31; ++i) { + const plainDate = new Temporal.PlainDate(1975, 12, i); + assert.sameValue(plainDate.weekOfYear, 1, `${plainDate} should be in week 1`); +} +for (let i = 1; i <= 4; ++i) { + const plainDate = new Temporal.PlainDate(1976, 1, i); + assert.sameValue(plainDate.weekOfYear, 1, `${plainDate} should be in week 1`); +} +for (let i = 5; i <= 11; ++i) { + const plainDate = new Temporal.PlainDate(1976, 1, i); + assert.sameValue(plainDate.weekOfYear, 2, `${plainDate} should be in week 2`); +} +for (let i = 20; i <= 26; ++i) { + const plainDate = new Temporal.PlainDate(1976, 12, i); + assert.sameValue(plainDate.weekOfYear, 52, `${plainDate} should be in week 52`); +} +for (let i = 27; i <= 31; ++i) { + const plainDate = new Temporal.PlainDate(1976, 12, i); + assert.sameValue(plainDate.weekOfYear, 53, `${plainDate} should be in week 53`); +} +for (let i = 1; i <= 2; ++i) { + const plainDate = new Temporal.PlainDate(1977, 1, i); + assert.sameValue(plainDate.weekOfYear, 53, `${plainDate} should be in week 53`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/weekOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/weekOfYear/prop-desc.js new file mode 100644 index 000000000000..80a4ce66113c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/weekOfYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.weekofyear +description: The "weekOfYear" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "weekOfYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/basic.js new file mode 100644 index 000000000000..bef2895efbd8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/basic.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Basic tests for with(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(1976, 11, 18); + +const withYear = plainDate.with({ year: 2019 }); +TemporalHelpers.assertPlainDate(withYear, 2019, 11, "M11", 18, "with(year)"); + +const withMonth = plainDate.with({ month: 5 }); +TemporalHelpers.assertPlainDate(withMonth, 1976, 5, "M05", 18, "with(month)"); + +const withMonthCode = plainDate.with({ monthCode: 'M05' }); +TemporalHelpers.assertPlainDate(withMonthCode, 1976, 5, "M05", 18, "with(monthCode)"); + +const withDay = plainDate.with({ day: 17 }); +TemporalHelpers.assertPlainDate(withDay, 1976, 11, "M11", 17, "with(day)"); + +const withPlural = plainDate.with({ months: 12, day: 15 }); +TemporalHelpers.assertPlainDate(withPlural, 1976, 11, "M11", 15, "with(plural)"); + +assert.throws(RangeError, () => plainDate.with({ month: 5, monthCode: 'M06' })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/builtin.js new file mode 100644 index 000000000000..ea95afbc14ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: > + Tests that Temporal.PlainDate.prototype.with + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.with), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.with), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.with), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.with.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/calendar-fields-iterable.js new file mode 100644 index 000000000000..10ec3a634147 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/calendar-fields-iterable.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.prototype.with step 9: + 9. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +date.with({ year: 2005 }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/calendar-merge-fields-returns-primitive.js new file mode 100644 index 000000000000..60d67974d63f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/calendar-merge-fields-returns-primitive.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: > + with() should throw a TypeError if mergeFields() returns a primitive, + without passing the value on to any other calendar methods +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive); + const instance = new Temporal.PlainDate(2000, 5, 2, calendar); + assert.throws(TypeError, () => instance.with({ year: 2005 }), "bad return from mergeFields() throws"); + assert.sameValue(calendar.dateFromFieldsCallCount, 0, "dateFromFields() never called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/copies-merge-fields-object.js new file mode 100644 index 000000000000..dc2bd310eb84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/copies-merge-fields-object.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: The object returned from mergeFields() is copied before being passed to dateFromFields(). +info: | + sec-temporal.plaindate.prototype.with steps 13–15: + 13. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialDate_). + 14. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»). + 15. Return ? DateFromFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get day", + "get day.valueOf", + "call day.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; + +const calendar = TemporalHelpers.calendarMergeFieldsGetters(); +const date = new Temporal.PlainDate(2021, 3, 31, calendar); +date.with({ year: 2022 }); + +assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/copy-properties-not-undefined.js new file mode 100644 index 000000000000..a6dc0b1f0222 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/copy-properties-not-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: PreparePartialTemporalFields copies only defined properties of source object +info: | + 4. For each value _property_ of _fieldNames_, do + a. Let _value_ be ? Get(_fields_, _property_). + b. If _value_ is not *undefined*, then + ... + iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(2006, 1, 24); + +TemporalHelpers.assertPlainDate(plainDate.with({ day: 1, year: undefined }), + 2006, 1, "M01", 1, + "only the properties that are present and defined in the plain object are copied" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..328aa741633f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.prototype.with +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.with({ [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.with({ [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/length.js new file mode 100644 index 000000000000..1abea0dbd679 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Temporal.PlainDate.prototype.with.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.with, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/name.js new file mode 100644 index 000000000000..bb11fd488b5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Temporal.PlainDate.prototype.with.name is "with". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/not-a-constructor.js new file mode 100644 index 000000000000..6c4e1981c73a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: > + Temporal.PlainDate.prototype.with does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.with(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.with), false, + "isConstructor(Temporal.PlainDate.prototype.with)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/options-invalid.js new file mode 100644 index 000000000000..2314e64eceea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/options-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(2000, 2, 2); +[null, true, "hello", Symbol("foo"), 1, 1n].forEach((badOptions) => + assert.throws(TypeError, () => plainDate.with({ day: 17 }, badOptions)) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/options-undefined.js new file mode 100644 index 000000000000..007b17919880 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 2, 2); +const fields = { day: 31 }; + +const explicit = date.with(fields, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = date.with(fields); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/order-of-operations.js new file mode 100644 index 000000000000..e84419c329a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/order-of-operations.js @@ -0,0 +1,55 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Properties on an object passed to with() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const expected = [ + "get calendar", + "get timeZone", + "get day", + "get day.valueOf", + "call day.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; +const actual = []; +const fields = { + year: 1.7, + month: 1.7, + monthCode: "M01", + day: 1.7, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.with(argument); +TemporalHelpers.assertPlainDate(result, 1, 1, "M01", 1); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js new file mode 100644 index 000000000000..d97f24c33da7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.with step 16: + 16. Return ? DateFromFields(_calendar_, _fields_, _options_). +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.with({ month: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-undefined.js new file mode 100644 index 000000000000..d62fac12aa81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.with step 16: + 16. Return ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const explicit = date.with({ month: 15 }, { overflow: undefined }); +TemporalHelpers.assertPlainDate(explicit, 2000, 12, "M12", 2, "default overflow is constrain"); +const implicit = date.with({ month: 15 }, {}); +TemporalHelpers.assertPlainDate(implicit, 2000, 12, "M12", 2, "default overflow is constrain"); +const fun = date.with({ month: 15 }, () => {}); +TemporalHelpers.assertPlainDate(fun, 2000, 12, "M12", 2, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-wrong-type.js new file mode 100644 index 000000000000..ceac2dd33c8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindate.prototype.with step 16: + 16. Return ? DateFromFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => date.with({ month: 8 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDate(result, 2000, 8, "M08", 2, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/plaindatelike-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/plaindatelike-invalid.js new file mode 100644 index 000000000000..c0c02016ba42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/plaindatelike-invalid.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Throws TypeError on an argument that is not a PlainDate-like property bag +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(1976, 11, 18); + +const tests = [ + // Step 3. + [undefined], + [null], + [true], + ["2019-05-17"], + ["2019-05-17T12:34"], + ["2019-05-17T12:34Z"], + ["18:05:42.577"], + ["42"], + [Symbol(), "symbol"], + [42, "number"], + [42n, "bigint"], + + // Step 4. + [Temporal.PlainDate.from("2019-05-17"), "PlainDate"], + [Temporal.PlainDateTime.from("2019-05-17T12:34"), "PlainDateTime"], + [Temporal.PlainMonthDay.from("2019-05-17"), "PlainMonthDay"], + [Temporal.PlainTime.from("12:34"), "PlainTime"], + [Temporal.PlainYearMonth.from("2019-05-17"), "PlainYearMonth"], + [Temporal.ZonedDateTime.from("2019-05-17T12:34Z[UTC]"), "ZonedDateTime"], + + // Step 5-6. + [{ year: 2021, calendar: "iso8601" }, "calendar"], + + // Step 7-8. + [{ year: 2021, timeZone: "UTC" }, "timeZone"], + + // Step 11. + [{}, "empty object"], + [{ months: 12 }, "only plural property"], + +]; + +for (const [value, message = String(value)] of tests) { + assert.throws(TypeError, () => plainDate.with(value), message); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/prop-desc.js new file mode 100644 index 000000000000..03bc76ce8cfa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: The "with" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.with, + "function", + "`typeof PlainDate.prototype.with` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "with", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/subclassing-ignored.js new file mode 100644 index 000000000000..bb24f862e782 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/with/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.with +description: Objects of a subclass are never created as return values for with() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDate, + [2000, 5, 2], + "with", + [{ day: 20 }], + (result) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 20), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/basic.js new file mode 100644 index 000000000000..58e2027d3288 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/basic.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: Basic tests for withCalendar(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate = Temporal.PlainDate.from("1976-11-18"); +const calendar = Temporal.Calendar.from("iso8601"); + +const objectResult = plainDate.withCalendar(calendar); +TemporalHelpers.assertPlainDate(objectResult, 1976, 11, "M11", 18, "object"); +assert.sameValue(objectResult.calendar, calendar, "object calendar"); + +const stringResult = plainDate.withCalendar("iso8601"); +TemporalHelpers.assertPlainDate(stringResult, 1976, 11, "M11", 18, "string"); +assert.sameValue(stringResult.calendar.id, "iso8601", "string calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/builtin.js new file mode 100644 index 000000000000..79840da4eb4c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: > + Tests that Temporal.PlainDate.prototype.withCalendar + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.withCalendar), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.withCalendar), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.withCalendar), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.withCalendar.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/calendar-temporal-object.js new file mode 100644 index 000000000000..3000fd3e2884 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/calendar-temporal-object.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.prototype.withcalendar step 3: + 3. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const plainDate = new Temporal.PlainDate(2000, 5, 2); + const result = plainDate.withCalendar(temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/length.js new file mode 100644 index 000000000000..83b8d8778d48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: Temporal.PlainDate.prototype.withCalendar.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.withCalendar, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/missing-argument.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/missing-argument.js new file mode 100644 index 000000000000..6f42f1118a68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/missing-argument.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: RangeError thrown when calendar argument not given +features: [Temporal] +---*/ + +const plainDate = Temporal.PlainDate.from("1976-11-18"); +assert.throws(RangeError, () => plainDate.withCalendar(), "missing argument"); +assert.throws(RangeError, () => plainDate.withCalendar(undefined), "undefined argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/name.js new file mode 100644 index 000000000000..d1561af73860 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: Temporal.PlainDate.prototype.withCalendar.name is "withCalendar". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.withCalendar, "name", { + value: "withCalendar", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/not-a-constructor.js new file mode 100644 index 000000000000..4d0fc088ed2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: > + Temporal.PlainDate.prototype.withCalendar does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.withCalendar(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.withCalendar), false, + "isConstructor(Temporal.PlainDate.prototype.withCalendar)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/prop-desc.js new file mode 100644 index 000000000000..a96031d1843b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: The "withCalendar" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.withCalendar, + "function", + "`typeof PlainDate.prototype.withCalendar` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "withCalendar", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/subclassing-ignored.js new file mode 100644 index 000000000000..d8688c934c86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/withCalendar/subclassing-ignored.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.withcalendar +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const customCalendar = { + era() { return undefined; }, + eraYear() { return undefined; }, + year() { return 1900; }, + month() { return 2; }, + monthCode() { return "M02"; }, + day() { return 5; }, + toString() { return "custom-calendar"; }, +}; + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDate, + [2000, 5, 2], + "withCalendar", + [customCalendar], + (result) => { + TemporalHelpers.assertPlainDate(result, 1900, 2, "M02", 5); + assert.sameValue(result.calendar, customCalendar, "calendar result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/year/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/year/calendar-returns-infinity.js new file mode 100644 index 000000000000..5409d989d09b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/year/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.year +description: Getter throws if the calendar returns ±∞ from its year method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + year() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainDate(2000, 5, 2, pos); +assert.throws(RangeError, () => instance1.year); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainDate(2000, 5, 2, neg); +assert.throws(RangeError, () => instance2.year); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/year/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/year/prop-desc.js new file mode 100644 index 000000000000..3447e8906147 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/year/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.year +description: The "year" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "year"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/shell.js index e69de29bb2d1..1d70b7579ee9 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDate/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/builtin.js new file mode 100644 index 000000000000..f30e466c29e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Tests that Temporal.PlainDateTime meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.PlainDateTime.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/calendar-temporal-object.js new file mode 100644 index 000000000000..bf42d14f53f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/calendar-temporal-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime step 11: + 11. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, temporalObject); + assert.sameValue(result.calendar, calendar, 'Temporal object coerced to calendar'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/calendar-undefined.js new file mode 100644 index 000000000000..abbc1c58c05e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/calendar-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Calendar argument defaults to the built-in ISO 8601 calendar +features: [Temporal] +---*/ + +const dateTimeArgs = [2020, 12, 24, 12, 34, 56, 123, 456, 789]; + +Object.defineProperty(Temporal.Calendar, "from", { + get() { + throw new Test262Error("Should not get Calendar.from"); + }, +}); + +const dateTimeExplicit = new Temporal.PlainDateTime(...dateTimeArgs, undefined); +assert.sameValue(dateTimeExplicit.calendar.toString(), "iso8601"); + +const dateTimeImplicit = new Temporal.PlainDateTime(...dateTimeArgs); +assert.sameValue(dateTimeImplicit.calendar.toString(), "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js new file mode 100644 index 000000000000..468106b637b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Plain object arguments may throw if they do not contain sufficient information +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.throws( + TypeError, + () => Temporal.PlainDateTime.compare({ year: 1976 }, dt2), + "object must contain at least the required properties (first arg)" +); + +assert.throws( + TypeError, + () => Temporal.PlainDateTime.compare(dt1, { year: 2019 }), + "object must contain at least the required properties (second arg)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-plaindate.js new file mode 100644 index 000000000000..256b1c734a5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-plaindate.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots +info: | + sec-temporal.plaindatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalDateTime(_one_). + 2. Set _two_ to ? ToTemporalDateTime(_two_). + sec-temporal-totemporaldatetime step 2.b: + b. If _item_ has an [[InitializedTemporalDate]] internal slot, then + i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date) => { + const result = Temporal.PlainDateTime.compare(date, datetime); + assert.sameValue(result, -1, "PlainDate is converted to midnight"); +}); + +TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date) => { + const result = Temporal.PlainDateTime.compare(datetime, date); + assert.sameValue(result, 1, "PlainDate is converted to midnight"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..13690c81b4f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-string-with-utc-designator.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: RangeError thrown if a string with UTC designator is used as a PlainDateTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const dateTime = new Temporal.PlainDateTime(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainDateTime.compare(arg, dateTime), + "String with UTC designator should not be valid as a PlainDateTime (first argument)" + ); + assert.throws( + RangeError, + () => Temporal.PlainDateTime.compare(arg, dateTime), + "String with UTC designator should not be valid as a PlainDateTime (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..da8670367553 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const zoned = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); +const plain = new Temporal.PlainDateTime(1969, 7, 24, 16, 50, 35, 0, 0, 1); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result1 = Temporal.PlainDateTime.compare(plain, zoned); +assert.sameValue(result1, 0); + +const result2 = Temporal.PlainDateTime.compare(zoned, plain); +assert.sameValue(result2, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..3ffaa8d52360 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, Infinity, -Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + + assert.throws(RangeError, () => Temporal.PlainDateTime.compare(datetime, plain)); + assert.throws(RangeError, () => Temporal.PlainDateTime.compare(plain, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..4a927df787d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.PlainDateTime.compare(datetime, plain), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); + assert.throws( + TypeError, + () => Temporal.PlainDateTime.compare(plain, datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..cb9980f4945c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + + assert.throws(RangeError, () => Temporal.PlainDateTime.compare(datetime, plain)); + assert.throws(RangeError, () => Temporal.PlainDateTime.compare(plain, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..9487f15b8a02 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + + assert.throws(TypeError, () => Temporal.PlainDateTime.compare(datetime, plain)); + assert.throws(TypeError, () => Temporal.PlainDateTime.compare(plain, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/basic.js new file mode 100644 index 000000000000..65f9123e65a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/basic.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Checking a typical case (nothing undefined, no NaNs, does not throw, etc.) +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt1, dt1), + 0, + "equal" +); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt1, dt2), + -1, + "smaller/larger" +); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt2, dt1), + 1, + "larger/smaller" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/builtin.js new file mode 100644 index 000000000000..d0a048b739f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Tests that Temporal.PlainDateTime.compare meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.compare), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.compare), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.compare), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.compare.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/calendar-fields-iterable.js new file mode 100644 index 000000000000..cb7d0774421e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/calendar-fields-iterable.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalDateTime(_one_). + 2. Set _two_ to ? ToTemporalDateTime(_two_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +Temporal.PlainDateTime.compare( + { year: 2000, month: 5, day: 2, calendar: calendar1 }, + { year: 2001, month: 6, day: 3, calendar: calendar2 }, +); + +assert.sameValue(calendar1.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar1.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar1.iteratorExhausted[0], "iterated through the whole iterable"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/calendar-temporal-object.js new file mode 100644 index 000000000000..9fb8e00c854a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/calendar-temporal-object.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalDateTime(_one_). + 2. Set _two_ to ? ToTemporalDateTime(_two_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + Temporal.PlainDateTime.compare( + { year: 2000, month: 5, day: 2, calendar: temporalObject }, + { year: 2001, month: 6, day: 3, calendar: temporalObject }, + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/cast.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/cast.js new file mode 100644 index 000000000000..a99651607c20 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/cast.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Arguments may be casted (string, plain object) +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.sameValue( + Temporal.PlainDateTime.compare({ year: 1976, month: 11, day: 18, hour: 15 }, dt2), + -1, + "casts first argument (plain object)" +); + +assert.sameValue( + Temporal.PlainDateTime.compare("1976-11-18T15:23:30.123456789", dt2), + -1, + "casts first argument (string)" +); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt1, { year: 2019, month: 10, day: 29, hour: 10 }), + -1, + "casts second argument (plain object)" +); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt1, "2019-10-29T10:46:38.271986102"), + -1, + "casts second argument (string)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..c5982da857fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.plaindatetime.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const other = new Temporal.PlainDateTime(2000, 5, 2, 15); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => Temporal.PlainDateTime.compare({ ...base, [prop]: inf }, other), `${prop} property cannot be ${inf}`); + + assert.throws(RangeError, () => Temporal.PlainDateTime.compare(other, { ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, prop); + assert.throws(RangeError, () => Temporal.PlainDateTime.compare({ ...base, [prop]: obj1 }, other)); + assert.compareArray(calls1, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, prop); + assert.throws(RangeError, () => Temporal.PlainDateTime.compare(other, { ...base, [prop]: obj2 })); + assert.compareArray(calls2, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/length.js new file mode 100644 index 000000000000..1300a9454d69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Temporal.PlainDateTime.compare.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.compare, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/name.js new file mode 100644 index 000000000000..ab74aefcdaa6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Temporal.PlainDateTime.compare.name is "compare" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.compare, "name", { + value: "compare", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/not-a-constructor.js new file mode 100644 index 000000000000..2f8e32b6ded2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Temporal.PlainDateTime.compare does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.compare(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.compare), false, + "isConstructor(Temporal.PlainDateTime.compare)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/prop-desc.js new file mode 100644 index 000000000000..eace313073a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: The "compare" property of Temporal.PlainDateTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.compare, + "function", + "`typeof PlainDateTime.compare` is `function`" +); + +verifyProperty(Temporal.PlainDateTime, "compare", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..a5c7dc8e6997 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/read-time-fields-before-datefromfields.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.plaindatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalDateTime(_one_). + 2. Set _two_ to ? ToTemporalDateTime(_two_). + sec-temporal-totemporaldatetime step 2.e: + e. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const result = Temporal.PlainDateTime.compare( + { year: 2000, month: 5, day: 2, hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321, calendar }, + { year: 2000, month: 5, day: 2, hour: 6, minute: 54, second: 32, millisecond: 123, microsecond: 456, nanosecond: 789, calendar }, +); + +// will be 0 if the time fields are coerced to their max values due to Infinity +assert.sameValue(result, 1, "comparison result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/use-internal-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/use-internal-slots.js new file mode 100644 index 000000000000..4c960631f590 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/use-internal-slots.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-compareisodatetime +description: compare() ignores the observable properties and uses internal slots +features: [Temporal] +---*/ + +function CustomError() {} + +class AvoidGettersDateTime extends Temporal.PlainDateTime { + get year() { + throw new CustomError(); + } + get month() { + throw new CustomError(); + } + get day() { + throw new CustomError(); + } + get hour() { + throw new CustomError(); + } + get minute() { + throw new CustomError(); + } + get second() { + throw new CustomError(); + } + get millisecond() { + throw new CustomError(); + } + get microsecond() { + throw new CustomError(); + } + get nanosecond() { + throw new CustomError(); + } +} + +const one = new AvoidGettersDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const two = new AvoidGettersDateTime(2006, 3, 25, 6, 54, 32, 123, 456, 789); +assert.sameValue(Temporal.PlainDateTime.compare(one, two), -1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/year-zero.js new file mode 100644 index 000000000000..d1bdf1c987f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/compare/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Negative zero, as an extended year, fails +esid: sec-temporal.plaindatetime.compare +features: [Temporal] +---*/ + +const ok = new Temporal.PlainDateTime(2000, 5, 2, 15); +const bad = "-000000-12-07T03:24:30"; + +assert.throws(RangeError, + () => Temporal.PlainDateTime.compare(bad,ok), + "Cannot use minus zero as extended year (first argument)" +); + +assert.throws(RangeError, + () => Temporal.PlainDateTime.compare(ok, bad), + "Cannot use minus zero as extended year (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/constructor-full.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/constructor-full.js new file mode 100644 index 000000000000..7abcf723eeed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/constructor-full.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Checking an explicitly constructed instance with all arguments +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); + +TemporalHelpers.assertPlainDateTime(datetime, + 1976, 11, "M11", 18, 15, 23, 30, 123, 456, 789, + "check instance (all arguments supplied)" +); + +assert.sameValue( + datetime.calendar, + calendar, + "calendar supplied in constructor can be extracted and is unchanged" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/constructor.js new file mode 100644 index 000000000000..a545a5b8eb81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Temporal.PlainDateTime constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.PlainDateTime()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/datetime-math.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/datetime-math.js new file mode 100644 index 000000000000..f54122e4c199 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/datetime-math.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Testing combinations of since, until, add, subtract, and negated +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const earlier = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const later = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); +const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"]; + +units.forEach((largestUnit) => { + const diff = later.since(earlier, { largestUnit }); + TemporalHelpers.assertDurationsEqual( + earlier.since(later, { largestUnit }), + diff.negated(), + `(${earlier}).since(${later}) == (${later}).since(${earlier}).negated()` + ); + TemporalHelpers.assertDurationsEqual( + earlier.until(later, { largestUnit }), + diff, + `(${earlier}).until(${later}) == (${later}).since(${earlier})` + ); + assert.sameValue( + earlier.add(diff).equals(later), + true, + `(${earlier}).add(${diff}) == (${later})` + ); + assert.sameValue( + later.subtract(diff).equals(earlier), + true, + `(${later}).subtract(${diff}) == (${earlier})` + ); + assert.sameValue( + earlier.subtract(diff.negated()).equals(later), + true, + "symmetrical with regard to negative durations (1)" + ); + assert.sameValue( + later.add(diff.negated()).equals(earlier), + true, + "symmetrical with regard to negative durations (2)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-plaindate.js new file mode 100644 index 000000000000..b7481a30673b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-plaindate.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots +info: | + sec-temporal.plaindatetime.from step 3: + 3. Return ? ToTemporalDateTime(_item_, _options_). + sec-temporal-totemporaldatetime step 2.b: + b. If _item_ has an [[InitializedTemporalDate]] internal slot, then + i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date, calendar) => { + const result = Temporal.PlainDateTime.from(date); + TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0, "midnight is assumed"); + assert.sameValue(result.calendar, calendar, "calendar result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..f3b1739d880e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-string-with-utc-designator.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: RangeError thrown if a string with UTC designator is used as a PlainDateTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainDateTime.from(arg), + "String with UTC designator should not be valid as a PlainDateTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..eb2b9d3008a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaldatetime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaindatetime.from step 3: + 3. Return ? ToTemporalDateTime(_temporalTime_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const pdt = Temporal.PlainDateTime.from(datetime); + +TemporalHelpers.assertPlainDateTime(pdt, 1970, 1, "M01", 1, 1, 1, 1, 1, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..7b9da21f28e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = Temporal.PlainDateTime.from(datetime); +TemporalHelpers.assertPlainDateTime(result, 1969, 7, "M07", 24, 16, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..e8b756432092 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => Temporal.PlainDateTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..80caa1fe2e18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaindatetime.from +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.PlainDateTime.from(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..3c8208ffe112 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => Temporal.PlainDateTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..cf5066b8fc49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => Temporal.PlainDateTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/builtin.js new file mode 100644 index 000000000000..27d004fd7805 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Tests that Temporal.PlainDateTime.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/calendar-fields-iterable.js new file mode 100644 index 000000000000..f345f5869c6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/calendar-fields-iterable.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.from step 3: + 3. Return ? ToTemporalDateTime(_item_, _options_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/calendar-temporal-object.js new file mode 100644 index 000000000000..7708ac0e9d47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime.from step 3: + 3. Return ? ToTemporalDateTime(_item_, _options_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..3146c4b01dc3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainDateTime.from({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => Temporal.PlainDateTime.from({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/length.js new file mode 100644 index 000000000000..c24cb424f65d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Temporal.PlainDateTime.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/name.js new file mode 100644 index 000000000000..a91cdecc0269 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Temporal.PlainDateTime.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/not-a-constructor.js new file mode 100644 index 000000000000..570f85f860b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Temporal.PlainDateTime.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.from), false, + "isConstructor(Temporal.PlainDateTime.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/options-undefined.js new file mode 100644 index 000000000000..69c8249f9d3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const fields = { year: 2000, month: 13, day: 2 }; + +const explicit = Temporal.PlainDateTime.from(fields, undefined); +assert.sameValue(explicit.month, 12, "default overflow is constrain"); + +const implicit = Temporal.PlainDateTime.from(fields); +assert.sameValue(implicit.month, 12, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/order-of-operations.js new file mode 100644 index 000000000000..ce49cb53284d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/order-of-operations.js @@ -0,0 +1,75 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Properties on an object passed to from() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get calendar", + "get day", + "get day.valueOf", + "call day.valueOf", + "get hour", + "get hour.valueOf", + "call hour.valueOf", + "get microsecond", + "get microsecond.valueOf", + "call microsecond.valueOf", + "get millisecond", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get minute", + "get minute.valueOf", + "call minute.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get nanosecond", + "get nanosecond.valueOf", + "call nanosecond.valueOf", + "get second", + "get second.valueOf", + "call second.valueOf", + "get year", + "get year.valueOf", + "call year.valueOf", +]; +const actual = []; +const fields = { + year: 1.7, + month: 1.7, + monthCode: "M01", + day: 1.7, + hour: 1.7, + minute: 1.7, + second: 1.7, + millisecond: 1.7, + microsecond: 1.7, + nanosecond: 1.7, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + if (key === "calendar") return Temporal.Calendar.from("iso8601"); + const result = target[key]; + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = Temporal.PlainDateTime.from(argument); +TemporalHelpers.assertPlainDateTime(result, 1, 1, "M01", 1, 1, 1, 1, 1, 1, 1); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js new file mode 100644 index 000000000000..d34fba3b9e02 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-totemporaldatetime steps 2–3: + 2. If Type(_item_) is Object, then + ... + g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + 3. Else, + a. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plaindatetime.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDateTime]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalDateTime(_item_, _options_). +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainDateTime(2000, 5, 2, 12), + { year: 2000, month: 5, day: 2, hour: 12 }, + "2000-05-02T12:00", +]; + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainDateTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-undefined.js new file mode 100644 index 000000000000..00c3fcd9b359 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-undefined.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-totemporaldatetime steps 2–3: + 2. If Type(_item_) is Object, then + ... + g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + 3. Else, + a. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plaindatetime.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDateTime]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalDateTime(_item_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainDateTime(2000, 5, 2, 12), + "2000-05-02T12:00", +]; +validValues.forEach((value) => { + const explicit = Temporal.PlainDateTime.from(value, { overflow: undefined }); + TemporalHelpers.assertPlainDateTime(explicit, 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, "overflow is ignored"); + const implicit = Temporal.PlainDateTime.from(value, {}); + TemporalHelpers.assertPlainDateTime(implicit, 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, "overflow is ignored"); +}); + +const propertyBag = { year: 2000, month: 13, day: 34, hour: 12 }; +const explicit = Temporal.PlainDateTime.from(propertyBag, { overflow: undefined }); +TemporalHelpers.assertPlainDateTime(explicit, 2000, 12, "M12", 31, 12, 0, 0, 0, 0, 0, "default overflow is constrain"); +const implicit = Temporal.PlainDateTime.from(propertyBag, {}); +TemporalHelpers.assertPlainDateTime(implicit, 2000, 12, "M12", 31, 12, 0, 0, 0, 0, 0, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-wrong-type.js new file mode 100644 index 000000000000..d15abae163ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/overflow-wrong-type.js @@ -0,0 +1,66 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-totemporaldatetime steps 2–3: + 2. If Type(_item_) is Object, then + ... + g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + 3. Else, + a. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plaindatetime.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDateTime]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalDateTime(_item_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainDateTime(2000, 5, 2, 12), + "2000-05-02T12:00", +]; +validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => Temporal.PlainDateTime.from(value, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, descr), +)); + +// See TemporalHelpers.checkStringOptionWrongType(); this code path has +// different expectations for observable calls +const propertyBag = { year: 2000, month: 5, day: 2, hour: 12 }; + +assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: null }), "null"); +assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: true }), "true"); +assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: false }), "false"); +assert.throws(TypeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: Symbol() }), "symbol"); +assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: 2n }), "bigint"); +assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: {} }), "plain object"); + +// toString property is read once by Calendar.dateFromFields() in the builtin +// calendars, to get the option value for the date part, and then once again +// internally to get the option value for the time part. +const expected = [ + "get overflow.toString", + "call overflow.toString", + "get overflow.toString", + "call overflow.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); +const result = Temporal.PlainDateTime.from(propertyBag, { overflow: observer }); +TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, "object with toString"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/parser.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/parser.js new file mode 100644 index 000000000000..a5fbe8add53b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/parser.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDateTime.from accepts a custom timezone that starts with "c". +esid: sec-temporal.plaindatetime.from +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dateTime = Temporal.PlainDateTime.from("2020-01-01T00:00:00+01:00[Custom]"); +TemporalHelpers.assertPlainDateTime(dateTime, 2020, 1, "M01", 1, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/prop-desc.js new file mode 100644 index 000000000000..a3a799e56ae0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: The "from" property of Temporal.PlainDateTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.from, + "function", + "`typeof PlainDateTime.from` is `function`" +); + +verifyProperty(Temporal.PlainDateTime, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..0c54705c83dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/read-time-fields-before-datefromfields.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.plaindatetime.from step 3: + 3. Return ? ToTemporalDateTime(_item_, _options_). + sec-temporal-totemporaldatetime step 2.e: + e. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321, calendar }); + +assert.sameValue(datetime.hour, 12, "hour value"); +assert.sameValue(datetime.minute, 34, "minute value"); +assert.sameValue(datetime.second, 56, "second value"); +assert.sameValue(datetime.millisecond, 987, "millisecond value"); +assert.sameValue(datetime.microsecond, 654, "microsecond value"); +assert.sameValue(datetime.nanosecond, 321, "nanosecond value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/subclassing-ignored.js new file mode 100644 index 000000000000..53093b1bfac2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/subclassing-ignored.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.PlainDateTime, + "from", + ["2000-05-02T12:34:56.987654321"], + (result) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 321), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/year-zero.js new file mode 100644 index 000000000000..6962a671d48e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/from/year-zero.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00[UTC]" +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { Temporal.PlainDateTime.from(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/hour-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/hour-undefined.js new file mode 100644 index 000000000000..3d847bda30f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/hour-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Hour argument defaults to 0 if not given +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const args = [2000, 5, 2]; + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0, + "hour default argument (argument present)" +); + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0, + "hour default argument (argument missing)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..d78080f6ee3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/infinity-throws-rangeerror.js @@ -0,0 +1,165 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDateTime throws a RangeError if any value is Infinity +esid: sec-temporal.plaindatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainDateTime(Infinity, 1, 1)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, Infinity, 1)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite year", + [O(Infinity, "year"), O(1, "month"), O(1, "day")], + ["get year.valueOf", "call year.valueOf" + ] + ], + [ + "infinite month", + [O(2, "year"), O(Infinity, "month"), O(1, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf" + ] + ], + [ + "infinite day", + [O(2, "year"), O(1, "month"), O(Infinity, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf" + ] + ], + [ + "infinite hour", + [O(2, "year"), O(1, "month"), O(1, "day"), O(Infinity, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf" + ] + ], + [ + "infinite minute", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(Infinity, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf" + ] + ], + [ + "infinite second", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(1, "minute"), O(Infinity, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf", + "get second.valueOf", + "call second.valueOf" + ] + ], + [ + "infinite millisecond", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(1, "minute"), O(1, "second"), O(Infinity, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf", + "get second.valueOf", + "call second.valueOf", + "get millisecond.valueOf", + "call millisecond.valueOf" + ] + ], + [ + "infinite microsecond", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(Infinity, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf", + "get second.valueOf", + "call second.valueOf", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get microsecond.valueOf", + "call microsecond.valueOf" + ] + ], + [ + "infinite nanosecond", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(Infinity, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf", + "get second.valueOf", + "call second.valueOf", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get microsecond.valueOf", + "call microsecond.valueOf", + "get nanosecond.valueOf", + "call nanosecond.valueOf" + ] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainDateTime(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/length.js new file mode 100644 index 000000000000..46bd4b0a1749 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Temporal.PlainDateTime.length is 3 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime, "length", { + value: 3, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/microsecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/microsecond-undefined.js new file mode 100644 index 000000000000..de522bfb69aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/microsecond-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Microsecond argument defaults to 0 if not given +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const args = [2000, 5, 2, 12, 34, 56, 123]; + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 34, 56, 123, 0, 0, + "microsecond default argument (argument present)" +); + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 34, 56, 123, 0, 0, + "microsecond default argument (argument missing)" +); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/millisecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/millisecond-undefined.js new file mode 100644 index 000000000000..61f1ae4e1653 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/millisecond-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Millisecond argument defaults to 0 if not given +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const args = [2000, 5, 2, 12, 34, 56]; + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, + "millisecond default argument (argument present)" +); + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, + "millisecond default argument (argument missing)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/minute-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/minute-undefined.js new file mode 100644 index 000000000000..3b2866160f84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/minute-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Minute argument defaults to 0 if not given +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const args = [2000, 5, 2, 12]; + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, + "minute default argument (argument present)" +); + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, + "minute default argument (argument missing)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/missing-arguments.js new file mode 100644 index 000000000000..2d14711875f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/missing-arguments.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: RangeError thrown after processing given args when invoked without all required args +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "valueOf year", + "valueOf month", +]; +const actual = []; +const args = [ + { valueOf() { actual.push("valueOf year"); return 1; } }, + { valueOf() { actual.push("valueOf month"); return 1; } }, +]; + +assert.throws(RangeError, () => new Temporal.PlainDateTime(...args)); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/name.js new file mode 100644 index 000000000000..3319db58942b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Temporal.PlainDateTime.name is "PlainDateTime" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime, "name", { + value: "PlainDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js new file mode 100644 index 000000000000..3673f5eee3fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Nanosecond argument defaults to 0 if not given +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const args = [2000, 5, 2, 12, 34, 56, 123, 456]; + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 34, 56, 123, 456, 0, + "nanosecond default argument (argument present)" +); + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 34, 56, 123, 456, 0, + "nanosecond default argument (argument missing)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..3d6b5ac1691c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/negative-infinity-throws-rangeerror.js @@ -0,0 +1,165 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDateTime throws a RangeError if any value is -Infinity +esid: sec-temporal.plaindatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainDateTime(-Infinity, 1, 1)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, -Infinity, 1)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, -Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite year", + [O(-Infinity, "year"), O(1, "month"), O(1, "day")], + ["get year.valueOf", "call year.valueOf" + ] + ], + [ + "infinite month", + [O(2, "year"), O(-Infinity, "month"), O(1, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf" + ] + ], + [ + "infinite day", + [O(2, "year"), O(1, "month"), O(-Infinity, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf" + ] + ], + [ + "infinite hour", + [O(2, "year"), O(1, "month"), O(1, "day"), O(-Infinity, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf" + ] + ], + [ + "infinite minute", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(-Infinity, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf" + ] + ], + [ + "infinite second", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(1, "minute"), O(-Infinity, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf", + "get second.valueOf", + "call second.valueOf" + ] + ], + [ + "infinite millisecond", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(1, "minute"), O(1, "second"), O(-Infinity, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf", + "get second.valueOf", + "call second.valueOf", + "get millisecond.valueOf", + "call millisecond.valueOf" + ] + ], + [ + "infinite microsecond", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(-Infinity, "microsecond"), O(1, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf", + "get second.valueOf", + "call second.valueOf", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get microsecond.valueOf", + "call microsecond.valueOf" + ] + ], + [ + "infinite nanosecond", + [O(2, "year"), O(1, "month"), O(1, "day"), O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(-Infinity, "nanosecond")], + [ + "get year.valueOf", + "call year.valueOf", + "get month.valueOf", + "call month.valueOf", + "get day.valueOf", + "call day.valueOf", + "get hour.valueOf", + "call hour.valueOf", + "get minute.valueOf", + "call minute.valueOf", + "get second.valueOf", + "call second.valueOf", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get microsecond.valueOf", + "call microsecond.valueOf", + "get nanosecond.valueOf", + "call nanosecond.valueOf" + ] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainDateTime(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/order-of-operations.js new file mode 100644 index 000000000000..bacd91e03092 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/order-of-operations.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Arguments are converted to primitives in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "get (argument 0).valueOf", + "call (argument 0).valueOf", + "get (argument 1).valueOf", + "call (argument 1).valueOf", + "get (argument 2).valueOf", + "call (argument 2).valueOf", + "get (argument 3).valueOf", + "call (argument 3).valueOf", + "get (argument 4).valueOf", + "call (argument 4).valueOf", + "get (argument 5).valueOf", + "call (argument 5).valueOf", + "get (argument 6).valueOf", + "call (argument 6).valueOf", + "get (argument 7).valueOf", + "call (argument 7).valueOf", + "get (argument 8).valueOf", + "call (argument 8).valueOf", +]; + +const dateTimeArgs = [2020, 12, 24, 12, 34, 56, 123, 456, 789].map((value, idx) => + TemporalHelpers.toPrimitiveObserver(actual, value, `(argument ${idx})`)); + +const dateTime = new Temporal.PlainDateTime(...dateTimeArgs, "iso8601"); +assert.compareArray(actual, expected); + +TemporalHelpers.assertPlainDateTime(dateTime, 2020, 12, "M12", 24, 12, 34, 56, 123, 456, 789); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prop-desc.js new file mode 100644 index 000000000000..541f9786700a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: The "PlainDateTime" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime, + "function", + "`typeof PlainDateTime` is `function`" +); + +verifyProperty(Temporal, "PlainDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js new file mode 100644 index 000000000000..d4424c7e1193 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Ambiguous addition is handled according to the overflow option +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ months: 1 }), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "constrain when ambiguous result (overflow options not supplied)" +); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ months: 1 }, { overflow: "constrain" }), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "constrain when ambiguous result (overflow options supplied)" +); + +assert.throws( + RangeError, + () => jan31.add({ months: 1 }, { overflow: "reject" }), + "throw when ambiguous result with reject" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js new file mode 100644 index 000000000000..358afc26b160 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Duration object arguments are handled +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.add(Temporal.Duration.from("P1MT1S")), + 2020, 2, "M02", 29, 15, 0, 1, 0, 0, 0, + "Duration argument" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-not-object.js new file mode 100644 index 000000000000..38668614e45c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Passing a primitive other than string to add() throws +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +assert.throws(RangeError, () => instance.add(undefined), "undefined"); +assert.throws(RangeError, () => instance.add(null), "null"); +assert.throws(RangeError, () => instance.add(true), "boolean"); +assert.throws(RangeError, () => instance.add(""), "empty string"); +assert.throws(TypeError, () => instance.add(Symbol()), "Symbol"); +assert.throws(RangeError, () => instance.add(7), "number"); +assert.throws(RangeError, () => instance.add(7n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js new file mode 100644 index 000000000000..6bbbfb85f1a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: At least one recognized property has to be present in argument +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +assert.throws( + TypeError, + () => jan31.add({}), + "empty object not acceptable" +); + +assert.throws( + TypeError, + () => jan31.add({ month: 12 }), // should be "months" + "misspelled property in argument throws if no other properties are present" +); + +assert.throws( + TypeError, + () => jan31.add({ nonsense: true }), + "unrecognized properties throw if no other recognized property is present" +); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ nonsense: 1, days: 1 }), + 2020, 2, "M02", 1, 15, 0, 0, 0, 0, 0, + "unrecognized properties ignored provided at least one recognized property is present" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js new file mode 100644 index 000000000000..2f7225c39f9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Positive and negative values in the temporalDurationLike argument are not acceptable +features: [Temporal] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +["constrain", "reject"].forEach((overflow) => { + assert.throws( + RangeError, + () => jan31.add({ hours: 1, minutes: -30 }, { overflow }), + `mixed positive and negative values always throw (overflow = "${overflow}")` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..67d9e66be9f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2); + +TemporalHelpers.assertPlainDateTime(datetime.add("PT1.03125H"), 2000, 5, "M05", 2, 1, 1, 52, 500, 0, 0, + "positive fractional units rounded with correct rounding mode"); +TemporalHelpers.assertPlainDateTime(datetime.add("-PT1.03125H"), 2000, 5, "M05", 1, 22, 58, 7, 500, 0, 0, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..d7027a99752f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2); + +const resultHours = instance.add("-PT24.567890123H"); +TemporalHelpers.assertPlainDateTime(resultHours, 2000, 4, "M04", 30, 23, 25, 55, 595, 557, 201, "negative fractional hours"); + +const resultMinutes = instance.add("-PT1440.567890123M"); +TemporalHelpers.assertPlainDateTime(resultMinutes, 2000, 4, "M04", 30, 23, 59, 25, 926, 592, 621, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string.js new file mode 100644 index 000000000000..3a13e61c681e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +const result = instance.add("P3D"); +TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 5, 0, 34, 56, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/balance-negative-time-units.js new file mode 100644 index 000000000000..80a8f800f8bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/balance-negative-time-units.js @@ -0,0 +1,52 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-adddatetime step 1: + 1. Let _timeResult_ be ? AddTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal.plaindatetime.prototype.add step 5: + 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1996, 5, 2, 1, 1, 1, 1, 1, 1); + +const result1 = datetime.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainDateTime(result1, 1996, 5, "M05", 2, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = datetime.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainDateTime(result2, 1996, 5, "M05", 2, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = datetime.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainDateTime(result3, 1996, 5, "M05", 2, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = datetime.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainDateTime(result4, 1996, 5, "M05", 2, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = datetime.add(new Temporal.Duration(0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainDateTime(result5, 1996, 5, "M05", 2, 0, 59, 1, 1, 1, 1, "minutes balance"); + +const result6 = datetime.add(new Temporal.Duration(0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainDateTime(result6, 1996, 5, "M05", 1, 23, 1, 1, 1, 1, 1, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/builtin.js new file mode 100644 index 000000000000..cdf071e265c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: > + Tests that Temporal.PlainDateTime.prototype.add + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.add), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.add), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.add), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.add.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js new file mode 100644 index 000000000000..13f8a4122be1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Testing overflow hours (adding hours that push one to the next/previous day) +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const earlier = new Temporal.PlainDateTime(2020, 5, 31, 23, 12, 38, 271, 986, 102); + +TemporalHelpers.assertPlainDateTime( + earlier.add({ hours: 2 }), + 2020, 6, "M06", 1, 1, 12, 38, 271, 986, 102, + "hours overflow (push to next day)" +); + +const later = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +TemporalHelpers.assertPlainDateTime( + later.add({ hours: -12 }), + 2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102, + "hours overflow (push to previous day)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..dad3c6bd158c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDateTime.prototype.add throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plaindatetime.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/length.js new file mode 100644 index 000000000000..d30f695ccaec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Temporal.PlainDateTime.prototype.add.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.add, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/name.js new file mode 100644 index 000000000000..5674e154d0b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Temporal.PlainDateTime.prototype.add.name is "add". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.add, "name", { + value: "add", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js new file mode 100644 index 000000000000..fc21d5959b58 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Negative durations can be supplied +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ minutes: -30 }), + 2020, 1, "M01", 31, 14, 30, 0, 0, 0, 0, + "negative minutes" +); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ seconds: -30 }), + 2020, 1, "M01", 31, 14, 59, 30, 0, 0, 0, + "negative seconds" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f80fa328c0f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDateTime.prototype.add throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plaindatetime.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..c3dbafa432f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.add({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/not-a-constructor.js new file mode 100644 index 000000000000..3875be229080 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: > + Temporal.PlainDateTime.prototype.add does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.add(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.add), false, + "isConstructor(Temporal.PlainDateTime.prototype.add)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js new file mode 100644 index 000000000000..685bafb0d308 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Verify that undefined options are handled correctly. +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ months: 1 }, {}), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "options may be empty object" +); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ months: 1 }, () => {}), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "options may be function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js new file mode 100644 index 000000000000..c252ac4c841c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Various invalid (wrong type) values for options argument +features: [Temporal, Symbol] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n]; + +badOptions.forEach((bad) => { + assert.throws( + TypeError, + () => jan31.add({ years: 1 }, bad), + `invalid options (${typeof bad})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-undefined.js new file mode 100644 index 000000000000..f2ffd4f4f643 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 1, 31, 12, 34, 56, 987, 654, 321); +const duration = { months: 1 }; + +const explicit = datetime.add(duration, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = datetime.add(duration); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/order-of-operations.js new file mode 100644 index 000000000000..ca4244a8c936 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Properties on an object passed to add() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.add(argument); +TemporalHelpers.assertPlainDateTime(result, 2001, 6, "M06", 10, 13, 35, 57, 988, 655, 322); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js new file mode 100644 index 000000000000..4415cfcc2f31 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-adddatetime step 4: + 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.plaindatetime.prototype.add step 5: + 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); +const duration = new Temporal.Duration(3, 3, 0, 3, 3); + + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.add({ months: 1 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-undefined.js new file mode 100644 index 000000000000..81a0a02519ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-undefined.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-adddatetime step 4: + 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.plaindatetime.prototype.add step 5: + 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 31, 12); +const duration = new Temporal.Duration(3, 1); + +const explicit = datetime.add(duration, { overflow: undefined }); +TemporalHelpers.assertPlainDateTime(explicit, 2003, 6, "M06", 30, 12, 0, 0, 0, 0, 0, "default overflow is constrain"); +const implicit = datetime.add(duration, {}); +TemporalHelpers.assertPlainDateTime(implicit, 2003, 6, "M06", 30, 12, 0, 0, 0, 0, 0, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-wrong-type.js new file mode 100644 index 000000000000..833124b0eb81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/overflow-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-adddatetime step 4: + 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.plaindatetime.prototype.add step 5: + 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); +const duration = new Temporal.Duration(3, 3, 0, 3, 3); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => datetime.add(duration, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2003, 8, "M08", 5, 15, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/prop-desc.js new file mode 100644 index 000000000000..81d5794512a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: The "add" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.add, + "function", + "`typeof PlainDateTime.prototype.add` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "add", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/subclassing-ignored.js new file mode 100644 index 000000000000..632c705e33c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/add/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Objects of a subclass are never created as return values for add() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDateTime, + [2000, 5, 2, 12, 34, 56, 987, 654, 321], + "add", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 322), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/calendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/calendar/prop-desc.js new file mode 100644 index 000000000000..1420ed897727 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/calendar/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.calendar +description: The "calendar" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "calendar"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/day/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/day/calendar-returns-infinity.js new file mode 100644 index 000000000000..c924aaacfb0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/day/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.day +description: Getter throws if the calendar returns ±∞ from its day method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + day() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, pos); +assert.throws(RangeError, () => instance1.day); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, neg); +assert.throws(RangeError, () => instance2.day); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/day/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/day/prop-desc.js new file mode 100644 index 000000000000..f0e5d368ba35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/day/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.day +description: The "day" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "day"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js new file mode 100644 index 000000000000..1f933cd54d36 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.dayofweek +description: Checking day of week for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.dayOfWeek, 4, "check day of week information"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/prop-desc.js new file mode 100644 index 000000000000..f48e03d745fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.dayofweek +description: The "dayOfWeek" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "dayOfWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js new file mode 100644 index 000000000000..ce9552f65b06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.dayofyear +description: Checking day of year for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.dayOfYear, 323, "check day of year information"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/prop-desc.js new file mode 100644 index 000000000000..c7864617a5f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.dayofyear +description: The "dayOfYear" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "dayOfYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js new file mode 100644 index 000000000000..337a11fbafae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinmonth +description: Checking days in month for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.daysInMonth, 30, "check days in month information"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/prop-desc.js new file mode 100644 index 000000000000..da31b4b1d496 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinmonth +description: The "daysInMonth" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "daysInMonth"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js new file mode 100644 index 000000000000..02a752f8fd5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinweek +description: Checking days in week for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.daysInWeek, 7, "check days in week information"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/prop-desc.js new file mode 100644 index 000000000000..0a528a0c8a8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinweek +description: The "daysInWeek" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "daysInWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js new file mode 100644 index 000000000000..4466fcc635eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinyear +description: Checking days in year for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.daysInYear, 366, "check days in year information"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInYear/prop-desc.js new file mode 100644 index 000000000000..958d959ef457 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/daysInYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinyear +description: The "daysInYear" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "daysInYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js new file mode 100644 index 000000000000..3c5241b9cd6a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: If argument is an object, it must contain sufficient information +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.throws( + TypeError, + () => dt.equals({ year: 1976 }), + "object must contain required properties" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-plaindate.js new file mode 100644 index 000000000000..01c30acff387 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-plaindate.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.b: + b. If _item_ has an [[InitializedTemporalDate]] internal slot, then + i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date, calendar) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 0, 0, 0, calendar); + assert(datetime.equals(date)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..0597bd120048 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: RangeError thrown if a string with UTC designator is used as a PlainDateTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "String with UTC designator should not be valid as a PlainDateTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-wrong-type.js new file mode 100644 index 000000000000..fd3742fdf23c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-wrong-type.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Appropriate error thrown when argument cannot be converted to a valid string +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +assert.throws(RangeError, () => instance.equals(undefined), "undefined"); +assert.throws(RangeError, () => instance.equals(null), "null"); +assert.throws(RangeError, () => instance.equals(true), "true"); +assert.throws(RangeError, () => instance.equals(""), "empty string"); +assert.throws(TypeError, () => instance.equals(Symbol()), "symbol"); +assert.throws(RangeError, () => instance.equals(1), "1"); +assert.throws(TypeError, () => instance.equals({}), "plain object"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainDateTime), "Temporal.PlainDateTime"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainDateTime.prototype), "Temporal.PlainDateTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..bce8a920cfd6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaldatetime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaindatetime.prototype.until step 3: + 3. Set _other_ ? ToTemporalDateTime(_other_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +assert(new Temporal.PlainDateTime(1970, 1, 1, 1, 1, 1, 1, 0, 999).equals(datetime)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..2e802d7eb866 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainDateTime(1969, 7, 24, 16, 50, 35, 0, 0, 1); +const result = instance.equals(datetime); +assert.sameValue(result, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..4d87d941321d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.equals(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..1d3a15d08914 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => plain.equals(zoned), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..d830bc5186b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.equals(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..ae52d498cfca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => plain.equals(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js new file mode 100644 index 000000000000..6a19a4256506 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Checking a typical case (everything defined, no NaNs, nothing throws, etc.) +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.sameValue(dt1.equals(dt1), true, "equal"); +assert.sameValue(dt1.equals(dt2), false, "unequal"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/builtin.js new file mode 100644 index 000000000000..9ab6e7a4bd3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: > + Tests that Temporal.PlainDateTime.prototype.equals + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.equals), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.equals), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.equals), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.equals.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-fields-iterable.js new file mode 100644 index 000000000000..c4d258197218 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-fields-iterable.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +datetime.equals({ year: 2005, month: 6, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-temporal-object.js new file mode 100644 index 000000000000..add5c68cbae8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, temporalObject); + datetime.equals({ year: 2005, month: 6, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js new file mode 100644 index 000000000000..46ea791ad317 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Argument may be cast +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.sameValue( + dt1.equals({ + year: 1976, + month: 11, + day: 18, + hour: 15, + minute: 23, + second: 30, + millisecond: 123, + microsecond: 456, + nanosecond: 789 + }), + true, + "casts argument (plain object, positive)" +); + + +assert.sameValue( + dt2.equals({ year: 1976, month: 11, day: 18, hour: 15 }), + false, + "casts argument (plain object, negative)" +); + +assert.sameValue( + dt1.equals("1976-11-18T15:23:30.123456789"), + true, + "casts argument (string, positive)" +); + +assert.sameValue( + dt2.equals("1976-11-18T15:23:30.123456789"), + false, + "casts argument (string, negative)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..d8371db96d74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/length.js new file mode 100644 index 000000000000..ffe5bcf80272 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Temporal.PlainDateTime.prototype.equals.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.equals, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/name.js new file mode 100644 index 000000000000..09b044c2ee20 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Temporal.PlainDateTime.prototype.equals.name is "equals". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.equals, "name", { + value: "equals", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/not-a-constructor.js new file mode 100644 index 000000000000..3deac8435b68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: > + Temporal.PlainDateTime.prototype.equals does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.equals(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.equals), false, + "isConstructor(Temporal.PlainDateTime.prototype.equals)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/prop-desc.js new file mode 100644 index 000000000000..793c615eb91f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: The "equals" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.equals, + "function", + "`typeof PlainDateTime.prototype.equals` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "equals", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..bfc29d0b2749 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/read-time-fields-before-datefromfields.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.plaindatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.e: + e. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = new Temporal.PlainDateTime(2021, 3, 31, 12, 34, 56, 987, 654, 321, calendar); +const result = datetime.equals({ year: 2021, month: 3, day: 31, hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321, calendar }); + +assert(result, "time fields are not modified"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/year-zero.js new file mode 100644 index 000000000000..4ca9b24c241e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/equals/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00[UTC]" +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { instance.equals(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/builtin.js new file mode 100644 index 000000000000..0d8d1cf34df9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.getisofields +description: > + Tests that Temporal.PlainDateTime.prototype.getISOFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.getISOFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.getISOFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.getISOFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.getISOFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-names.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-names.js new file mode 100644 index 000000000000..c42309ae4ffb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-names.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.getisofields +description: Correct field names on the object returned from getISOFields +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +const result = datetime.getISOFields(); +assert.sameValue(result.isoYear, 2000, "isoYear result"); +assert.sameValue(result.isoMonth, 5, "isoMonth result"); +assert.sameValue(result.isoDay, 2, "isoDay result"); +assert.sameValue(result.isoHour, 12, "isoHour result"); +assert.sameValue(result.isoMinute, 34, "isoMinute result"); +assert.sameValue(result.isoSecond, 56, "isoSecond result"); +assert.sameValue(result.isoMillisecond, 987, "isoMillisecond result"); +assert.sameValue(result.isoMicrosecond, 654, "isoMicrosecond result"); +assert.sameValue(result.isoNanosecond, 321, "isoNanosecond result"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-prop-desc.js new file mode 100644 index 000000000000..8f050b96f6a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-prop-desc.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.getisofields +description: Properties on the returned object have the correct descriptor +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoHour", + "isoMicrosecond", + "isoMillisecond", + "isoMinute", + "isoMonth", + "isoNanosecond", + "isoSecond", + "isoYear", +]; + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const result = datetime.getISOFields(); + +for (const property of expected) { + verifyProperty(result, property, { + writable: true, + enumerable: true, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-traversal-order.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-traversal-order.js new file mode 100644 index 000000000000..c3d3bb6e712a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/field-traversal-order.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.getisofields +description: Properties added in correct order to object returned from getISOFields +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoHour", + "isoMicrosecond", + "isoMillisecond", + "isoMinute", + "isoMonth", + "isoNanosecond", + "isoSecond", + "isoYear", +]; + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const result = datetime.getISOFields(); + +assert.compareArray(Object.keys(result), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/length.js new file mode 100644 index 000000000000..c1a8e2204cad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.getisofields +description: Temporal.PlainDateTime.prototype.getISOFields.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.getISOFields, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/name.js new file mode 100644 index 000000000000..a1af9e96b33b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.getisofields +description: Temporal.PlainDateTime.prototype.getISOFields.name is "getISOFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.getISOFields, "name", { + value: "getISOFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/not-a-constructor.js new file mode 100644 index 000000000000..6e3576c6cee8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.getisofields +description: > + Temporal.PlainDateTime.prototype.getISOFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.getISOFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.getISOFields), false, + "isConstructor(Temporal.PlainDateTime.prototype.getISOFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/prop-desc.js new file mode 100644 index 000000000000..4aafde07ef6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.getisofields +description: The "getISOFields" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.getISOFields, + "function", + "`typeof PlainDateTime.prototype.getISOFields` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "getISOFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/getISOFields/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/hour/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/hour/prop-desc.js new file mode 100644 index 000000000000..a8ce30a04035 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/hour/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.hour +description: The "hour" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "hour"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/inLeapYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/inLeapYear/prop-desc.js new file mode 100644 index 000000000000..154e7c1e8f24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/inLeapYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.inleapyear +description: The "inLeapYear" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "inLeapYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/microsecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/microsecond/prop-desc.js new file mode 100644 index 000000000000..71e9a3325e62 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/microsecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.microsecond +description: The "microsecond" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "microsecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/millisecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/millisecond/prop-desc.js new file mode 100644 index 000000000000..414119117b4c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/millisecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.millisecond +description: The "millisecond" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "millisecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/minute/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/minute/prop-desc.js new file mode 100644 index 000000000000..2b3a85c1d64d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/minute/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.minute +description: The "minute" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "minute"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/month/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/month/calendar-returns-infinity.js new file mode 100644 index 000000000000..7614da4b1bc7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/month/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.month +description: Getter throws if the calendar returns ±∞ from its month method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + month() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, pos); +assert.throws(RangeError, () => instance1.month); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, neg); +assert.throws(RangeError, () => instance2.month); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/month/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/month/prop-desc.js new file mode 100644 index 000000000000..27b5949d30f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/month/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.month +description: The "month" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "month"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthCode/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthCode/prop-desc.js new file mode 100644 index 000000000000..1bdb340e464a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthCode/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.monthcode +description: The "monthCode" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "monthCode"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js new file mode 100644 index 000000000000..edae9f578536 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.monthsinyear +description: Checking months in year for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.monthsInYear, 12, "check months in year information"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/prop-desc.js new file mode 100644 index 000000000000..817db328749a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.monthsinyear +description: The "monthsInYear" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "monthsInYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/nanosecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/nanosecond/prop-desc.js new file mode 100644 index 000000000000..f760695c1bd2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/nanosecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.nanosecond +description: The "nanosecond" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "nanosecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/prop-desc.js new file mode 100644 index 000000000000..e81046f6b02d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-plaindatetime-prototype +description: The "prototype" property of Temporal.PlainDateTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.PlainDateTime.prototype, "object"); +assert.notSameValue(Temporal.PlainDateTime.prototype, null); + +verifyProperty(Temporal.PlainDateTime, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/builtin.js new file mode 100644 index 000000000000..72b9e642f5ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: > + Tests that Temporal.PlainDateTime.prototype.round + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.round), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.round), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.round), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.round.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/length.js new file mode 100644 index 000000000000..902a11761010 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Temporal.PlainDateTime.prototype.round.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.round, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/name.js new file mode 100644 index 000000000000..e8fbd750bf1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Temporal.PlainDateTime.prototype.round.name is "round". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.round, "name", { + value: "round", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/not-a-constructor.js new file mode 100644 index 000000000000..22493e2467d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: > + Temporal.PlainDateTime.prototype.round does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.round(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.round), false, + "isConstructor(Temporal.PlainDateTime.prototype.round)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/prop-desc.js new file mode 100644 index 000000000000..4eb1ef31237f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: The "round" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.round, + "function", + "`typeof PlainDateTime.prototype.round` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "round", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-nan.js new file mode 100644 index 000000000000..93c8c552be7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-nan.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal-totemporaldatetimeroundingincrement step 5: + 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*). + sec-temporal.plaindatetime.prototype.round step 8: + 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +assert.throws(RangeError, () => datetime.round({ smallestUnit: 'second', roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-non-integer.js new file mode 100644 index 000000000000..7e665d468846 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 5); +const result = datetime.round({ smallestUnit: "nanosecond", roundingIncrement: 2.5 }); +TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 6, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..3cd495f9eeca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "nanoseconds", roundingIncrement: -Infinity })); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "nanoseconds", roundingIncrement: -1 })); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "nanoseconds", roundingIncrement: 0 })); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "nanoseconds", roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-undefined.js new file mode 100644 index 000000000000..e68dea511871 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal-totemporaldatetimeroundingincrement step 5: + 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*). + sec-temporal.plaindatetime.prototype.round step 8: + 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +const explicit = datetime.round({ smallestUnit: 'second', roundingIncrement: undefined }); +TemporalHelpers.assertPlainDateTime(explicit, 2000, 5, "M05", 2, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1"); + +const implicit = datetime.round({ smallestUnit: 'second' }); +TemporalHelpers.assertPlainDateTime(implicit, 2000, 5, "M05", 2, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..bc4da94a2c45 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal-totemporaldatetimeroundingincrement step 5: + 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*). + sec-temporal.plaindatetime.prototype.round step 8: + 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => datetime.round({ smallestUnit: 'second', roundingIncrement }), + (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 57, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-invalid-string.js new file mode 100644 index 000000000000..d19ca8197958 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => datetime.round({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-undefined.js new file mode 100644 index 000000000000..4bf4f5fc0b6a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); + +const explicit1 = datetime.round({ smallestUnit: "microsecond", roundingMode: undefined }); +TemporalHelpers.assertPlainDateTime(explicit1, 2000, 5, "M05", 2, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand"); +const implicit1 = datetime.round({ smallestUnit: "microsecond" }); +TemporalHelpers.assertPlainDateTime(implicit1, 2000, 5, "M05", 2, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand"); + +const explicit2 = datetime.round({ smallestUnit: "millisecond", roundingMode: undefined }); +TemporalHelpers.assertPlainDateTime(explicit2, 2000, 5, "M05", 2, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand"); +const implicit2 = datetime.round({ smallestUnit: "millisecond" }); +TemporalHelpers.assertPlainDateTime(implicit2, 2000, 5, "M05", 2, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand"); + +const explicit3 = datetime.round({ smallestUnit: "second", roundingMode: undefined }); +TemporalHelpers.assertPlainDateTime(explicit3, 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand"); +const implicit3 = datetime.round({ smallestUnit: "second" }); +TemporalHelpers.assertPlainDateTime(implicit3, 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-wrong-type.js new file mode 100644 index 000000000000..ba1f909724bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand", + (roundingMode) => datetime.round({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 123, 988, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-disallowed-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-disallowed-units.js new file mode 100644 index 000000000000..2ccc733e297e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-disallowed-units.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Specifically disallowed units for the smallestUnit option +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 789, 999, 999); +const invalidUnits = [ + "era", + "eras", + "year", + "month", + "week", + "years", + "months", + "weeks", +]; +invalidUnits.forEach((smallestUnit) => { + assert.throws( + RangeError, + () => instance.round({ smallestUnit }), + `{ smallestUnit: "${smallestUnit}" } should not be allowed as an argument to round` + ); + assert.throws( + RangeError, + () => instance.round(smallestUnit), + `"${smallestUnit}" should not be allowed as an argument to round` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-invalid-string.js new file mode 100644 index 000000000000..7626ceec045d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-invalid-string.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..7974e35eb575 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-plurals-accepted.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 789, 999, 999); +const validUnits = [ + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => datetime.round({ smallestUnit }), validUnits); +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => datetime.round(smallestUnit), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-string-shorthand.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-string-shorthand.js new file mode 100644 index 000000000000..46759b97d9d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-string-shorthand.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: String as first argument is equivalent to options bag with smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 789, 999, 999); +const validUnits = [ + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +validUnits.forEach((smallestUnit) => { + const full = instance.round({ smallestUnit }); + const shorthand = instance.round(smallestUnit); + TemporalHelpers.assertPlainDateTimesEqual(shorthand, full, `"${smallestUnit}" as first argument to round is equivalent to options bag`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-wrong-type.js new file mode 100644 index 000000000000..865f3276dec9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => datetime.round({ smallestUnit }), + (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 123, 988, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/subclassing-ignored.js new file mode 100644 index 000000000000..35ae9650f14f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/round/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDateTime, + [2000, 5, 2, 12, 34, 56, 987, 654, 321], + "round", + [{ smallestUnit: 'second' }], + (result) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 57, 0, 0, 0), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/second/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/second/prop-desc.js new file mode 100644 index 000000000000..b285d915c2dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/second/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.second +description: The "second" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "second"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-plaindate.js new file mode 100644 index 000000000000..c716ed8ec1e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-plaindate.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.b: + b. If _item_ has an [[InitializedTemporalDate]] internal slot, then + i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date, calendar) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 987, 654, 321, calendar); + const result = datetime.since(date); + assert.sameValue(result.total({ unit: "nanoseconds" }), 987654321, "PlainDate is converted to midnight"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..b10564ce7f65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown if a string with UTC designator is used as a PlainDateTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + "String with UTC designator should not be valid as a PlainDateTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..598b1cfcd8d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaldatetime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaindatetime.prototype.since step 3: + 3. Set _other_ ? ToTemporalDateTime(_other_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const diff = new Temporal.PlainDateTime(1970, 1, 1).since(datetime); + +TemporalHelpers.assertDuration(diff, 0, 0, 0, 0, -1, -1, -1, -1, 0, -999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..105eae540a52 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321); +const result = instance.since(datetime); +TemporalHelpers.assertDuration(result, 0, 0, 0, 11239, 22, 40, 10, 987, 654, 320); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..e40000e64782 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.since(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..f9eb28db5708 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => plain.since(zoned), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..0754c1e68ccc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.since(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..c6cb4f9ec913 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => plain.since(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-duration.js new file mode 100644 index 000000000000..6aa1a2455c62 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-duration.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Negative durations are balanced correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-balanceduration step 4: + 4. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + sec-temporal-differenceisodatetime steps 7 and 13: + 7. If _timeSign_ is -_dateSign_, then + ... + b. Set _timeDifference_ to ? BalanceDuration(-_timeSign_, _timeDifference_.[[Hours]], _timeDifference_.[[Minutes]], _timeDifference_.[[Seconds]], _timeDifference_.[[Milliseconds]], _timeDifference_.[[Microseconds]], _timeDifference_.[[Nanoseconds]], _largestUnit_). + ... + 16. Return ? BalanceDuration(_dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], _dateDifference_.[[Days]], _timeDifference_.[[Hours]], _timeDifference_.[[Minutes]], _timeDifference_.[[Seconds]], _timeDifference_.[[Milliseconds]], _timeDifference_.[[Microseconds]], _timeDifference_.[[Nanoseconds]], _largestUnit_). + sec-temporal.plaindatetime.prototype.since step 14: + 14. Let _diff_ be ? DifferenceISODateTime(_other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _largestUnit_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier1 = new Temporal.PlainDateTime(2000, 5, 2, 9); +const later1 = new Temporal.PlainDateTime(2000, 5, 5, 10); +const result1 = later1.since(earlier1, { largestUnit: 'day' }); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, "date sign == time sign"); + +const earlier2 = new Temporal.PlainDateTime(2000, 5, 2, 10); +const later2 = new Temporal.PlainDateTime(2000, 5, 5, 9); +const result2 = later2.since(earlier2, { largestUnit: 'day' }); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 2, 23, 0, 0, 0, 0, 0, "date sign != time sign"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-time-units.js new file mode 100644 index 000000000000..73f8e311d770 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-time-units.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-differenceisodatetime step 2: + 2. Let _timeDifference_ be ? DifferenceTime(_h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_). + sec-temporal.plaindatetime.prototype.since step 14: + 14. Let _diff_ be ? DifferenceISODateTime(_other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _largestUnit_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1996, 5, 2, 1, 1, 1, 1, 1, 1); + +const result1 = datetime.since(new Temporal.PlainDateTime(1996, 5, 2, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = datetime.since(new Temporal.PlainDateTime(1996, 5, 2, 0, 0, 0, 0, 2)); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = datetime.since(new Temporal.PlainDateTime(1996, 5, 2, 0, 0, 0, 2)); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = datetime.since(new Temporal.PlainDateTime(1996, 5, 2, 0, 0, 2)); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = datetime.since(new Temporal.PlainDateTime(1996, 5, 2, 0, 2)); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = datetime.since(new Temporal.PlainDateTime(1996, 5, 2, 2)); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/builtin.js new file mode 100644 index 000000000000..ef7f82e66ea5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: > + Tests that Temporal.PlainDateTime.prototype.since + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.since), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.since), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.since), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.since.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..77a4d25fd715 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, calendar); +instance.since(new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 0, 0, 0, calendar), { smallestUnit: "month" }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-copy-of-options.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-copy-of-options.js new file mode 100644 index 000000000000..e1046b957f11 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-copy-of-options.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: The dateUntil() method on the calendar is called with a copy of the options bag +features: [Temporal] +---*/ + +const originalOptions = { + largestUnit: "year", + shouldBeCopied: {}, +}; +let called = false; + +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(d1, d2, options) { + called = true; + assert.notSameValue(options, originalOptions, "options bag should be a copy"); + assert.sameValue(options.shouldBeCopied, originalOptions.shouldBeCopied, "options bag should be a shallow copy"); + return new Temporal.Duration(); + } +} +const calendar = new Calendar(); +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322, calendar); +earlier.since(later, originalOptions); +assert(called, "calendar.dateUntil must be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-plaindate-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-plaindate-calendar.js new file mode 100644 index 000000000000..5f3822241229 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-plaindate-calendar.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: calendar.dateUntil() is passed PlainDate objects with the receiver's calendar +info: | + DifferenceISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2, calendar, largestUnit [ , options ] ) + + 8. Let _date1_ be ? CreateTemporalDate(_balanceResult_.[[Year]], _balanceResult_.[[Month]], _balanceResult_.[[Day]], _calendar_). + 9. Let _date2_ be ? CreateTemporalDate(_y2_, _mon2_, _d2_, _calendar_). + 12. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +features: [Temporal] +---*/ + +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(d1, d2) { + assert.sameValue(d1.calendar, this, "d1.calendar"); + assert.sameValue(d2.calendar, this, "d2.calendar"); + return new Temporal.Duration(); + } +} +const calendar = new Calendar(); +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322, calendar); +const result = earlier.since(later); +assert(result instanceof Temporal.Duration, "result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..7fd3bdebec0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.plaindatetime.prototype.since step 14: + 14. Let _diff_ be ? DifferenceISODateTime(_other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _largestUnit_, _options_). + sec-temporal-differenceisodatetime steps 9–11: + 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). + 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322, calendar); + later.since(earlier, { largestUnit }); + }, + { + years: ["year"], + months: ["month"], + weeks: ["week"], + days: ["day"], + hours: ["day"], + minutes: ["day"], + seconds: ["day"], + milliseconds: ["day"], + microseconds: ["day"], + nanoseconds: ["day"] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-fields-iterable.js new file mode 100644 index 000000000000..2c6c7cba3080 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-fields-iterable.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +datetime.since({ year: 2005, month: 6, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-temporal-object.js new file mode 100644 index 000000000000..2b4ffb28bcf2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, temporalObject); + datetime.since({ year: 2005, month: 6, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..de8f728ade56 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.since +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.since({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.since({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string.js new file mode 100644 index 000000000000..23ce028f885c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); +const values = ["era", "eraYear", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..63fabddfd8d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 12, 13, 35, 57, 988, 655, 322); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => later.since(earlier, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..2b8df138a9e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); +const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => later.since(earlier, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-undefined.js new file mode 100644 index 000000000000..1fb1a7c90312 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); + +const explicit = later.since(earlier, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 1, 1, 1, 987, 654, 321, "default largestUnit is day"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 1, 1, 1, 987, 654, 321, "default largestUnit is day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-wrong-type.js new file mode 100644 index 000000000000..255c37f299bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "year", + (largestUnit) => later.since(earlier, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 1, 1, 1, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit.js new file mode 100644 index 000000000000..da247d4cfe3b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/largestunit.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Specify behavior of PlainDateTime.since when largest specified unit is years or months. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ +const lastFeb20 = new Temporal.PlainDateTime(2020, 2, 20, 5, 45, 20); +const lastFeb21 = new Temporal.PlainDateTime(2021, 2, 21, 17, 18, 57); +TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20), 0, 0, 0, 367, 11, 33, 37, 0, 0, 0, 'does not include higher units than necessary (largest unit unspecified)'); +TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: 'months' }), 0, 12, 0, 1, 11, 33, 37, 0, 0, 0, 'does not include higher units than necessary (largest unit is months)'); +TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: 'years' }), 1, 0, 0, 1, 11, 33, 37, 0, 0, 0, 'does not include higher units than necessary (largest unit is years)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/length.js new file mode 100644 index 000000000000..50fa7f3187f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Temporal.PlainDateTime.prototype.since.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.since, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/name.js new file mode 100644 index 000000000000..0d8c058ce721 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Temporal.PlainDateTime.prototype.since.name is "since". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.since, "name", { + value: "since", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/not-a-constructor.js new file mode 100644 index 000000000000..9c056f1a1f34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: > + Temporal.PlainDateTime.prototype.since does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.since(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.since), false, + "isConstructor(Temporal.PlainDateTime.prototype.since)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/options-undefined.js new file mode 100644 index 000000000000..5887c30e18da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/options-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2000, 6, 12, 12, 34, 56, 987, 654, 322); + +const explicit = later.since(earlier, undefined); +assert.sameValue(explicit.years, 0, "default largest unit is days"); +assert.sameValue(explicit.months, 0, "default largest unit is days"); +assert.sameValue(explicit.weeks, 0, "default largest unit is days"); +assert.sameValue(explicit.days, 41, "default largest unit is days"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = later.since(earlier); +assert.sameValue(implicit.years, 0, "default largest unit is days"); +assert.sameValue(implicit.months, 0, "default largest unit is days"); +assert.sameValue(implicit.weeks, 0, "default largest unit is days"); +assert.sameValue(implicit.days, 41, "default largest unit is days"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/prop-desc.js new file mode 100644 index 000000000000..8ff70f507f09 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: The "since" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.since, + "function", + "`typeof PlainDateTime.prototype.since` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "since", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..9acbe9aaf73c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/read-time-fields-before-datefromfields.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.plaindatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.e: + e. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = new Temporal.PlainDateTime(2021, 3, 31, 12, 34, 56, 987, 654, 321); +const duration = datetime.since({ year: 2021, month: 3, day: 31, calendar }); + +TemporalHelpers.assertDuration(duration, 0, 0, 0, 0, 12, 34, 56, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/round-negative-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/round-negative-duration.js new file mode 100644 index 000000000000..e04010c88ec6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/round-negative-duration.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Negative durations are rounded correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-roundduration step 6: + 6. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + sec-temporal.plaindatetime.prototype.since step 15: + 15. Let _roundResult_ be ? RoundDuration(−_diff_.[[Years]], −_diff_.[[Months]], −_diff_.[[Weeks]], −_diff_.[[Days]], −_diff_.[[Hours]], −_diff_.[[Minutes]], −_diff_.[[Seconds]], −_diff_.[[Milliseconds]], −_diff_.[[Microseconds]], −_diff_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _dateTime_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12); +const later = new Temporal.PlainDateTime(2000, 5, 5); +const result = later.since(earlier, { smallestUnit: "day", roundingIncrement: 2 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-nan.js new file mode 100644 index 000000000000..1122fcfbc4b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindatetime.prototype.since step 13: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-non-integer.js new file mode 100644 index 000000000000..3c82108fb0dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 5); +const result = later.since(earlier, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..740e4e433341 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -1 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 0 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-undefined.js new file mode 100644 index 000000000000..7ed3192ac723 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindatetime.prototype.since step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322); + +const explicit = later.since(earlier, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..c689cd3f1f5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindatetime.prototype.since step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => later.since(earlier, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 397, 1, 1, 1, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string.js new file mode 100644 index 000000000000..53d217711d59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-undefined.js new file mode 100644 index 000000000000..7474e7e85012 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500); + +const explicit1 = later.since(earlier, { smallestUnit: "microsecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc"); +const implicit1 = later.since(earlier, { smallestUnit: "microsecond" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc"); + +const explicit2 = later.since(earlier, { smallestUnit: "millisecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 1, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc"); +const implicit2 = later.since(earlier, { smallestUnit: "millisecond" }); +TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 1, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc"); + +const explicit3 = later.since(earlier, { smallestUnit: "second", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc"); +const implicit3 = later.since(earlier, { smallestUnit: "second" }); +TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-wrong-type.js new file mode 100644 index 000000000000..85888ed69a14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string.js new file mode 100644 index 000000000000..9673917b67b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321); +const values = ["era", "eraYear", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..210f642a177c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 12, 13, 35, 57, 988, 655, 322); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => later.since(earlier, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-undefined.js new file mode 100644 index 000000000000..9a898489b0ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321); + +const explicit = later.since(earlier, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-wrong-type.js new file mode 100644 index 000000000000..ea798bc6f599 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => later.since(earlier, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/year-zero.js new file mode 100644 index 000000000000..7888ce9d0000 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/since/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00[UTC]" +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { instance.since(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js new file mode 100644 index 000000000000..1f10c21966a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Ambiguous subtraction is handled according to the overflow option +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const mar31 = new Temporal.PlainDateTime(2020, 3, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + mar31.subtract({ months: 1 }), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "constrain when ambiguous result (overflow options not supplied)" +); + +TemporalHelpers.assertPlainDateTime( + mar31.subtract({ months: 1 }, { overflow: "constrain" }), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "constrain when ambiguous result (overflow options supplied)" +); + +assert.throws( + RangeError, + () => mar31.subtract({ months: 1 }, { overflow: "reject" }), + "throw when ambiguous result with reject" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js new file mode 100644 index 000000000000..eaef89e44d19 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Duration object arguments are handled +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +const subtractWithDuration = jan31.subtract(new Temporal.Duration(0, 1, 0, 0, 0, 1)); +TemporalHelpers.assertPlainDateTime( + subtractWithDuration, + 2019, 12, "M12", 31, 14, 59, 0, 0, 0, 0, + "Duration argument" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-not-object.js new file mode 100644 index 000000000000..cb6f192d3065 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Passing a primitive other than string to subtract() throws +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +assert.throws(RangeError, () => instance.subtract(undefined), "undefined"); +assert.throws(RangeError, () => instance.subtract(null), "null"); +assert.throws(RangeError, () => instance.subtract(true), "boolean"); +assert.throws(RangeError, () => instance.subtract(""), "empty string"); +assert.throws(TypeError, () => instance.subtract(Symbol()), "Symbol"); +assert.throws(RangeError, () => instance.subtract(7), "number"); +assert.throws(RangeError, () => instance.subtract(7n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js new file mode 100644 index 000000000000..34bb7fe54a0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: At least one recognized property has to be present in argument +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +assert.throws( + TypeError, + () => jan31.subtract({}), + "empty object not acceptable" +); + +assert.throws( + TypeError, + () => jan31.subtract({ month: 12 }), // should be "months" + "misspelled property in argument throws if no other properties are present" +); + +assert.throws( + TypeError, + () => jan31.subtract({ nonsense: true }), + "unrecognized properties throw if no other recognized property is present" +); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ nonsense: 1, days: 1 }), + 2020, 1, "M01", 30, 15, 0, 0, 0, 0, 0, + "unrecognized properties ignored provided at least one recognized property is present" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js new file mode 100644 index 000000000000..7f9f36307582 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Positive and negative values in the temporalDurationLike argument are not acceptable +features: [Temporal] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +["constrain", "reject"].forEach((overflow) => { + assert.throws( + RangeError, + () => jan31.subtract({ hours: 1, minutes: -30 }, { overflow }), + `mixed positive and negative values always throw (overflow = "${overflow}")` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..a65826b451b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2); + +TemporalHelpers.assertPlainDateTime(datetime.subtract("PT1.03125H"), 2000, 5, "M05", 1, 22, 58, 7, 500, 0, 0, + "positive fractional units rounded with correct rounding mode"); +TemporalHelpers.assertPlainDateTime(datetime.subtract("-PT1.03125H"), 2000, 5, "M05", 2, 1, 1, 52, 500, 0, 0, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..91ef0fc97d86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2); + +const resultHours = instance.subtract("-PT24.567890123H"); +TemporalHelpers.assertPlainDateTime(resultHours, 2000, 5, "M05", 3, 0, 34, 4, 404, 442, 799, "negative fractional hours"); + +const resultMinutes = instance.subtract("-PT1440.567890123M"); +TemporalHelpers.assertPlainDateTime(resultMinutes, 2000, 5, "M05", 3, 0, 0, 34, 73, 407, 379, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string.js new file mode 100644 index 000000000000..12e0ea3f2a4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +const result = instance.subtract("P3D"); +TemporalHelpers.assertPlainDateTime(result, 2000, 4, "M04", 29, 0, 34, 56, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/balance-negative-time-units.js new file mode 100644 index 000000000000..0a79c299a974 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/balance-negative-time-units.js @@ -0,0 +1,52 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-adddatetime step 1: + 1. Let _timeResult_ be ? AddTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal.plaindatetime.prototype.subtract step 5: + 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1996, 5, 2, 1, 1, 1, 1, 1, 1); + +const result1 = datetime.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainDateTime(result1, 1996, 5, "M05", 2, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = datetime.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainDateTime(result2, 1996, 5, "M05", 2, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = datetime.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainDateTime(result3, 1996, 5, "M05", 2, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = datetime.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainDateTime(result4, 1996, 5, "M05", 2, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = datetime.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainDateTime(result5, 1996, 5, "M05", 2, 0, 59, 1, 1, 1, 1, "minutes balance"); + +const result6 = datetime.subtract(new Temporal.Duration(0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainDateTime(result6, 1996, 5, "M05", 1, 23, 1, 1, 1, 1, 1, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/builtin.js new file mode 100644 index 000000000000..c71cad21516a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: > + Tests that Temporal.PlainDateTime.prototype.subtract + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.subtract), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.subtract), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.subtract), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.subtract.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js new file mode 100644 index 000000000000..ce134763f2ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Testing overflow hours (subtracting hours that push one to the next/previous day) +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); +const later = new Temporal.PlainDateTime(2020, 5, 31, 23, 12, 38, 271, 986, 102); + +TemporalHelpers.assertPlainDateTime( + dt.subtract({ hours: 12 }), + 2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102, + "subtract result" +); + +TemporalHelpers.assertPlainDateTime( + dt.add({ hours: -12 }), + 2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102, + "hour overflow (pushes to previous day)" +); + +TemporalHelpers.assertPlainDateTime( + later.subtract({ hours: -2 }), + 2020, 6, "M06", 1, 1, 12, 38, 271, 986, 102, + "subtracting a negative amount of hours is equivalent to adding hours" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..9c5fd133f410 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDateTime.prototype.subtract throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plaindatetime.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/length.js new file mode 100644 index 000000000000..ae1f0e9c30b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Temporal.PlainDateTime.prototype.subtract.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.subtract, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/name.js new file mode 100644 index 000000000000..e36d02f035b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Temporal.PlainDateTime.prototype.subtract.name is "subtract". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.subtract, "name", { + value: "subtract", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js new file mode 100644 index 000000000000..2ed41175eac9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Negative durations can be supplied +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ minutes: -30 }), + 2020, 1, "M01", 31, 15, 30, 0, 0, 0, 0, + "negative minutes" +); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ seconds: -30 }), + 2020, 1, "M01", 31, 15, 0, 30, 0, 0, 0, + "negative seconds" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..009d1bd08cb3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDateTime.prototype.subtract throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plaindatetime.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainDateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..7be872302833 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.subtract({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/not-a-constructor.js new file mode 100644 index 000000000000..a5e39d43c2a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: > + Temporal.PlainDateTime.prototype.subtract does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.subtract(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.subtract), false, + "isConstructor(Temporal.PlainDateTime.prototype.subtract)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js new file mode 100644 index 000000000000..687f6f5e6e70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Verify that undefined options are handled correctly. +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ months: 2 }, {}), + 2019, 11, "M11", 30, 15, 0, 0, 0, 0, 0, + "options may be empty object" +); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ months: 2 }, () => {}), + 2019, 11, "M11", 30, 15, 0, 0, 0, 0, 0, + "options may be function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js new file mode 100644 index 000000000000..30990fc7a8ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Various invalid (wrong type) values for options argument +features: [Temporal, Symbol] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n]; + +badOptions.forEach((bad) => { + assert.throws( + TypeError, + () => jan31.subtract({ years: 1 }, bad), + `invalid options (${typeof bad})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-undefined.js new file mode 100644 index 000000000000..fe4aa8c98d19 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 3, 31, 12, 34, 56, 987, 654, 321); +const duration = { months: 1 }; + +const explicit = datetime.subtract(duration, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = datetime.subtract(duration); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/order-of-operations.js new file mode 100644 index 000000000000..b194a5dd3d87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Properties on an object passed to subtract() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.subtract(argument); +TemporalHelpers.assertPlainDateTime(result, 1999, 3, "M03", 25, 11, 33, 55, 986, 653, 320); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js new file mode 100644 index 000000000000..e72ec170398c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-adddatetime step 4: + 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.plaindatetime.prototype.subtract step 5: + 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_). +features: [Temporal] +---*/ + +const date = new Temporal.PlainDateTime(2000, 5, 2, 12); +const duration = new Temporal.Duration(3, 3, 0, 3, 3); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-undefined.js new file mode 100644 index 000000000000..abea7f5ece46 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-undefined.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.subtract +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-adddatetime step 4: + 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.plaindatetime.prototype.subtract step 5: + 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 31, 12); +const duration = new Temporal.Duration(3, 1); + +const explicit = datetime.subtract(duration, { overflow: undefined }); +TemporalHelpers.assertPlainDateTime(explicit, 1997, 4, "M04", 30, 12, 0, 0, 0, 0, 0, "default overflow is constrain"); +const implicit = datetime.subtract(duration, {}); +TemporalHelpers.assertPlainDateTime(implicit, 1997, 4, "M04", 30, 12, 0, 0, 0, 0, 0, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-wrong-type.js new file mode 100644 index 000000000000..2a038d21962b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-adddatetime step 4: + 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.plaindatetime.prototype.subtract step 5: + 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); +const duration = new Temporal.Duration(3, 3, 0, 3, 3); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => datetime.subtract(duration, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDateTime(result, 1997, 1, "M01", 30, 9, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/prop-desc.js new file mode 100644 index 000000000000..ecf847c3b002 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: The "subtract" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.subtract, + "function", + "`typeof PlainDateTime.prototype.subtract` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "subtract", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/subclassing-ignored.js new file mode 100644 index 000000000000..f0e6ca39b7e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/subtract/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Objects of a subclass are never created as return values for subtract() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDateTime, + [2000, 5, 2, 12, 34, 56, 987, 654, 321], + "subtract", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 320), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..2a2d769baa59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tojson +description: > + Tests that Temporal.PlainDateTime.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/length.js new file mode 100644 index 000000000000..a7c9a4679d83 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tojson +description: Temporal.PlainDateTime.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/name.js new file mode 100644 index 000000000000..1d33479c4e53 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tojson +description: Temporal.PlainDateTime.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..329ef410787d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tojson +description: > + Temporal.PlainDateTime.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.toJSON), false, + "isConstructor(Temporal.PlainDateTime.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..e6aaecce36a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tojson +description: The "toJSON" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.toJSON, + "function", + "`typeof PlainDateTime.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/year-format.js new file mode 100644 index 000000000000..455c875d3101 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toJSON/year-format.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainDateTime(-100000, 12, 3, 4, 56, 7, 890); +assert.sameValue(instance.toJSON(), "-100000-12-03T04:56:07.89", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-10000, 4, 5, 6, 7, 8, 910); +assert.sameValue(instance.toJSON(), "-010000-04-05T06:07:08.91", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-9999, 6, 7, 8, 9, 10, 987); +assert.sameValue(instance.toJSON(), "-009999-06-07T08:09:10.987", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-1000, 8, 9, 10, 9, 8, 765); +assert.sameValue(instance.toJSON(), "-001000-08-09T10:09:08.765", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-999, 10, 9, 8, 7, 6, 543); +assert.sameValue(instance.toJSON(), "-000999-10-09T08:07:06.543", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-1, 8, 7, 6, 54, 32, 100); +assert.sameValue(instance.toJSON(), "-000001-08-07T06:54:32.1", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(0, 6, 5, 4, 32, 10, 123); +assert.sameValue(instance.toJSON(), "0000-06-05T04:32:10.123", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(1, 4, 3, 21, 0, 12, 345); +assert.sameValue(instance.toJSON(), "0001-04-03T21:00:12.345", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(999, 2, 10, 12, 34, 56, 789); +assert.sameValue(instance.toJSON(), "0999-02-10T12:34:56.789", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(1000, 1, 23, 4, 56, 7, 890); +assert.sameValue(instance.toJSON(), "1000-01-23T04:56:07.89", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(9999, 4, 5, 6, 7, 8, 910); +assert.sameValue(instance.toJSON(), "9999-04-05T06:07:08.91", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(10000, 6, 7, 8, 9, 10, 987); +assert.sameValue(instance.toJSON(), "+010000-06-07T08:09:10.987", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(100000, 8, 9, 10, 9, 8, 765); +assert.sameValue(instance.toJSON(), "+100000-08-09T10:09:08.765", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/builtin.js new file mode 100644 index 000000000000..1a29935e0fca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: > + Tests that Temporal.PlainDateTime.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/length.js new file mode 100644 index 000000000000..b76ad82fd2ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: Temporal.PlainDateTime.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/name.js new file mode 100644 index 000000000000..344fdd82f817 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: Temporal.PlainDateTime.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 000000000000..3f1c93efacc5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: > + Temporal.PlainDateTime.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.toLocaleString), false, + "isConstructor(Temporal.PlainDateTime.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/prop-desc.js new file mode 100644 index 000000000000..a7fefdd236b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.toLocaleString, + "function", + "`typeof PlainDateTime.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/return-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/return-string.js new file mode 100644 index 000000000000..dd7d87a4f217 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/return-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: > + toLocaleString return a string. +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +assert.sameValue(typeof datetime.toLocaleString("en", { dateStyle: "short" }), "string"); +assert.sameValue(typeof datetime.toLocaleString("en", { timeStyle: "short" }), "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/builtin.js new file mode 100644 index 000000000000..feb76632894b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaindate +description: > + Tests that Temporal.PlainDateTime.prototype.toPlainDate + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.toPlainDate), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.toPlainDate), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.toPlainDate), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.toPlainDate.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/length.js new file mode 100644 index 000000000000..f9551dfcb505 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaindate +description: Temporal.PlainDateTime.prototype.toPlainDate.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toPlainDate, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/limits.js new file mode 100644 index 000000000000..b691fc3527a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/limits.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaindate +description: toPlainDate works at the edges of the supported range +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const min = Temporal.PlainDateTime.from('-271821-04-19T00:00:00.000000001'); +TemporalHelpers.assertPlainDate(min.toPlainDate(), + -271821, 4, "M04", 19, "min"); + +const max = Temporal.PlainDateTime.from('+275760-09-13T23:59:59.999999999'); +TemporalHelpers.assertPlainDate(max.toPlainDate(), + 275760, 9, "M09", 13, "max"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/name.js new file mode 100644 index 000000000000..39c2ddcb75ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaindate +description: Temporal.PlainDateTime.prototype.toPlainDate.name is "toPlainDate". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toPlainDate, "name", { + value: "toPlainDate", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/not-a-constructor.js new file mode 100644 index 000000000000..3b9cc3317222 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaindate +description: > + Temporal.PlainDateTime.prototype.toPlainDate does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.toPlainDate(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.toPlainDate), false, + "isConstructor(Temporal.PlainDateTime.prototype.toPlainDate)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/prop-desc.js new file mode 100644 index 000000000000..fddfe63f1197 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaindate +description: The "toPlainDate" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.toPlainDate, + "function", + "`typeof PlainDateTime.prototype.toPlainDate` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "toPlainDate", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainDate/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/builtin.js new file mode 100644 index 000000000000..899da1938031 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: > + Tests that Temporal.PlainDateTime.prototype.toPlainMonthDay + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.toPlainMonthDay), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.toPlainMonthDay), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.toPlainMonthDay), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.toPlainMonthDay.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-arguments.js new file mode 100644 index 000000000000..a15a57019ae6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-arguments.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: Correct options value is passed to calendar method +info: | + MonthDayFromFields ( calendar, fields [ , options ] ) + + 3. If options is not present, then + a. Set options to undefined. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + monthDayFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.sameValue(args[1], undefined, "args[1]"); + return super.monthDayFromFields(...args); + } +} +const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 456, 789, new CustomCalendar()); +const result = plainDateTime.toPlainMonthDay(); +TemporalHelpers.assertPlainMonthDay(result, "M05", 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-fields-iterable.js new file mode 100644 index 000000000000..183f903ea01e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-fields-iterable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.prototype.toplainmonthday step 4: + 4. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"monthCode"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "monthCode", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +datetime.toPlainMonthDay(); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..968018c8c3cf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +instance.toPlainMonthDay(); +assert.sameValue(calendar.monthDayFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/length.js new file mode 100644 index 000000000000..99000569bd60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: Temporal.PlainDateTime.prototype.toPlainMonthDay.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toPlainMonthDay, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/name.js new file mode 100644 index 000000000000..519a41a004e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: Temporal.PlainDateTime.prototype.toPlainMonthDay.name is "toPlainMonthDay". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toPlainMonthDay, "name", { + value: "toPlainMonthDay", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/not-a-constructor.js new file mode 100644 index 000000000000..bf9935ba012a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: > + Temporal.PlainDateTime.prototype.toPlainMonthDay does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.toPlainMonthDay(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.toPlainMonthDay), false, + "isConstructor(Temporal.PlainDateTime.prototype.toPlainMonthDay)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/prop-desc.js new file mode 100644 index 000000000000..adb83c4fdc2c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: The "toPlainMonthDay" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.toPlainMonthDay, + "function", + "`typeof PlainDateTime.prototype.toPlainMonthDay` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "toPlainMonthDay", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/basic.js new file mode 100644 index 000000000000..a730e68b47d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/basic.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaintime +description: Basic usage +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDateTime = Temporal.PlainDateTime.from("2020-02-12T11:42:56.987654321+01:00[Europe/Amsterdam]"); +TemporalHelpers.assertPlainTime(plainDateTime.toPlainTime(), 11, 42, 56, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/builtin.js new file mode 100644 index 000000000000..788deddbf603 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaintime +description: > + Tests that Temporal.PlainDateTime.prototype.toPlainTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.toPlainTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.toPlainTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.toPlainTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.toPlainTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/length.js new file mode 100644 index 000000000000..5ad135cdb16e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaintime +description: Temporal.PlainDateTime.prototype.toPlainTime.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toPlainTime, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/name.js new file mode 100644 index 000000000000..0799547bcfa3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaintime +description: Temporal.PlainDateTime.prototype.toPlainTime.name is "toPlainTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toPlainTime, "name", { + value: "toPlainTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/not-a-constructor.js new file mode 100644 index 000000000000..2f61893892ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaintime +description: > + Temporal.PlainDateTime.prototype.toPlainTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.toPlainTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.toPlainTime), false, + "isConstructor(Temporal.PlainDateTime.prototype.toPlainTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/prop-desc.js new file mode 100644 index 000000000000..b3f07cb10155 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplaintime +description: The "toPlainTime" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.toPlainTime, + "function", + "`typeof PlainDateTime.prototype.toPlainTime` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "toPlainTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/builtin.js new file mode 100644 index 000000000000..1f1c80af6930 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: > + Tests that Temporal.PlainDateTime.prototype.toPlainYearMonth + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.toPlainYearMonth), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.toPlainYearMonth), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.toPlainYearMonth), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.toPlainYearMonth.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-arguments.js new file mode 100644 index 000000000000..6f1793a3d5d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-arguments.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: Correct options value is passed to calendar method +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 3. If options is not present, then + a. Set options to undefined. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + yearMonthFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.sameValue(args[1], undefined, "args[1]"); + return super.yearMonthFromFields(...args); + } +} +const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 456, 789, new CustomCalendar()); +const result = plainDateTime.toPlainYearMonth(); +TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-fields-iterable.js new file mode 100644 index 000000000000..a037b3e6866a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-fields-iterable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.prototype.toplainyearmonth step 4: + 4. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +datetime.toPlainYearMonth(); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..8ecb2f45326f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +instance.toPlainYearMonth(); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/length.js new file mode 100644 index 000000000000..73c2932648b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: Temporal.PlainDateTime.prototype.toPlainYearMonth.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toPlainYearMonth, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/name.js new file mode 100644 index 000000000000..02343bcade2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: Temporal.PlainDateTime.prototype.toPlainYearMonth.name is "toPlainYearMonth". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toPlainYearMonth, "name", { + value: "toPlainYearMonth", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/not-a-constructor.js new file mode 100644 index 000000000000..9b7ebb5a45ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: > + Temporal.PlainDateTime.prototype.toPlainYearMonth does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.toPlainYearMonth(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.toPlainYearMonth), false, + "isConstructor(Temporal.PlainDateTime.prototype.toPlainYearMonth)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/prop-desc.js new file mode 100644 index 000000000000..c2631f9e97b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: The "toPlainYearMonth" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.toPlainYearMonth, + "function", + "`typeof PlainDateTime.prototype.toPlainYearMonth` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "toPlainYearMonth", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js new file mode 100644 index 000000000000..a4b3218253f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Checking the string form of an explicitly constructed instance with all arguments +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); + +assert.sameValue(datetime.toString(), "1976-11-18T15:23:30.123456789", "check string value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/builtin.js new file mode 100644 index 000000000000..504ae48015e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: > + Tests that Temporal.PlainDateTime.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-invalid-string.js new file mode 100644 index 000000000000..fe695be5aa97 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-invalid-string.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.protoype.tostring +description: RangeError thrown when calendarName option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plaindatetime.protoype.tostring step 6: + 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +assert.throws(RangeError, () => datetime.toString({ calendarName: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-undefined.js new file mode 100644 index 000000000000..a59e596aa6c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-undefined.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.protoype.tostring +description: Fallback value for calendarName option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plaindatetime.protoype.tostring step 6: + 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const datetime1 = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const datetime2 = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + +[ + [datetime1, "2000-05-02T12:34:56.987654321"], + [datetime2, "2000-05-02T12:34:56.987654321[u-ca=custom]"], +].forEach(([datetime, expected]) => { + const explicit = datetime.toString({ calendarName: undefined }); + assert.sameValue(explicit, expected, "default calendarName option is auto"); + + // See options-undefined.js for {} +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-wrong-type.js new file mode 100644 index 000000000000..e402e57b6767 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.protoype.tostring +description: Type conversions for calendarName option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plaindatetime.protoype.tostring step 6: + 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + +TemporalHelpers.checkStringOptionWrongType("calendarName", "auto", + (calendarName) => datetime.toString({ calendarName }), + (result, descr) => assert.sameValue(result, "2000-05-02T12:34:56.987654321[u-ca=custom]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js new file mode 100644 index 000000000000..c2bee94ca738 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values +info: | + sec-getstringornumberoption step 4: + 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaindatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); + +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-nan.js new file mode 100644 index 000000000000..d27995366068 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-nan.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaindatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js new file mode 100644 index 000000000000..565c8e410221 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Rounding for fractionalSecondDigits option +info: | + sec-getstringornumberoption step 3.b: + b. Return floor(ℝ(_value_)). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaindatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); + +const string = datetime.toString({ fractionalSecondDigits: 2.5 }); +assert.sameValue(string, "2000-05-02T12:34:56.98", "fractionalSecondDigits 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js new file mode 100644 index 000000000000..d7191cf3f23c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option out of range +info: | + sec-getstringornumberoption step 3.a: + a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaindatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); + +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -1 })); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 10 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js new file mode 100644 index 000000000000..255114ed7b67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Fallback value for fractionalSecondDigits option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaindatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); + +const explicit = datetime.toString({ fractionalSecondDigits: undefined }); +assert.sameValue(explicit, "2000-05-02T12:34:56.98765", "default fractionalSecondDigits is auto"); + +// See options-undefined.js for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js new file mode 100644 index 000000000000..a964c4f72eeb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Type conversions for fractionalSecondDigits option +info: | + sec-getoption steps 8–9: + 8. Else if _type_ is Number, then + a. Set _value_ to ? ToNumber(value). + b. ... + 9. Else, + a. Set _value_ to ? ToString(value). + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaindatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); +TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(datetime); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/length.js new file mode 100644 index 000000000000..7ea6e28f40f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Temporal.PlainDateTime.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/name.js new file mode 100644 index 000000000000..c412c12d9295 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Temporal.PlainDateTime.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..3c4d3f86d581 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: > + Temporal.PlainDateTime.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.toString), false, + "isConstructor(Temporal.PlainDateTime.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/options-undefined.js new file mode 100644 index 000000000000..3f9ee3553fb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/options-undefined.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const datetime1 = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); +const datetime2 = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0, calendar); + +[ + [datetime1, "2000-05-02T12:34:56.98765"], + [datetime2, "2000-05-02T12:34:56.98765[u-ca=custom]"], +].forEach(([datetime, expected]) => { + const explicit = datetime.toString(undefined); + assert.sameValue(explicit, expected, "default calendarName option is auto, precision is auto, and no rounding"); + + const propertyImplicit = datetime.toString({}); + assert.sameValue(propertyImplicit, expected, "default calendarName option is auto, precision is auto, and no rounding"); + + const implicit = datetime.toString(); + assert.sameValue(implicit, expected, "default calendarName option is auto, precision is auto, and no rounding"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..d5e16001765a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: The "toString" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.toString, + "function", + "`typeof PlainDateTime.prototype.toString` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-invalid-string.js new file mode 100644 index 000000000000..ae3fec6e544c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => datetime.toString({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-undefined.js new file mode 100644 index 000000000000..182e14d15880 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Fallback value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); + +const explicit1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: undefined }); +assert.sameValue(explicit1, "2000-05-02T12:34:56.123987", "default roundingMode is trunc"); +const implicit1 = datetime.toString({ smallestUnit: "microsecond" }); +assert.sameValue(implicit1, "2000-05-02T12:34:56.123987", "default roundingMode is trunc"); + +const explicit2 = datetime.toString({ smallestUnit: "millisecond", roundingMode: undefined }); +assert.sameValue(explicit2, "2000-05-02T12:34:56.123", "default roundingMode is trunc"); +const implicit2 = datetime.toString({ smallestUnit: "millisecond" }); +assert.sameValue(implicit2, "2000-05-02T12:34:56.123", "default roundingMode is trunc"); + +const explicit3 = datetime.toString({ smallestUnit: "second", roundingMode: undefined }); +assert.sameValue(explicit3, "2000-05-02T12:34:56", "default roundingMode is trunc"); +const implicit3 = datetime.toString({ smallestUnit: "second" }); +assert.sameValue(implicit3, "2000-05-02T12:34:56", "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-wrong-type.js new file mode 100644 index 000000000000..5d60bbf24b06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => datetime.toString({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => assert.sameValue(result, "2000-05-02T12:34:56.123987", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-invalid-string.js new file mode 100644 index 000000000000..a1a86b67b3da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-invalid-string.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); +assert.throws(RangeError, () => datetime.toString({ smallestUnit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..5a844c5d783e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 789, 999, 999); +const validUnits = [ + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => datetime.toString({ smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-undefined.js new file mode 100644 index 000000000000..2c322a3f6a4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-undefined.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Fallback value for smallestUnit option +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); + +const explicit1 = datetime.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 }); +assert.sameValue(explicit1, "2000-05-02T12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits"); +const implicit1 = datetime.toString({ fractionalSecondDigits: 6 }); +assert.sameValue(implicit1, "2000-05-02T12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits"); + +const explicit2 = datetime.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 }); +assert.sameValue(explicit2, "2000-05-02T12:34:56.123", "default smallestUnit defers to fractionalSecondDigits"); +const implicit2 = datetime.toString({ fractionalSecondDigits: 3 }); +assert.sameValue(implicit2, "2000-05-02T12:34:56.123", "default smallestUnit defers to fractionalSecondDigits"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-valid-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-valid-units.js new file mode 100644 index 000000000000..45f9a886335c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-valid-units.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Valid units for the smallestUnit option +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 789, 999, 999); + +assert.sameValue(datetime.toString({ smallestUnit: "minute" }), "2000-05-02T12:34"); +assert.sameValue(datetime.toString({ smallestUnit: "second" }), "2000-05-02T12:34:56"); +assert.sameValue(datetime.toString({ smallestUnit: "millisecond" }), "2000-05-02T12:34:56.789"); +assert.sameValue(datetime.toString({ smallestUnit: "microsecond" }), "2000-05-02T12:34:56.789999"); +assert.sameValue(datetime.toString({ smallestUnit: "nanosecond" }), "2000-05-02T12:34:56.789999999"); + +const notValid = [ + "year", + "month", + "week", + "day", + "hour", +]; + +notValid.forEach((smallestUnit) => { + assert.throws(RangeError, () => datetime.toString({ smallestUnit }), smallestUnit); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-wrong-type.js new file mode 100644 index 000000000000..27bd9c12ff38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => datetime.toString({ smallestUnit }), + (result, descr) => assert.sameValue(result, "2000-05-02T12:34:56.123987", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/year-format.js new file mode 100644 index 000000000000..f45596d579c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toString/year-format.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainDateTime(-100000, 12, 3, 4, 56, 7, 890); +assert.sameValue(instance.toString(), "-100000-12-03T04:56:07.89", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-10000, 4, 5, 6, 7, 8, 910); +assert.sameValue(instance.toString(), "-010000-04-05T06:07:08.91", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-9999, 6, 7, 8, 9, 10, 987); +assert.sameValue(instance.toString(), "-009999-06-07T08:09:10.987", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-1000, 8, 9, 10, 9, 8, 765); +assert.sameValue(instance.toString(), "-001000-08-09T10:09:08.765", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-999, 10, 9, 8, 7, 6, 543); +assert.sameValue(instance.toString(), "-000999-10-09T08:07:06.543", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-1, 8, 7, 6, 54, 32, 100); +assert.sameValue(instance.toString(), "-000001-08-07T06:54:32.1", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(0, 6, 5, 4, 32, 10, 123); +assert.sameValue(instance.toString(), "0000-06-05T04:32:10.123", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(1, 4, 3, 21, 0, 12, 345); +assert.sameValue(instance.toString(), "0001-04-03T21:00:12.345", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(999, 2, 10, 12, 34, 56, 789); +assert.sameValue(instance.toString(), "0999-02-10T12:34:56.789", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(1000, 1, 23, 4, 56, 7, 890); +assert.sameValue(instance.toString(), "1000-01-23T04:56:07.89", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(9999, 4, 5, 6, 7, 8, 910); +assert.sameValue(instance.toString(), "9999-04-05T06:07:08.91", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(10000, 6, 7, 8, 9, 10, 987); +assert.sameValue(instance.toString(), "+010000-06-07T08:09:10.987", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(100000, 8, 9, 10, 9, 8, 765); +assert.sameValue(instance.toString(), "+100000-08-09T10:09:08.765", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/balance-negative-time-units.js new file mode 100644 index 000000000000..8214ffa215d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/balance-negative-time-units.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-adddatetime step 1: + 1. Let _timeResult_ be ? AddTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-builtintimezonegetinstantfor step 13.a: + a. Let _earlier_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], 0, 0, 0, 0, 0, 0, 0, 0, 0, −_nanoseconds_, *"constrain"*). + sec-temporal.plaindatetime.prototype.tozoneddatetime step 6: + 6. Let _instant_ be BuiltinTimeZoneGetInstantFor(_timeZone_, _dateTime_, _disambiguation_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const shiftInstant = new Temporal.Instant(3661_001_001_001n); +const tz = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2); +const datetime = new Temporal.PlainDateTime(1970, 1, 1, 1, 1, 1, 1, 1, 1); + +// This code path is encountered if disambiguation is `earlier` and the shift is +// a spring-forward change +datetime.toZonedDateTime(tz, { disambiguation: "earlier" }); + +const expected = [ + "1970-01-01T01:01:01.001001001", + "1970-01-01T01:01:01.001000999", +]; +assert.compareArray(tz.getPossibleInstantsForCalledWith, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/builtin.js new file mode 100644 index 000000000000..336d485ecb66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: > + Tests that Temporal.PlainDateTime.prototype.toZonedDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.toZonedDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.toZonedDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.toZonedDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.toZonedDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..2030577a174d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, calendar); + +["earlier", "compatible", "later"].forEach((disambiguation) => { + calendar.dateAddCallCount = 0; + + instance.toZonedDateTime(timeZone, { disambiguation }); + assert.sameValue(calendar.dateAddCallCount, 1, `calling with disambiguation ${disambiguation}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-invalid-string.js new file mode 100644 index 000000000000..1b5a2dab245f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-invalid-string.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: RangeError thrown when disambiguation option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.plaindatetime.prototype.tozoneddatetime step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321); +const timeZone = new Temporal.TimeZone("UTC"); +assert.throws(RangeError, () => datetime.toZonedDateTime(timeZone, { disambiguation: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-undefined.js new file mode 100644 index 000000000000..f0ec955c269e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-undefined.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: Fallback value for disambiguation option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.plaindatetime.prototype.tozoneddatetime step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); +const springForwardDatetime = new Temporal.PlainDateTime(2000, 4, 2, 2, 30); +const fallBackDatetime = new Temporal.PlainDateTime(2000, 10, 29, 1, 30); + +[ + [springForwardDatetime, 954671400_000_000_000n], + [fallBackDatetime, 972808200_000_000_000n], +].forEach(([datetime, expected]) => { + const explicit = datetime.toZonedDateTime(timeZone, { disambiguation: undefined }); + assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible"); + const implicit = datetime.toZonedDateTime(timeZone, {}); + assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-wrong-type.js new file mode 100644 index 000000000000..42a2fba3c708 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/disambiguation-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: Type conversions for disambiguation option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.plaindatetime.prototype.tozoneddatetime step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321); +const timeZone = new Temporal.TimeZone("UTC"); +TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible", + (disambiguation) => datetime.toZonedDateTime(timeZone, { disambiguation }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/length.js new file mode 100644 index 000000000000..95a1924004b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: Temporal.PlainDateTime.prototype.toZonedDateTime.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toZonedDateTime, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/name.js new file mode 100644 index 000000000000..1bdddc9dc416 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: Temporal.PlainDateTime.prototype.toZonedDateTime.name is "toZonedDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.toZonedDateTime, "name", { + value: "toZonedDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/not-a-constructor.js new file mode 100644 index 000000000000..752357bfbebe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: > + Temporal.PlainDateTime.prototype.toZonedDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.toZonedDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.toZonedDateTime), false, + "isConstructor(Temporal.PlainDateTime.prototype.toZonedDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/options-undefined.js new file mode 100644 index 000000000000..1bb99ff8b12e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/options-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +includes: [temporalHelpers.js] +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const datetimeEarlier = new Temporal.PlainDateTime(2000, 10, 29, 1, 34, 56, 987, 654, 321); +const datetimeLater = new Temporal.PlainDateTime(2000, 4, 2, 2, 34, 56, 987, 654, 321); +const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); + +[ + [datetimeEarlier, 972808496987654321n], + [datetimeLater, 954671696987654321n], +].forEach(([datetime, expected]) => { + const explicit = datetime.toZonedDateTime(timeZone, undefined); + assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible"); + + const implicit = datetime.toZonedDateTime(timeZone); + assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/plain-custom-timezone.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/plain-custom-timezone.js new file mode 100644 index 000000000000..f1e48f0e6f67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/plain-custom-timezone.js @@ -0,0 +1,69 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: TimeZone.getPossibleInstantsFor called after processing timeZone and options +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "has timeZone.timeZone", + "get options.disambiguation", + "get disambiguation.toString", + "call disambiguation.toString", + "get timeZone.getPossibleInstantsFor", + "call timeZone.getPossibleInstantsFor", +]; + +Object.defineProperty(Temporal.TimeZone, "from", { + get() { + actual.push("get Temporal.TimeZone.from"); + return undefined; + }, +}); + +const dateTime = Temporal.PlainDateTime.from("1975-02-02T14:25:36.123456789"); +const instant = Temporal.Instant.fromEpochNanoseconds(-205156799012345679n); + +const options = new Proxy({ + disambiguation: TemporalHelpers.toPrimitiveObserver(actual, "reject", "disambiguation"), +}, { + has(target, property) { + actual.push(`has options.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get options.${property}`); + return target[property]; + }, +}); + +const timeZone = new Proxy({ + getPossibleInstantsFor(dateTimeArg) { + actual.push("call timeZone.getPossibleInstantsFor"); + assert.sameValue(dateTimeArg, dateTime); + return [instant]; + }, +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + }, +}); + +const result = dateTime.toZonedDateTime(timeZone, options); +assert.sameValue(result.epochNanoseconds, instant.epochNanoseconds); +assert.sameValue(result.timeZone, timeZone); +assert.sameValue(result.calendar, dateTime.calendar); + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/prop-desc.js new file mode 100644 index 000000000000..89d0d1be76e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: The "toZonedDateTime" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.toZonedDateTime, + "function", + "`typeof PlainDateTime.prototype.toZonedDateTime` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "toZonedDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..7ecb94ade0b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => datetime.toZonedDateTime(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..eede9009ac10 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + timeZone.getPossibleInstantsFor = function () { + return []; + }; + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.toZonedDateTime(timeZone), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..75b4643a8d65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => datetime.toZonedDateTime(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..8c9f10624cc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + assert.throws(TypeError, () => datetime.toZonedDateTime(timeZone)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..f1bd0e06d86d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.plaindatetime.prototype.tozoneddatetime step 6: + 6. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "2000-05-02T12:34:56.987654321", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + datetime.toZonedDateTime(timeZone); +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:30:00", + "2030-01-01T01:30:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.PlainDateTime(2030, 1, 1, 0, 30); + datetime.toZonedDateTime(timeZone); +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..cc4e1b5dc7dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.toZonedDateTime(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = instance.toZonedDateTime(timeZone); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = instance.toZonedDateTime(timeZone); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = instance.toZonedDateTime(timeZone); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = instance.toZonedDateTime(timeZone); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = instance.toZonedDateTime(timeZone); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..9c416fffb1de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = instance.toZonedDateTime(timeZone); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-plaindate.js new file mode 100644 index 000000000000..9fae1e5378d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-plaindate.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.b: + b. If _item_ has an [[InitializedTemporalDate]] internal slot, then + i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date, calendar) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 987, 654, 321, calendar); + const result = datetime.until(date); + assert.sameValue(result.total({ unit: "nanoseconds" }), -987654321, "PlainDate is converted to midnight"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..753931045138 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown if a string with UTC designator is used as a PlainDateTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "String with UTC designator should not be valid as a PlainDateTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..542e968c8005 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaldatetime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaindatetime.prototype.until step 3: + 3. Set _other_ ? ToTemporalDateTime(_other_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const diff = new Temporal.PlainDateTime(1970, 1, 1).until(datetime); + +TemporalHelpers.assertDuration(diff, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..d65c1ed94a98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321); +const result = instance.until(datetime); +TemporalHelpers.assertDuration(result, 0, 0, 0, -11239, -22, -40, -10, -987, -654, -320); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..97c8f2b86f11 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.until(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..862a02582d4d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => plain.until(zoned), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..f574edfb8d06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.until(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..25f9414c92e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => plain.until(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-duration.js new file mode 100644 index 000000000000..3a8d97e43203 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-duration.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Negative durations are balanced correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-balanceduration step 4: + 4. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + sec-temporal-differenceisodatetime steps 7 and 13: + 7. If _timeSign_ is -_dateSign_, then + ... + b. Set _timeDifference_ to ? BalanceDuration(-_timeSign_, _timeDifference_.[[Hours]], _timeDifference_.[[Minutes]], _timeDifference_.[[Seconds]], _timeDifference_.[[Milliseconds]], _timeDifference_.[[Microseconds]], _timeDifference_.[[Nanoseconds]], _largestUnit_). + ... + 13. Return ? BalanceDuration(_dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], _dateDifference_.[[Days]], _timeDifference_.[[Hours]], _timeDifference_.[[Minutes]], _timeDifference_.[[Seconds]], _timeDifference_.[[Milliseconds]], _timeDifference_.[[Microseconds]], _timeDifference_.[[Nanoseconds]], _largestUnit_). + sec-temporal.plaindatetime.prototype.until step 13: + 13. Let _diff_ be ? DifferenceISODateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _dateTime_.[[Calendar]], _largestUnit_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier1 = new Temporal.PlainDateTime(2000, 5, 2, 9); +const later1 = new Temporal.PlainDateTime(2000, 5, 5, 10); +const result1 = later1.until(earlier1, { largestUnit: 'day' }); +TemporalHelpers.assertDuration(result1, 0, 0, 0, -3, -1, 0, 0, 0, 0, 0, "date sign == time sign"); + +const earlier2 = new Temporal.PlainDateTime(2000, 5, 2, 10); +const later2 = new Temporal.PlainDateTime(2000, 5, 5, 9); +const result2 = later2.until(earlier2, { largestUnit: 'day' }); +TemporalHelpers.assertDuration(result2, 0, 0, 0, -2, -23, 0, 0, 0, 0, 0, "date sign != time sign"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-time-units.js new file mode 100644 index 000000000000..03d74a6b0ec1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-time-units.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-differenceisodatetime step 2: + 2. Let _timeDifference_ be ? DifferenceTime(_h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_). + sec-temporal.plaindatetime.prototype.until step 13: + 13. Let _diff_ be ? DifferenceISODateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _dateTime_.[[Calendar]], _largestUnit_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1996, 5, 2, 1, 1, 1, 1, 1, 1); + +const result1 = new Temporal.PlainDateTime(1996, 5, 2, 0, 0, 0, 0, 0, 2).until(datetime); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = new Temporal.PlainDateTime(1996, 5, 2, 0, 0, 0, 0, 2).until(datetime); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = new Temporal.PlainDateTime(1996, 5, 2, 0, 0, 0, 2).until(datetime); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = new Temporal.PlainDateTime(1996, 5, 2, 0, 0, 2).until(datetime); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = new Temporal.PlainDateTime(1996, 5, 2, 0, 2).until(datetime); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = new Temporal.PlainDateTime(1996, 5, 2, 2).until(datetime); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance.js new file mode 100644 index 000000000000..bb664ddfa802 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/balance.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Results with opposite-sign components (e.g. months=1, hours=-1) are balanced correctly +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const a = Temporal.PlainDateTime.from('2017-10-05T08:07:14+00:00[UTC]'); +const b = Temporal.PlainDateTime.from('2021-03-05T03:32:45+00:00[UTC]'); +const c = Temporal.PlainDateTime.from('2021-03-05T09:32:45+00:00[UTC]'); + +const r1 = a.until(b, { largestUnit: 'months' }); +TemporalHelpers.assertDuration(r1, 0, 40, 0, 27, 19, 25, 31, 0, 0, 0, "r1"); +assert.sameValue(a.add(r1).toString(), b.toString(), "a.add(r1)"); + +const r2 = b.until(a, { largestUnit: 'months' }); +TemporalHelpers.assertDuration(r2, 0, -40, 0, -30, -19, -25, -31, 0, 0, 0, "r2"); +assert.sameValue(b.add(r2).toString(), a.toString(), "b.add(r2)"); + +const r3 = c.until(a, { largestUnit: 'months' }); +TemporalHelpers.assertDuration(r3, 0, -41, 0, 0, -1, -25, -31, 0, 0, 0, "r3"); +assert.sameValue(c.add(r3).toString(), a.toString(), "c.add(r3)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/builtin.js new file mode 100644 index 000000000000..7a34b0ffdf90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: > + Tests that Temporal.PlainDateTime.prototype.until + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.until), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.until), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.until), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.until.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..3008f3a4cac3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, calendar); +instance.until(new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 0, 0, 0, calendar), { smallestUnit: "month" }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-copy-of-options.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-copy-of-options.js new file mode 100644 index 000000000000..87cc7f67166e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-copy-of-options.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: The dateUntil() method on the calendar is called with a copy of the options bag +features: [Temporal] +---*/ + +const originalOptions = { + largestUnit: "year", + shouldBeCopied: {}, +}; +let called = false; + +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(d1, d2, options) { + called = true; + assert.notSameValue(options, originalOptions, "options bag should be a copy"); + assert.sameValue(options.shouldBeCopied, originalOptions.shouldBeCopied, "options bag should be a shallow copy"); + return new Temporal.Duration(); + } +} +const calendar = new Calendar(); +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322, calendar); +earlier.until(later, originalOptions); +assert(called, "calendar.dateUntil must be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-plaindate-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-plaindate-calendar.js new file mode 100644 index 000000000000..6656ff1aabca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-plaindate-calendar.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: calendar.dateUntil() is passed PlainDate objects with the receiver's calendar +info: | + DifferenceISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2, calendar, largestUnit [ , options ] ) + + 8. Let _date1_ be ? CreateTemporalDate(_balanceResult_.[[Year]], _balanceResult_.[[Month]], _balanceResult_.[[Day]], _calendar_). + 9. Let _date2_ be ? CreateTemporalDate(_y2_, _mon2_, _d2_, _calendar_). + 12. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +features: [Temporal] +---*/ + +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(d1, d2) { + assert.sameValue(d1.calendar, this, "d1.calendar"); + assert.sameValue(d2.calendar, this, "d2.calendar"); + return new Temporal.Duration(); + } +} +const calendar = new Calendar(); +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322, calendar); +const result = earlier.until(later); +assert(result instanceof Temporal.Duration, "result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..21f7b583983c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.plaindatetime.prototype.until step 13: + 13. Let _diff_ be ? DifferenceISODateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _dateTime_.[[Calendar]], _largestUnit_, _options_). + sec-temporal-differenceisodatetime steps 9–11: + 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). + 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322, calendar); + earlier.until(later, { largestUnit }); + }, + { + years: ["year"], + months: ["month"], + weeks: ["week"], + days: ["day"], + hours: ["day"], + minutes: ["day"], + seconds: ["day"], + milliseconds: ["day"], + microseconds: ["day"], + nanoseconds: ["day"] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-fields-iterable.js new file mode 100644 index 000000000000..af3a94c3ace5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-fields-iterable.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +datetime.until({ year: 2005, month: 6, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-temporal-object.js new file mode 100644 index 000000000000..a0df81afceb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const date = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, temporalObject); + date.until({ year: 2005, month: 6, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js new file mode 100644 index 000000000000..c81009539c53 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: String and object arguments get cast +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +TemporalHelpers.assertDuration( + datetime.until({ year: 2019, month: 10, day: 29, hour: 10 }), + 0, 0, 0, 15684, 18, 36, 29, 876, 543, 211, + "plain object argument" +); + +TemporalHelpers.assertDuration( + datetime.until("2019-10-29T10:46:38.271986102"), + 0, 0, 0, 15684, 19, 23, 8, 148, 529, 313, + "string argument gets cast" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js new file mode 100644 index 000000000000..14c6f18eca4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Using different calendars is not acceptable +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(2000, 1, 1, 0, 0, 0, 0, 0, 0); + +const cal = { + id: 'thisisnotiso' +}; + +const dt2 = new Temporal.PlainDateTime(2000, 1, 1, 0, 0, 0, 0, 0, 0, cal); + +assert.throws( + RangeError, + () => dt1.until(dt2), + "cannot use until with PDTs having different calendars" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..50e39f64bdc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.until({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.until({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js new file mode 100644 index 000000000000..7cb683190dd7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: The since and until operations act as inverses +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const later = new Temporal.PlainDateTime(2016, 3, 3, 18); + +TemporalHelpers.assertDurationsEqual(dt.until(later), later.since(dt), "until and since act as inverses"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string.js new file mode 100644 index 000000000000..1c33be37fc90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); +const values = ["era", "eraYear", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..e709edcf6f9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 12, 13, 35, 57, 988, 655, 322); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => earlier.until(later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..7bfb69df4862 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); +const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => earlier.until(later, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-undefined.js new file mode 100644 index 000000000000..020c5442eb79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); + +const explicit = earlier.until(later, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 1, 1, 1, 987, 654, 321, "default largestUnit is day"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 1, 1, 1, 987, 654, 321, "default largestUnit is day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-wrong-type.js new file mode 100644 index 000000000000..f36eff357c3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "year", + (largestUnit) => earlier.until(later, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 1, 1, 1, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/length.js new file mode 100644 index 000000000000..c42b96f9c98b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Temporal.PlainDateTime.prototype.until.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.until, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/name.js new file mode 100644 index 000000000000..537a02528ba2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Temporal.PlainDateTime.prototype.until.name is "until". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.until, "name", { + value: "until", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js new file mode 100644 index 000000000000..3946ce1ac188 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Do not return Durations with unnecessary units +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const lastFeb20 = new Temporal.PlainDateTime(2020, 2, 29, 0, 0); +const lastFeb21 = new Temporal.PlainDateTime(2021, 2, 28, 0, 0); + +TemporalHelpers.assertDuration( + lastFeb20.until(lastFeb21, { largestUnit: "months" }), + 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + "does not include higher units than necessary (largest unit = months)" +); + +TemporalHelpers.assertDuration( + lastFeb20.until(lastFeb21, { largestUnit: "years" }), + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "does not include higher units than necessary (largest unit = years)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/not-a-constructor.js new file mode 100644 index 000000000000..6b224976f3e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: > + Temporal.PlainDateTime.prototype.until does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.until(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.until), false, + "isConstructor(Temporal.PlainDateTime.prototype.until)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/options-undefined.js new file mode 100644 index 000000000000..7875d565bc44 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/options-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2000, 6, 12, 12, 34, 56, 987, 654, 322); + +const explicit = earlier.until(later, undefined); +assert.sameValue(explicit.years, 0, "default largest unit is days"); +assert.sameValue(explicit.months, 0, "default largest unit is days"); +assert.sameValue(explicit.weeks, 0, "default largest unit is days"); +assert.sameValue(explicit.days, 41, "default largest unit is days"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = earlier.until(later); +assert.sameValue(implicit.years, 0, "default largest unit is days"); +assert.sameValue(implicit.months, 0, "default largest unit is days"); +assert.sameValue(implicit.weeks, 0, "default largest unit is days"); +assert.sameValue(implicit.days, 41, "default largest unit is days"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/prop-desc.js new file mode 100644 index 000000000000..82cfa51f1df3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: The "until" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.until, + "function", + "`typeof PlainDateTime.prototype.until` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "until", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..2b0e264e48e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/read-time-fields-before-datefromfields.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.plaindatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDateTime(_other_). + sec-temporal-totemporaldatetime step 2.e: + e. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = new Temporal.PlainDateTime(2021, 3, 31, 12, 34, 56, 987, 654, 321); +const duration = datetime.until({ year: 2021, month: 3, day: 31, calendar }); + +TemporalHelpers.assertDuration(duration, 0, 0, 0, 0, -12, -34, -56, -987, -654, -321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js new file mode 100644 index 000000000000..9531598f83e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Return days by default +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0); +const feb21 = new Temporal.PlainDateTime(2021, 2, 1, 0, 0); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "auto" }), + 0, 0, 0, 366, 0, 0, 0, 0, 0, 0, + "defaults to returning days (largest unit = auto)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "days" }), + 0, 0, 0, 366, 0, 0, 0, 0, 0, 0, + "defaults to returning days (largest unit = days)" +); + +TemporalHelpers.assertDuration( + feb20.until(new Temporal.PlainDateTime(2021, 2, 1, 0, 0, 0, 0, 0, 1)), + 0, 0, 0, 366, 0, 0, 0, 0, 0, 1, + "returns nanoseconds if argument is PDT with non-zero nanoseconds" +); + +const dt = new Temporal.PlainDateTime(2020, 2, 1, 0, 0, 0, 0, 0, 1); + +TemporalHelpers.assertDuration( + dt.until(feb21), + 0, 0, 0, 365, 23, 59, 59, 999, 999, 999, + "one nanosecond away from one year away" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/round-negative-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/round-negative-duration.js new file mode 100644 index 000000000000..b44f6f51d65f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/round-negative-duration.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Negative durations are rounded correctly by the modulo operation in NanosecondsToDays +info: | + sec-temporal-nanosecondstodays step 6: + 6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }. + sec-temporal-roundduration step 6: + 6. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + sec-temporal.plaindatetime.prototype.until step 14: + 14. Let _roundResult_ be ? RoundDuration(_diff_.[[Years]], _diff_.[[Months]], _diff_.[[Weeks]], _diff_.[[Days]], _diff_.[[Hours]], _diff_.[[Minutes]], _diff_.[[Seconds]], _diff_.[[Milliseconds]], _diff_.[[Microseconds]], _diff_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _dateTime_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12); +const later = new Temporal.PlainDateTime(2000, 5, 5); +const result = later.until(earlier, { smallestUnit: "day", roundingIncrement: 2 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-nan.js new file mode 100644 index 000000000000..d04dd1c644ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindatetime.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-non-integer.js new file mode 100644 index 000000000000..96bcff8a750d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 5); +const result = earlier.until(later, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..80cd91efa23f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-undefined.js new file mode 100644 index 000000000000..fcd1240cf2b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindatetime.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322); + +const explicit = earlier.until(later, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..a22c71bf7a1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindatetime.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => earlier.until(later, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 397, 1, 1, 1, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string.js new file mode 100644 index 000000000000..089746d7d8df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-undefined.js new file mode 100644 index 000000000000..00e4c66c68f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500); + +const explicit1 = earlier.until(later, { smallestUnit: "microsecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc"); +const implicit1 = earlier.until(later, { smallestUnit: "microsecond" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc"); + +const explicit2 = earlier.until(later, { smallestUnit: "millisecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 1, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc"); +const implicit2 = earlier.until(later, { smallestUnit: "millisecond" }); +TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 1, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc"); + +const explicit3 = earlier.until(later, { smallestUnit: "second", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc"); +const implicit3 = earlier.until(later, { smallestUnit: "second" }); +TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-wrong-type.js new file mode 100644 index 000000000000..580f6e64f93e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string.js new file mode 100644 index 000000000000..adf6f19a570c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321); +const values = ["era", "eraYear", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..c8273da67151 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainDateTime(2001, 6, 12, 13, 35, 57, 988, 655, 322); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => earlier.until(later, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-undefined.js new file mode 100644 index 000000000000..081a2a4a8741 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321); + +const explicit = earlier.until(later, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-wrong-type.js new file mode 100644 index 000000000000..9f06d658aede --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => earlier.until(later, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js new file mode 100644 index 000000000000..b655b10c7f7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Largest unit is respected +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0); + +const later = feb20.add({ + days: 1, + milliseconds: 250, + microseconds: 250, + nanoseconds: 250 +}); + +TemporalHelpers.assertDuration( + feb20.until(later, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, 86400250, 250, 250, + "can return subseconds (millisecond precision)" +); + +TemporalHelpers.assertDuration( + feb20.until(later, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 86400250250, 250, + "can return subseconds (microsecond precision)" +); + +TemporalHelpers.assertDuration( + feb20.until(later, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 86400250250250, + "can return subseconds (nanosecond precision)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js new file mode 100644 index 000000000000..503836577e5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js @@ -0,0 +1,69 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Largest unit is respected +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0); +const feb21 = new Temporal.PlainDateTime(2021, 2, 1, 0, 0); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "years" }), + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (years)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "months" }), + 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (months)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "weeks" }), + 0, 0, 52, 2, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (weeks)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "hours" }), + 0, 0, 0, 0, 8784, 0, 0,0, 0, 0, + "can return lower or higher units (hours)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "minutes" }), + 0, 0, 0, 0, 0, 527040, 0, 0, 0, 0, 0, + "can return lower or higher units (minutes)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "seconds" }), + 0, 0, 0, 0, 0, 0, 31622400, 0, 0, 0, + "can return lower or higher units (seconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, 31622400000, 0, 0, + "can return lower or higher units (milliseconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 31622400000000, 0, + "can return lower or higher units (microseconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 31622400000000000, + "can return lower or higher units (nanoseconds)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js new file mode 100644 index 000000000000..7e27778ad79e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Weeks and months are mutually exclusive +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const laterDateTime = dt.add({ days: 42, hours: 3 }); + +TemporalHelpers.assertDuration( + dt.until(laterDateTime, { largestUnit: "weeks" }), + 0, 0, 6, 0, 3, 0, 0, 0, 0, 0, + "weeks and months mutually exclusive (1)" +); + +TemporalHelpers.assertDuration( + dt.until(laterDateTime, { largestUnit: "months" }), + 0, 1, 0, 12, 3, 0, 0, 0, 0, 0, + "weeks and months mutually exclusive (2)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/year-zero.js new file mode 100644 index 000000000000..84b18c94d79f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/until/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00[UTC]" +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { instance.until(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js new file mode 100644 index 000000000000..553c2bbc23d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.valueof +description: Comparison operators (except !== and ===) do not work +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1963, 2, 13, 9, 36, 29, 123, 456, 789); +const dt1again = new Temporal.PlainDateTime(1963, 2, 13, 9, 36, 29, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +assert.sameValue(dt1 === dt1, true, "object equality implies ==="); +assert.sameValue(dt1 !== dt1again, true, "object non-equality, even if all data is the same, implies !=="); +assert.throws(TypeError, () => dt1 < dt1, "< throws (same objects)"); +assert.throws(TypeError, () => dt1 < dt2, "< throws (different objects)"); +assert.throws(TypeError, () => dt1 > dt1, "> throws (same objects)"); +assert.throws(TypeError, () => dt1 > dt2, "> throws (different objects)"); +assert.throws(TypeError, () => dt1 <= dt1, "<= does not throw (same objects)"); +assert.throws(TypeError, () => dt1 <= dt2, "<= throws (different objects)"); +assert.throws(TypeError, () => dt1 >= dt1, ">= throws (same objects)"); +assert.throws(TypeError, () => dt1 >= dt2, ">= throws (different objects)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/builtin.js new file mode 100644 index 000000000000..25bd6f2096c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.valueof +description: > + Tests that Temporal.PlainDateTime.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/length.js new file mode 100644 index 000000000000..94ec35eedfd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.valueof +description: Temporal.PlainDateTime.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/name.js new file mode 100644 index 000000000000..32f28badaa13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.valueof +description: Temporal.PlainDateTime.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/not-a-constructor.js new file mode 100644 index 000000000000..287edc0c5c38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.valueof +description: > + Temporal.PlainDateTime.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.valueOf), false, + "isConstructor(Temporal.PlainDateTime.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/prop-desc.js new file mode 100644 index 000000000000..f21fb8d988ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.valueof +description: The "valueOf" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.valueOf, + "function", + "`typeof PlainDateTime.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/valueOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js new file mode 100644 index 000000000000..3af96d98216a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.weekofyear +description: Checking week of year for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.weekOfYear, 47, "check week of year information"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/prop-desc.js new file mode 100644 index 000000000000..170417c6af13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.weekofyear +description: The "weekOfYear" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "weekOfYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js new file mode 100644 index 000000000000..b916ec87028f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Unrecognized properties (incl. plurals of recognized units) are ignored +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +assert.throws( + TypeError, + () => instance.with({}), + "empty object not acceptable" +); + +const units = ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]; + +units.forEach((unit) => { + let plural = `${unit}s`; + let options = {}; + options[plural] = 1; + assert.throws( + TypeError, + () => instance.with(options), + `plural unit ("${plural}" vs "${unit}") is not acceptable` + ); +}); + +assert.throws( + TypeError, + () => instance.with({nonsense: true}), + "throw if no recognized properties present" +); + +TemporalHelpers.assertPlainDateTime( + instance.with({year: 1965, nonsense: true}), + 1965, 5, "M05", 2, 12, 34, 56, 987, 654, 321, + "unrecognized properties ignored & does not throw if recognized properties present)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/basic.js new file mode 100644 index 000000000000..71f65458443d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/basic.js @@ -0,0 +1,80 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: A variety of "normal" (non-throwing, non-boundary case, non-null, etc.) arguments +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ year: 2019 }), + 2019, 11, "M11", 18, 15, 23, 30, 123, 456, 789, + "with year works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ month: 5 }), + 1976, 5, "M05", 18, 15, 23, 30, 123, 456, 789, + "with month works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ monthCode: "M05" }), + 1976, 5, "M05", 18, 15, 23, 30, 123, 456, 789, + "with month code works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ day: 5 }), + 1976, 11, "M11", 5, 15, 23, 30, 123, 456, 789, + "with day works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ hour: 5 }), + 1976, 11, "M11", 18, 5, 23, 30, 123, 456, 789, + "with hour works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ minute: 5 }), + 1976, 11, "M11", 18, 15, 5, 30, 123, 456, 789, + "with minute works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ second: 5 }), + 1976, 11, "M11", 18, 15, 23, 5, 123, 456, 789, + "with second works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ millisecond: 5 }), + 1976, 11, "M11", 18, 15, 23, 30, 5, 456, 789, + "with millisecond works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ microsecond: 5 }), + 1976, 11, "M11", 18, 15, 23, 30, 123, 5, 789, + "with microsecond works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ nanosecond: 5 }), + 1976, 11, "M11", 18, 15, 23, 30, 123, 456, 5, + "with nanosecond works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ month: 5, second: 15 }), + 1976, 5, "M05", 18, 15, 23, 15, 123, 456, 789, + "with month and second works" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/builtin.js new file mode 100644 index 000000000000..3e7cef2035c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: > + Tests that Temporal.PlainDateTime.prototype.with + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.with), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.with), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.with), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.with.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-fields-iterable.js new file mode 100644 index 000000000000..1e59a9033de8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-fields-iterable.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.prototype.with step 9: + 9. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +datetime.with({ year: 2005 }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-merge-fields-returns-primitive.js new file mode 100644 index 000000000000..18cec0b9fd30 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-merge-fields-returns-primitive.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: > + with() should throw a TypeError if mergeFields() returns a primitive, + without passing the value on to any other calendar methods +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive); + const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, calendar); + assert.throws(TypeError, () => instance.with({ year: 2005 }), "bad return from mergeFields() throws"); + assert.sameValue(calendar.dateFromFieldsCallCount, 0, "dateFromFields() never called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js new file mode 100644 index 000000000000..bebb363d2ff7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if a calendar is supplied +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +assert.throws( + TypeError, + () => datetime.with({ year: 2021, calendar: "iso8601" }), + "throws with calendar property" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/copies-merge-fields-object.js new file mode 100644 index 000000000000..92beb2d10da2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/copies-merge-fields-object.js @@ -0,0 +1,58 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: The object returned from mergeFields() is copied before being passed to dateFromFields(). +info: | + sec-temporal.plaindatetime.prototype.with steps 13–15: + 13. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialDate_). + 14. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»). + 15. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields step 2: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get day", + "get day.valueOf", + "call day.valueOf", + "get hour", + "get hour.valueOf", + "call hour.valueOf", + "get microsecond", + "get microsecond.valueOf", + "call microsecond.valueOf", + "get millisecond", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get minute", + "get minute.valueOf", + "call minute.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get nanosecond", + "get nanosecond.valueOf", + "call nanosecond.valueOf", + "get second", + "get second.valueOf", + "call second.valueOf", + "get year", + "get year.valueOf", + "call year.valueOf", +]; + +const calendar = TemporalHelpers.calendarMergeFieldsGetters(); +const datetime = new Temporal.PlainDateTime(2021, 3, 31, 12, 34, 56, 987, 654, 321, calendar); +datetime.with({ year: 2022 }); + +assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/copy-properties-not-undefined.js new file mode 100644 index 000000000000..e7dab597cac6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/copy-properties-not-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: PreparePartialTemporalFields copies only defined properties of source object +info: | + 4. For each value _property_ of _fieldNames_, do + a. Let _value_ be ? Get(_fields_, _property_). + b. If _value_ is not *undefined*, then + ... + iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDateTime = new Temporal.PlainDateTime(2006, 1, 24, 11, 42, 58); + +TemporalHelpers.assertPlainDateTime(plainDateTime.with({ day: 8, hour: 10, year: undefined }), + 2006, 1, "M01", 8, 10, 42, 58, 0, 0, 0, + "only the properties that are present and defined in the plain object are copied" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..31bdb1c51fda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.with +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.with({ [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.with({ [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/length.js new file mode 100644 index 000000000000..713432bb3238 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Temporal.PlainDateTime.prototype.with.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.with, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js new file mode 100644 index 000000000000..7f9619a83213 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: The month and month code should agree +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +assert.throws( + RangeError, + () => datetime.with({ month: 5, monthCode: "M06" }), + "month and monthCode must agree" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js new file mode 100644 index 000000000000..c259fe4769ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Unrecognized units are ignored +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const units = ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]; + +units.forEach((unit) => { + let plural = `${unit}s`; + let arg = { month: 12 }; + arg[plural] = 1; + TemporalHelpers.assertPlainDateTime( + datetime.with(arg), + 1976, 12, "M12", 18, 15, 23, 30, 123, 456, 789, + `unrecognized property (${plural}) gets ignored` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/name.js new file mode 100644 index 000000000000..516401b3dd18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Temporal.PlainDateTime.prototype.with.name is "with". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/not-a-constructor.js new file mode 100644 index 000000000000..9ac091862017 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: > + Temporal.PlainDateTime.prototype.with does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.with(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.with), false, + "isConstructor(Temporal.PlainDateTime.prototype.with)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js new file mode 100644 index 000000000000..f1570f3af1af --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Verify that undefined options are handled correctly. +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ day: 40 }, {}), + 1976, 11, "M11", 30, 15, 23, 30, 123, 456, 789, + "options may be empty object" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ day: 40 }, () => {}), + 1976, 11, "M11", 30, 15, 23, 30, 123, 456, 789, + "read empty options from function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js new file mode 100644 index 000000000000..05f7045eba5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Verify that undefined options are handled correctly. +features: [Temporal, Symbol] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n]; + +badOptions.forEach((bad) => { + assert.throws( + TypeError, + () => datetime.with({ day: 5 }, bad), + `bad options (${typeof bad})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-undefined.js new file mode 100644 index 000000000000..22b9915d52b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 2, 2, 12, 34, 56, 987, 654, 321); +const fields = { day: 31 }; + +const explicit = datetime.with(fields, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = datetime.with(fields); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js new file mode 100644 index 000000000000..9246fbafc935 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js @@ -0,0 +1,79 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Properties on an object passed to with() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const expected = [ + "get calendar", + "get timeZone", + "get day", + "get day.valueOf", + "call day.valueOf", + "get hour", + "get hour.valueOf", + "call hour.valueOf", + "get microsecond", + "get microsecond.valueOf", + "call microsecond.valueOf", + "get millisecond", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get minute", + "get minute.valueOf", + "call minute.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get nanosecond", + "get nanosecond.valueOf", + "call nanosecond.valueOf", + "get second", + "get second.valueOf", + "call second.valueOf", + "get year", + "get year.valueOf", + "call year.valueOf", +]; +const actual = []; +const fields = { + year: 1.7, + month: 1.7, + monthCode: "M01", + day: 1.7, + hour: 1.7, + minute: 1.7, + second: 1.7, + millisecond: 1.7, + microsecond: 1.7, + nanosecond: 1.7, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.with(argument); +TemporalHelpers.assertPlainDateTime(result, 1, 1, "M01", 1, 1, 1, 1, 1, 1, 1); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js new file mode 100644 index 000000000000..088ddde8fe96 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindatetime.prototype.with step 16: + 16. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.with({ minute: 45 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-undefined.js new file mode 100644 index 000000000000..17432b0d7767 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindatetime.prototype.with step 16: + 16. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); +const explicit = datetime.with({ minute: 67 }, { overflow: undefined }); +TemporalHelpers.assertPlainDateTime(explicit, 2000, 5, "M05", 2, 12, 59, 0, 0, 0, 0, "default overflow is constrain"); +const implicit = datetime.with({ minute: 67 }, {}); +TemporalHelpers.assertPlainDateTime(implicit, 2000, 5, "M05", 2, 12, 59, 0, 0, 0, 0, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-wrong-type.js new file mode 100644 index 000000000000..1b261ab3ccab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/overflow-wrong-type.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plaindatetime.prototype.with step 16: + 16. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); + +// See TemporalHelpers.checkStringOptionWrongType(); this code path has +// different expectations for observable calls + +assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: null }), "null"); +assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: true }), "true"); +assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: false }), "false"); +assert.throws(TypeError, () => datetime.with({ minute: 45 }, { overflow: Symbol() }), "symbol"); +assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: 2n }), "bigint"); +assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: {} }), "plain object"); + +// toString property is read once by Calendar.dateFromFields() in the builtin +// calendars, to get the option value for the date part, and then once again +// internally to get the option value for the time part. +const expected = [ + "get overflow.toString", + "call overflow.toString", + "get overflow.toString", + "call overflow.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); +const result = datetime.with({ minute: 45 }, { overflow: observer }); +TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 45, 0, 0, 0, 0, "object with toString"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/prop-desc.js new file mode 100644 index 000000000000..b0a7e95026e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: The "with" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.with, + "function", + "`typeof PlainDateTime.prototype.with` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "with", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..ccb33e0b041d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/read-time-fields-before-datefromfields.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.plaindatetime.prototype.with step 15: + 15. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = new Temporal.PlainDateTime(2021, 3, 31, 12, 34, 56, 987, 654, 321, calendar); +const newDatetime = datetime.with({ year: 2022 }); + +assert.sameValue(newDatetime.hour, 12, "hour value"); +assert.sameValue(newDatetime.minute, 34, "minute value"); +assert.sameValue(newDatetime.second, 56, "second value"); +assert.sameValue(newDatetime.millisecond, 987, "millisecond value"); +assert.sameValue(newDatetime.microsecond, 654, "microsecond value"); +assert.sameValue(newDatetime.nanosecond, 321, "nanosecond value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js new file mode 100644 index 000000000000..d21ed20e8ec2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if a string argument is supplied +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +const baddies = ["12:00", "1995-04-07", "2019-05-17T12:34:56.007007007", "2019-05-17T12:34:56.007007007Z", "42"]; + +baddies.forEach((bad) => { + assert.throws( + TypeError, + () => instance.with(bad), + `bad argument (${bad})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/subclassing-ignored.js new file mode 100644 index 000000000000..e38f3bebf087 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Objects of a subclass are never created as return values for with() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDateTime, + [2000, 5, 2, 12, 34, 56, 987, 654, 321], + "with", + [{ nanosecond: 1 }], + (result) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 1), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js new file mode 100644 index 000000000000..2e988eeecfbf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if a timezone is supplied +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +assert.throws( + TypeError, + () => datetime.with({ year: 2021, timeZone: "UTC" }), + "throws with timezone property" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/builtin.js new file mode 100644 index 000000000000..8599e1ff9c85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withcalendar +description: > + Tests that Temporal.PlainDateTime.prototype.withCalendar + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.withCalendar), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.withCalendar), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.withCalendar), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.withCalendar.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/calendar-temporal-object.js new file mode 100644 index 000000000000..536ff0ccee26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/calendar-temporal-object.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withcalendar +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.withcalendar step 3: + 3. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const result = plainDateTime.withCalendar(temporalObject); + assert.sameValue(result.calendar, calendar, 'Temporal object coerced to calendar'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/length.js new file mode 100644 index 000000000000..7b3a17411ebf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withcalendar +description: Temporal.PlainDateTime.prototype.withCalendar.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.withCalendar, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/missing-argument.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/missing-argument.js new file mode 100644 index 000000000000..d92f64049454 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/missing-argument.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withcalendar +description: RangeError thrown when calendar argument not given +features: [Temporal] +---*/ + +const plainDateTime = Temporal.PlainDateTime.from("1976-11-18T14:00:00"); +assert.throws(RangeError, () => plainDateTime.withCalendar(), "missing argument"); +assert.throws(RangeError, () => plainDateTime.withCalendar(undefined), "undefined argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/name.js new file mode 100644 index 000000000000..64a08f581885 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withcalendar +description: Temporal.PlainDateTime.prototype.withCalendar.name is "withCalendar". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.withCalendar, "name", { + value: "withCalendar", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/not-a-constructor.js new file mode 100644 index 000000000000..34b602c1ac41 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withcalendar +description: > + Temporal.PlainDateTime.prototype.withCalendar does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.withCalendar(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.withCalendar), false, + "isConstructor(Temporal.PlainDateTime.prototype.withCalendar)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/prop-desc.js new file mode 100644 index 000000000000..249c69278161 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withcalendar +description: The "withCalendar" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.withCalendar, + "function", + "`typeof PlainDateTime.prototype.withCalendar` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "withCalendar", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/subclassing-ignored.js new file mode 100644 index 000000000000..fb95a3d33050 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withCalendar/subclassing-ignored.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withcalendar +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const customCalendar = { + era() { return undefined; }, + eraYear() { return undefined; }, + year() { return 1900; }, + month() { return 2; }, + monthCode() { return "M02"; }, + day() { return 5; }, + toString() { return "custom-calendar"; }, +}; + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDateTime, + [2000, 5, 2, 12, 34, 56, 987, 654, 321], + "withCalendar", + [customCalendar], + (result) => { + TemporalHelpers.assertPlainDateTime(result, 1900, 2, "M02", 5, 12, 34, 56, 987, 654, 321); + assert.sameValue(result.calendar, customCalendar, "calendar result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js new file mode 100644 index 000000000000..e376b9e01f7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Unrecognized properties of plain object ignored +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30); + +assert.throws( + TypeError, + () => dt.withPlainDate({}), + "empty object not acceptable" +); + +assert.throws( + TypeError, + () => dt.withPlainDate({ months: 12 }), // should be "month" + "no recognized properties (look like it might work)" +); + +assert.throws( + TypeError, + () => dt.with({nonsense: true}), + "no recognized properties (clearly won't work)" +); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainDate({ year: 2000, month: 6, day: 1, months: 123 }), // 'months' unrecognized; see above + 2000, 6, "M06", 1, 3, 24, 30, 0, 0, 0, + "unrecognized properties ignored & does not throw if recognized properties present)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js new file mode 100644 index 000000000000..90b60fb2b015 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Plain object may be acceptable +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainDate({ year: 2000, month: 6, day: 1 }), + 2000, 6, "M06", 1, 3, 24, 30, 0, 0, 0, + "plain object works" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js new file mode 100644 index 000000000000..852f9d3be268 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: PlainDate object is acceptable +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30); +const date = new Temporal.PlainDate(2020, 1, 23); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainDate(date), + 2020, 1, "M01", 23, 3, 24, 30, 0, 0, 0, + "PlainDate argument works" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindatetime.js new file mode 100644 index 000000000000..428ee75fccf7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.withplaindate +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.withplaindate step 3: + 3. Let _plainDate_ be ? ToTemporalDate(_plainDateLike_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const receiver = new Temporal.PlainDateTime(2001, 9, 9, 6, 54, 32, 123, 456, 789); + const result = receiver.withPlainDate(datetime); + TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 6, 54, 32, 123, 456, 789); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js new file mode 100644 index 000000000000..d39e0b596221 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.withPlainDate(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js new file mode 100644 index 000000000000..c1d8b4f70c29 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: New calendar is preserved if original PDT has ISO calendar +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const cal = { + id: 'thisisnotiso', + era() { return "the era"; }, + eraYear() { return 1909; }, + toString() { return "this is a string"; }, + year() { return 2008; }, + month() { return 9; }, + monthCode() { return "M09"; }, + day() { return 6; } +}; +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal); +const shifted = dt.withPlainDate("2010-11-12"); + +TemporalHelpers.assertPlainDateTime( + shifted, + 2008, 9, "M09", 6, 3, 24, 30, 0, 0, 0, + "calendar is unchanged if input has ISO calendar (1)", + "the era", + 1909 +); + +assert.sameValue( + shifted.calendar, + cal, + "calendar is unchanged if input has ISO calendar (2)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..d18a2a876cc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.withPlainDate(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js new file mode 100644 index 000000000000..e0ffd12e07cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: PlainDate-like string argument is acceptable +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainDate("2018-09-15"), + 2018, 9, "M09", 15, 3, 24, 30, 0, 0, 0, + "PlainDate-like string argument works" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..d2a6bd73c3de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.withPlainDate(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..cb9bcd212341 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => plain.withPlainDate(zoned), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..4a28b13aac17 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.withPlainDate(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..731007ec8645 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => plain.withPlainDate(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/builtin.js new file mode 100644 index 000000000000..ee09d79f286e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: > + Tests that Temporal.PlainDateTime.prototype.withPlainDate + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.withPlainDate), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.withPlainDate), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.withPlainDate), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.withPlainDate.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..fdcc89504769 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +instance.withPlainDate({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-fields-iterable.js new file mode 100644 index 000000000000..815b0121e417 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-fields-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindatetime.prototype.withplaindate step 3: + 3. Let _plainDate_ be ? ToTemporalDate(_plainDateLike_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.PlainDateTime(2000, 5, 3, 13, 3, 27, 123, 456, 789, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +datetime.withPlainDate({ year: 2001, month: 6, day: 4, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-temporal-object.js new file mode 100644 index 000000000000..dbadfed8ca42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.withplaindate step 3: + 3. Let _plainDate_ be ? ToTemporalDate(_plainDateLike_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 3, 13, 3, 27, 123, 456, 789); + // the PlainDate's calendar will override the PlainDateTime's ISO calendar + const result = datetime.withPlainDate({ year: 2001, month: 6, day: 4, calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..6b636c55b1bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.withplaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.withPlainDate({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.withPlainDate({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/length.js new file mode 100644 index 000000000000..135dba6ec19f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Temporal.PlainDateTime.prototype.withPlainDate.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.withPlainDate, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/name.js new file mode 100644 index 000000000000..be6fd4f10c0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Temporal.PlainDateTime.prototype.withPlainDate.name is "withPlainDate". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.withPlainDate, "name", { + value: "withPlainDate", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js new file mode 100644 index 000000000000..8ec7e1477df6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.withplaindate +description: If two non-ISO calendars are involved, an error is raised +features: [Temporal] +---*/ + +const cal = { + id: 'foo', + toString() { return "this is a string"; }, +}; + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal); + +const anotherCal = { + id: 'bar', + toString() { return "this is another string"; }, +}; + +const date = new Temporal.PlainDate(2008, 9, 6, anotherCal); + +assert.throws( + RangeError, + () => dt.withPlainDate(date), + "throws if both `this` and `other` have a non-ISO calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/not-a-constructor.js new file mode 100644 index 000000000000..1b47c6bf6f21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: > + Temporal.PlainDateTime.prototype.withPlainDate does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.withPlainDate(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.withPlainDate), false, + "isConstructor(Temporal.PlainDateTime.prototype.withPlainDate)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/prop-desc.js new file mode 100644 index 000000000000..f2a6bdd3f6a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: The "withPlainDate" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.withPlainDate, + "function", + "`typeof PlainDateTime.prototype.withPlainDate` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "withPlainDate", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/subclassing-ignored.js new file mode 100644 index 000000000000..4e16eda6e386 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDateTime, + [2000, 5, 2, 12, 34, 56, 987, 654, 321], + "withPlainDate", + ["1999-04-27"], + (result) => TemporalHelpers.assertPlainDateTime(result, 1999, 4, "M04", 27, 12, 34, 56, 987, 654, 321), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/year-zero.js new file mode 100644 index 000000000000..b3f967db678e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +assert.throws( + RangeError, + () => { instance.withPlainDate(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js new file mode 100644 index 000000000000..262b8e986909 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: A plain object can be used as an argument +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500); + +assert.throws( + TypeError, + () => dt.withPlainTime({}), + "empty object not an acceptable argument" +); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime({ hour: 10 }), + 2015, 12, "M12", 7, 10, 0, 0, 0, 0, 0, + "plain object (hour) works" +); + +assert.throws( + TypeError, + () => dt.withPlainTime({ hours: 9 }), // should be "hour", see above + "plain object with a single unrecognized property fails" +); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime({ hour: 10, seconds: 123 }), + 2015, 12, "M12", 7, 10, 0, 0, 0, 0, 0, + "unrecognized properties are ignored if at least one recognized property is present" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..ae0d2abc9edd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +assert.throws( + RangeError, + () => instance.withPlainTime(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..e5b6dbad793e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.withPlainTime(arg), + `${string} is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.withPlainTime(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.withPlainTime(arg), + 'space is not accepted as a substitute for T prefix' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => instance.withPlainTime(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-with-time-designator.js new file mode 100644 index 000000000000..93d57e0dddda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-with-time-designator.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 1, 1, 12, 30, 45, 123, 456, 789); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.withPlainTime(arg); + TemporalHelpers.assertPlainDateTime(result, 2000, 1, "M01", 1, 0, 30, 0, 0, 0, 0, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..02c14ad1993e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.withPlainTime(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js new file mode 100644 index 000000000000..a7c0e5d278f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: String argument without ISO 8601 time designator "T" allowed +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime("12:34"), + 2015, 12, "M12", 7, 12, 34, 0, 0, 0, 0, + "time-like string works" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js new file mode 100644 index 000000000000..e588207282c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: An instance of PlainTime can be used as an argument +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500); +const hour = 11; +const minute = 22; +const time = new Temporal.PlainTime(hour, minute); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime(time), + 2015, + 12, + "M12", + 7, + hour, + minute, + 0, + 0, + 0, + 0, + "PlainTime argument works" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..da1bc4cfa3e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaindatetime.prototype.withplaintime step 4: + 4. Let _plainTime_ be ? ToTemporalTime(_plainTimeLike_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const pdt = new Temporal.PlainDateTime(2000, 5, 2); +const newpdt = pdt.withPlainTime(datetime); + +TemporalHelpers.assertPlainDateTime(newpdt, 2000, 5, "M05", 2, 1, 1, 1, 1, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..e2f0e52fd0cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321); +const result = instance.withPlainTime(datetime); +TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 16, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..28853d41f54c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.withPlainTime(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..2e934d9b6eca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => plain.withPlainTime(zoned), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..8a819d117792 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => plain.withPlainTime(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..85754205278f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const plain = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + const zoned = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => plain.withPlainTime(zoned)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/builtin.js new file mode 100644 index 000000000000..239cd9dd307c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: > + Tests that Temporal.PlainDateTime.prototype.withPlainTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDateTime.prototype.withPlainTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDateTime.prototype.withPlainTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDateTime.prototype.withPlainTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDateTime.prototype.withPlainTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/calendar-temporal-object.js new file mode 100644 index 000000000000..99eaee4e6e43 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/calendar-temporal-object.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime.prototype.withplaintime step 4.a: + a. Let _plainTime_ be ? ToTemporalTime(_plainTimeLike_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + assert.throws(RangeError, () => datetime.withPlainTime({ hour: 12, minute: 30, calendar: temporalObject })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/length.js new file mode 100644 index 000000000000..8d45f07a5779 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: Temporal.PlainDateTime.prototype.withPlainTime.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.withPlainTime, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/name.js new file mode 100644 index 000000000000..31b58c11e727 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: Temporal.PlainDateTime.prototype.withPlainTime.name is "withPlainTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDateTime.prototype.withPlainTime, "name", { + value: "withPlainTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js new file mode 100644 index 000000000000..846f03480957 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: If no argument is given, default to midnight +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime(), + 2015, 12, "M12", 7, 0, 0, 0, 0, 0, 0, + "no argument defaults to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/not-a-constructor.js new file mode 100644 index 000000000000..fea61fa56c34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: > + Temporal.PlainDateTime.prototype.withPlainTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDateTime.prototype.withPlainTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDateTime.prototype.withPlainTime), false, + "isConstructor(Temporal.PlainDateTime.prototype.withPlainTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/plaintime-propertybag-no-time-units.js new file mode 100644 index 000000000000..8ef6e565de82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/plaintime-propertybag-no-time-units.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: Missing time units in property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 1, 1, 12, 30, 45, 123, 456, 789); + +const props = {}; +assert.throws(TypeError, () => instance.withPlainTime(props), "TypeError if at least one property is not present"); + +props.minute = 30; +const result = instance.withPlainTime(props); +TemporalHelpers.assertPlainDateTime(result, 2000, 1, "M01", 1, 0, 30, 0, 0, 0, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/prop-desc.js new file mode 100644 index 000000000000..3f4aa87b412f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: The "withPlainTime" property of Temporal.PlainDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDateTime.prototype.withPlainTime, + "function", + "`typeof PlainDateTime.prototype.withPlainTime` is `function`" +); + +verifyProperty(Temporal.PlainDateTime.prototype, "withPlainTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/subclassing-ignored.js new file mode 100644 index 000000000000..77b098aff097 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainDateTime, + [2000, 5, 2, 12, 34, 56, 987, 654, 321], + "withPlainTime", + ["05:43:21.123456789"], + (result) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 5, 43, 21, 123, 456, 789), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/time-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/time-undefined.js new file mode 100644 index 000000000000..9f7546c6802f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/time-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: The time is assumed to be midnight if not given +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +const explicit = datetime.withPlainTime(undefined); +assert.sameValue(explicit.hour, 0, "default time is midnight"); +assert.sameValue(explicit.minute, 0, "default time is midnight"); +assert.sameValue(explicit.second, 0, "default time is midnight"); +assert.sameValue(explicit.millisecond, 0, "default time is midnight"); +assert.sameValue(explicit.microsecond, 0, "default time is midnight"); +assert.sameValue(explicit.nanosecond, 0, "default time is midnight"); + +const implicit = datetime.withPlainTime(); +assert.sameValue(implicit.hour, 0, "default time is midnight"); +assert.sameValue(implicit.minute, 0, "default time is midnight"); +assert.sameValue(implicit.second, 0, "default time is midnight"); +assert.sameValue(implicit.millisecond, 0, "default time is midnight"); +assert.sameValue(implicit.microsecond, 0, "default time is midnight"); +assert.sameValue(implicit.nanosecond, 0, "default time is midnight"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/year-zero.js new file mode 100644 index 000000000000..15f82475e1df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-12-07T03:24:30', + '-000000-12-07T03:24:30+01:00[UTC]' +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.withPlainTime(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/year/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/year/calendar-returns-infinity.js new file mode 100644 index 000000000000..a55423be4823 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/year/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.year +description: Getter throws if the calendar returns ±∞ from its year method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + year() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, pos); +assert.throws(RangeError, () => instance1.year); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, neg); +assert.throws(RangeError, () => instance2.year); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/year/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/year/prop-desc.js new file mode 100644 index 000000000000..d12071b7111e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/year/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.year +description: The "year" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "year"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/second-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/second-undefined.js new file mode 100644 index 000000000000..b12dbbf72ef0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/second-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Second argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [2000, 5, 2, 12, 34]; + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 34, 0, 0, 0, 0, + "second default argument (argument present)" +); + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 34, 0, 0, 0, 0, + "second default argument (argument missing)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/shell.js index e69de29bb2d1..1d70b7579ee9 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainDateTime/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/basic.js new file mode 100644 index 000000000000..5dc759dbcb6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/basic.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: Basic tests for the PlainMonthDay constructor. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const leapDay = new Temporal.PlainMonthDay(2, 29); +TemporalHelpers.assertPlainMonthDay(leapDay, "M02", 29, "leap day is supported"); +assert.sameValue(leapDay.calendar.id, "iso8601", "leap day calendar"); + +const beforeEpoch = new Temporal.PlainMonthDay(12, 2, "iso8601", 1920); +TemporalHelpers.assertPlainMonthDay(beforeEpoch, "M12", 2, "reference year before epoch", 1920); +assert.sameValue(beforeEpoch.calendar.id, "iso8601", "reference year before epoch calendar"); + +const afterEpoch = new Temporal.PlainMonthDay(1, 7, "iso8601", 1980); +TemporalHelpers.assertPlainMonthDay(afterEpoch, "M01", 7, "reference year after epoch", 1980); +assert.sameValue(afterEpoch.calendar.id, "iso8601", "reference year after epoch calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/builtin.js new file mode 100644 index 000000000000..e46327cc6214 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: Tests that Temporal.PlainMonthDay meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.PlainMonthDay.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-always.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-always.js new file mode 100644 index 000000000000..555a53b5bec4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-always.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: If calendar name is to be emitted, include additional reference info +features: [Temporal] +---*/ + +const pmd = new Temporal.PlainMonthDay(10, 31, "iso8601", 2019); + +assert.sameValue( + pmd.toString({ calendarName: 'always' }), + "2019-10-31[u-ca=iso8601]", + "emit year-month-day if calendarName = 'always' (four-argument constructor)" +); + +const anotherPMD = Temporal.PlainMonthDay.from("2019-10-31"); // 2019 will get dropped + +assert.sameValue( + anotherPMD.toString({ calendarName: 'always' }), + "1972-10-31[u-ca=iso8601]", + "emit fallback year if calendarName = 'always' (static from)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-invalid.js new file mode 100644 index 000000000000..bd3d87e74b95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-invalid.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainMonthDay throws a RangeError if the calendar argument is invalid +esid: sec-temporal.plainmonthday +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"]; +const actual = []; +const args = [ + TemporalHelpers.toPrimitiveObserver(actual, 2, "month"), + TemporalHelpers.toPrimitiveObserver(actual, 1, "day"), + "local", + TemporalHelpers.toPrimitiveObserver(actual, 1, "year") +]; +assert.throws(RangeError, () => new Temporal.PlainMonthDay(...args)); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-temporal-object.js new file mode 100644 index 000000000000..ac1dea51c431 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-temporal-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainmonthday step 5: + 5. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = new Temporal.PlainMonthDay(5, 2, temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-undefined.js new file mode 100644 index 000000000000..a8571289ace5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: Calendar argument defaults to the built-in ISO 8601 calendar +features: [Temporal] +---*/ + +const args = [5, 2]; + +Object.defineProperty(Temporal.Calendar, "from", { + get() { + throw new Test262Error("Should not get Calendar.from"); + }, +}); + +const dateExplicit = new Temporal.PlainMonthDay(...args, undefined); +assert.sameValue(dateExplicit.calendar.toString(), "iso8601"); + +const dateImplicit = new Temporal.PlainMonthDay(...args); +assert.sameValue(dateImplicit.calendar.toString(), "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/constructor.js new file mode 100644 index 000000000000..bb93b5f5506a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: Temporal.PlainMonthDay constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.PlainMonthDay()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..97de764aa392 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-with-utc-designator.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: RangeError thrown if a string with UTC designator is used as a PlainMonthDay +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainMonthDay.from(arg), + "String with UTC designator should not be valid as a PlainMonthDay" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/builtin.js new file mode 100644 index 000000000000..9063f58e0a8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Tests that Temporal.PlainMonthDay.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-fields-iterable.js new file mode 100644 index 000000000000..797f3448cf73 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-fields-iterable.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainmonthday.from step 3: + 3. Return ? ToTemporalMonthDay(_item_, _options_). + sec-temporal-totemporalmonthday step 2.f: + f. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +Temporal.PlainMonthDay.from({ monthCode: "M05", day: 2, calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..e712df7f1450 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-called-with-options-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +features: [Temporal] +---*/ + +const realMonthDayFromFields = Temporal.Calendar.prototype.monthDayFromFields; +let monthDayFromFieldsCallCount = 0; +Temporal.Calendar.prototype.monthDayFromFields = function (fields, options) { + monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return realMonthDayFromFields.call(this, fields, options); +} + +Temporal.PlainMonthDay.from("2000-05-02"); +assert.sameValue(monthDayFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.monthDayFromFields = realMonthDayFromFields; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-temporal-object.js new file mode 100644 index 000000000000..16f3e1447a70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainmonthday.from step 3: + 3. Return ? ToTemporalMonthDay(_item_, _options_). + sec-temporal-totemporalmonthday step 3.e: + e. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = Temporal.PlainMonthDay.from({ monthCode: "M05", day: 2, calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-leap-day.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-leap-day.js new file mode 100644 index 000000000000..f72165165d2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-leap-day.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Basic tests for PlainMonthDay.from(string). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +// Leap years +["reject", "constrain"].forEach((overflow) => { + const string = Temporal.PlainMonthDay.from("02-29", { overflow }); + TemporalHelpers.assertPlainMonthDay(string, "M02", 29, `from ${overflow} string`); + + const monthCode = Temporal.PlainMonthDay.from({ monthCode: "M02", day: 29 }, { overflow }); + TemporalHelpers.assertPlainMonthDay(monthCode, "M02", 29, `from ${overflow} with monthCode`); + + const implicit = Temporal.PlainMonthDay.from({ month: 2, day: 29 }, { overflow }); + TemporalHelpers.assertPlainMonthDay(implicit, "M02", 29, `from ${overflow} without year`); + + const explicit = Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 1996 }, { overflow }); + TemporalHelpers.assertPlainMonthDay(explicit, "M02", 29, `from ${overflow} with leap year`); +}); + +// Non-leap years +assert.throws(RangeError, + () => Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 2001 }, { overflow: "reject" }), + "from reject with non-leap year"); + +const nonLeap = Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 2001 }, { overflow: "constrain" }); +TemporalHelpers.assertPlainMonthDay(nonLeap, "M02", 28, "from constrain with non-leap year"); + +assert.throws(RangeError, + () => Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 2001, calendar: "iso8601" }, { overflow: "reject" }), + "from reject with non-leap year and explicit calendar"); + +const nonLeapCalendar = Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 2001, calendar: "iso8601" }, { overflow: "constrain" }); +TemporalHelpers.assertPlainMonthDay(nonLeapCalendar, "M02", 28, "from constrain with non-leap year and explicit calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-missing-properties.js new file mode 100644 index 000000000000..130b548f741b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-missing-properties.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Basic tests for PlainMonthDay.from(object) with missing properties. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.PlainMonthDay.from({}), "No properties"); +assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ day: 15 }), "Only day"); +assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ monthCode: 'M12' }), "Only monthCode"); +assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ monthCode: undefined, day: 15 }), "monthCode undefined"); +assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ months: 12, day: 31 }), "months plural"); +assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ month: 11, day: 18, calendar: "iso8601" }), "month, day with calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-object.js new file mode 100644 index 000000000000..af3704f06642 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Basic tests for PlainMonthDay.from(object). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const tests = [ + [{ monthCode: "M10", day: 1 }, "option bag with monthCode"], + [{ monthCode: "M10", day: 1, year: 2015 }, "option bag with year, monthCode"], + [{ month: 10, day: 1 }, "option bag with year, month"], + [{ month: 10, day: 1, year: 2015 }, "option bag with year, month"], + [{ month: 10, day: 1, days: 31 }, "option bag with plural 'days'"], + [new Temporal.PlainMonthDay(10, 1), "PlainMonthDay object"], + [Temporal.PlainDate.from("2019-10-01"), "PlainDate object"], +]; + +for (const [argument, description = argument] of tests) { + const plainMonthDay = Temporal.PlainMonthDay.from(argument); + assert.notSameValue(plainMonthDay, argument, `from ${description} converts`); + TemporalHelpers.assertPlainMonthDay(plainMonthDay, "M10", 1, `from ${description}`); + assert.sameValue(plainMonthDay.calendar.id, "iso8601", `from ${description} calendar`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-plainmonthday.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-plainmonthday.js new file mode 100644 index 000000000000..77db7ceac9bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-plainmonthday.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Basic tests for PlainMonthDay.from(PlainMonthDay). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get overflow", + "get overflow.toString", + "call overflow.toString", +]; +const actual = []; +const options = { + get overflow() { + actual.push("get overflow"); + return TemporalHelpers.toPrimitiveObserver(actual, "reject", "overflow"); + } +}; + +const fields = new Temporal.PlainMonthDay(11, 16, undefined, 1960); +const result = Temporal.PlainMonthDay.from(fields, options); +TemporalHelpers.assertPlainMonthDay(result, "M11", 16, "should copy reference year", 1960); +assert.compareArray(actual, expected, "Should get overflow"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-string.js new file mode 100644 index 000000000000..edb584f183a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-string.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Basic tests for PlainMonthDay.from(string). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const tests = [ + "10-01", + "1001", + "1965-10-01", + "1976-10-01T152330.1+00:00", + "19761001T15:23:30.1+00:00", + "1976-10-01T15:23:30.1+0000", + "1976-10-01T152330.1+0000", + "19761001T15:23:30.1+0000", + "19761001T152330.1+00:00", + "19761001T152330.1+0000", + "+001976-10-01T152330.1+00:00", + "+0019761001T15:23:30.1+00:00", + "+001976-10-01T15:23:30.1+0000", + "+001976-10-01T152330.1+0000", + "+0019761001T15:23:30.1+0000", + "+0019761001T152330.1+00:00", + "+0019761001T152330.1+0000", + "1976-10-01T15:23:00", + "1976-10-01T15:23", + "1976-10-01T15", + "1976-10-01", + "--10-01", + "--1001", + 1001, +]; + +for (const argument of tests) { + const plainMonthDay = Temporal.PlainMonthDay.from(argument); + assert.notSameValue(plainMonthDay, argument, `from ${argument} converts`); + TemporalHelpers.assertPlainMonthDay(plainMonthDay, "M10", 1, `from ${argument}`); + assert.sameValue(plainMonthDay.calendar.id, "iso8601", `from ${argument} calendar`); +} + +assert.throws(RangeError, () => Temporal.PlainMonthDay.from("11-18junk"), "no junk at end of string"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..fc01224a13a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainmonthday.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainMonthDay.from({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => Temporal.PlainMonthDay.from({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/length.js new file mode 100644 index 000000000000..584ef5530d7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Temporal.PlainMonthDay.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/name.js new file mode 100644 index 000000000000..8490ca0e197d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Temporal.PlainMonthDay.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/not-a-constructor.js new file mode 100644 index 000000000000..8fd7785d939f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Temporal.PlainMonthDay.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.from), false, + "isConstructor(Temporal.PlainMonthDay.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-invalid.js new file mode 100644 index 000000000000..8ca417d5173f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-invalid.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const fields = { month: 2, day: 31 }; + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +for (const badOptions of values) { + assert.throws(TypeError, () => Temporal.PlainMonthDay.from(fields, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-undefined.js new file mode 100644 index 000000000000..77010318cdb0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +includes: [temporalHelpers.js] +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const fields = { month: 2, day: 31 }; + +const explicit = Temporal.PlainMonthDay.from(fields, undefined); +TemporalHelpers.assertPlainMonthDay(explicit, "M02", 29, "default overflow is constrain"); + +const implicit = Temporal.PlainMonthDay.from(fields); +TemporalHelpers.assertPlainMonthDay(implicit, "M02", 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/order-of-operations.js new file mode 100644 index 000000000000..9ec29a7de162 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/order-of-operations.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Properties on an object passed to from() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get calendar", + "get day", + "get day.valueOf", + "call day.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; +const actual = []; +const fields = { + year: 1.7, + month: 1.7, + monthCode: "M01", + day: 1.7, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + if (key === "calendar") return Temporal.Calendar.from("iso8601"); + const result = target[key]; + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = Temporal.PlainMonthDay.from(argument); +TemporalHelpers.assertPlainMonthDay(result, "M01", 1); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js new file mode 100644 index 000000000000..9c039b63182d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporalmonthday steps 3–4: + 3. If Type(_item_) is Object, then + ... + j. Return ? MonthDayFromFields(_calendar_, _fields_, _options_). + 4. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plainmonthday.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalMonthDay]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalMonthDay(_item_, _options_). +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainMonthDay(5, 2), + { monthCode: "M05", day: 2 }, + "05-02", +]; + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainMonthDay.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-undefined.js new file mode 100644 index 000000000000..e1b5dc0af1c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-undefined.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporalmonthday steps 3–4: + 3. If Type(_item_) is Object, then + ... + j. Return ? MonthDayFromFields(_calendar_, _fields_, _options_). + 4. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plainmonthday.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalMonthDay]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalMonthDay(_item_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainMonthDay(5, 2), + "05-02", +]; +validValues.forEach((value) => { + const explicit = Temporal.PlainMonthDay.from(value, { overflow: undefined }); + TemporalHelpers.assertPlainMonthDay(explicit, "M05", 2, "overflow is ignored"); + const implicit = Temporal.PlainMonthDay.from(value, {}); + TemporalHelpers.assertPlainMonthDay(implicit, "M05", 2, "overflow is ignored"); + const lambda = Temporal.PlainMonthDay.from(value, () => {}); + TemporalHelpers.assertPlainMonthDay(lambda, "M05", 2, "overflow is ignored"); +}); + +const propertyBag = { year: 2000, month: 13, day: 34 }; +const explicit = Temporal.PlainMonthDay.from(propertyBag, { overflow: undefined }); +TemporalHelpers.assertPlainMonthDay(explicit, "M12", 31, "default overflow is constrain"); +const implicit = Temporal.PlainMonthDay.from(propertyBag, {}); +TemporalHelpers.assertPlainMonthDay(implicit, "M12", 31, "default overflow is constrain"); +const lambda = Temporal.PlainMonthDay.from(propertyBag, () => {}); +TemporalHelpers.assertPlainMonthDay(lambda, "M12", 31, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-wrong-type.js new file mode 100644 index 000000000000..11d63c249210 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-wrong-type.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporalmonthday steps 3–4: + 3. If Type(_item_) is Object, then + ... + j. Return ? MonthDayFromFields(_calendar_, _fields_, _options_). + 4. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plainmonthday.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalMonthDay]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalMonthDay(_item_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainMonthDay(5, 2), + { monthCode: "M05", day: 2 }, + "05-02", +]; +validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => Temporal.PlainMonthDay.from(value, { overflow }), + (result, descr) => TemporalHelpers.assertPlainMonthDay(result, "M05", 2, descr), +)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow.js new file mode 100644 index 000000000000..ed2c39ceaffd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Handling for overflow option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainMonthDay(5, 2), + "05-02", +]; +validValues.forEach((value) => { + const constrain = Temporal.PlainMonthDay.from(value, { overflow: "constrain" }); + TemporalHelpers.assertPlainMonthDay(constrain, "M05", 2, "overflow is ignored: constrain"); + + const reject = Temporal.PlainMonthDay.from(value, { overflow: "reject" }); + TemporalHelpers.assertPlainMonthDay(reject, "M05", 2, "overflow is ignored: reject"); +}); + +const propertyBag1 = { year: 2000, month: 13, day: 34 }; +const result1 = Temporal.PlainMonthDay.from(propertyBag1, { overflow: "constrain" }); +TemporalHelpers.assertPlainMonthDay(result1, "M12", 31, "default overflow is constrain"); +assert.throws(RangeError, () => Temporal.PlainMonthDay.from(propertyBag1, { overflow: "reject" }), + "invalid property bag: reject"); + +const propertyBag2 = { month: 1, day: 32 }; +const result2 = Temporal.PlainMonthDay.from(propertyBag2, { overflow: "constrain" }); +TemporalHelpers.assertPlainMonthDay(result2, "M01", 31, "default overflow is constrain"); +assert.throws(RangeError, () => Temporal.PlainMonthDay.from(propertyBag2, { overflow: "reject" }), + "invalid property bag: reject"); + +assert.throws(RangeError, () => Temporal.PlainMonthDay.from("13-34", { overflow: "constrain" }), + "invalid ISO string: constrain"); +assert.throws(RangeError, () => Temporal.PlainMonthDay.from("13-34", { overflow: "reject" }), + "invalid ISO string: reject"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/prop-desc.js new file mode 100644 index 000000000000..a364190e963b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: The "from" property of Temporal.PlainMonthDay +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.from, + "function", + "`typeof PlainMonthDay.from` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/subclassing-ignored.js new file mode 100644 index 000000000000..981346099bf5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/subclassing-ignored.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.PlainMonthDay, + "from", + ["05-02"], + (result) => TemporalHelpers.assertPlainMonthDay(result, "M05", 2), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/year-zero.js new file mode 100644 index 000000000000..5419f8351efb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-08", + "-000000-08-24", + "-000000-08-24T15:43:27", + "-000000-08-24T15:43:27+01:00[UTC]" +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { Temporal.PlainMonthDay.from(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..dd4953e0edc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/infinity-throws-rangeerror.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainMonthDay throws a RangeError if any numerical value is Infinity +esid: sec-temporal.plainmonthday +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const isoCalendar = Temporal.Calendar.from('iso8601'); + +assert.throws(RangeError, () => new Temporal.PlainMonthDay(Infinity, 1)); +assert.throws(RangeError, () => new Temporal.PlainMonthDay(1, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainMonthDay(1, 1, isoCalendar, Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite month", + [O(Infinity, "month"), O(1, "day"), () => "iso8601", O(1, "year")], + ["get month.valueOf", "call month.valueOf"] + ], + [ + "infinite day", + [O(2, "month"), O(Infinity, "day"), () => "iso8601", O(1, "year")], + ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"] + ], + [ + "infinite year", + [O(2, "month"), O(1, "day"), () => "iso8601", O(Infinity, "year")], + ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf", "get year.valueOf", "call year.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainMonthDay(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/length.js new file mode 100644 index 000000000000..cb49635d0dbe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: Temporal.PlainMonthDay.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/missing-arguments.js new file mode 100644 index 000000000000..2cdd40485d88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/missing-arguments.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: RangeError thrown after processing given args when invoked without all required args +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get month.valueOf", + "call month.valueOf", +]; +const actual = []; +const args = [ + TemporalHelpers.toPrimitiveObserver(actual, 1, "month"), +]; + +assert.throws(RangeError, () => new Temporal.PlainMonthDay(...args)); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/name.js new file mode 100644 index 000000000000..8662580f575f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: Temporal.PlainMonthDay.name is "PlainMonthDay" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay, "name", { + value: "PlainMonthDay", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..bcd44f87e9a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/negative-infinity-throws-rangeerror.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainMonthDay throws a RangeError if any numerical value is -Infinity +esid: sec-temporal.plainmonthday +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const isoCalendar = Temporal.Calendar.from('iso8601'); + +assert.throws(RangeError, () => new Temporal.PlainMonthDay(-Infinity, 1)); +assert.throws(RangeError, () => new Temporal.PlainMonthDay(1, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainMonthDay(1, 1, isoCalendar, -Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite month", + [O(-Infinity, "month"), O(1, "day"), () => "iso8601", O(1, "year")], + ["get month.valueOf", "call month.valueOf"] + ], + [ + "infinite day", + [O(2, "month"), O(-Infinity, "day"), () => "iso8601", O(1, "year")], + ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"] + ], + [ + "infinite year", + [O(2, "month"), O(1, "day"), () => "iso8601", O(-Infinity, "year")], + ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf", "get year.valueOf", "call year.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainMonthDay(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prop-desc.js new file mode 100644 index 000000000000..f1e89eea6613 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: The "PlainMonthDay" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay, + "function", + "`typeof PlainMonthDay` is `function`" +); + +verifyProperty(Temporal, "PlainMonthDay", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendar/prop-desc.js new file mode 100644 index 000000000000..a1ec2c6ca226 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendar/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainmonthday.prototype.calendar +description: The "calendar" property of Temporal.PlainMonthDay.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "calendar"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/basic.js new file mode 100644 index 000000000000..ebdae564149a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/basic.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainmonthday.prototype.day +description: Basic tests for day(). +features: [Temporal] +---*/ + +const md = new Temporal.PlainMonthDay(1, 15); +assert.sameValue(md.day, 15); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/calendar-returns-infinity.js new file mode 100644 index 000000000000..a62635309454 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainmonthday.prototype.day +description: Getter throws if the calendar returns ±∞ from its day method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + day() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainMonthDay(5, 2, pos); +assert.throws(RangeError, () => instance1.day); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainMonthDay(5, 2, neg); +assert.throws(RangeError, () => instance2.day); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/prop-desc.js new file mode 100644 index 000000000000..9ccd5c6d5773 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainmonthday.prototype.day +description: The "day" property of Temporal.PlainMonthDay.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "day"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..21395d0117ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: RangeError thrown if a string with UTC designator is used as a PlainMonthDay +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainMonthDay(5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "String with UTC designator should not be valid as a PlainMonthDay" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-wrong-type.js new file mode 100644 index 000000000000..303f66117cfe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-wrong-type.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: Appropriate error thrown when argument cannot be converted to a valid string +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainMonthDay.from({ month: 5, day: 2 }); + +assert.throws(RangeError, () => instance.equals(undefined), "undefined"); +assert.throws(RangeError, () => instance.equals(null), "null"); +assert.throws(RangeError, () => instance.equals(true), "true"); +assert.throws(RangeError, () => instance.equals(""), "empty string"); +assert.throws(TypeError, () => instance.equals(Symbol()), "symbol"); +assert.throws(RangeError, () => instance.equals(1), "1"); +assert.throws(TypeError, () => instance.equals({}), "plain object"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainMonthDay), "Temporal.PlainMonthDay"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/basic.js new file mode 100644 index 000000000000..0e5a82ff63be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/basic.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: Basic tests for equals() +features: [Temporal] +---*/ + +const md1 = Temporal.PlainMonthDay.from("01-22"); +const md2 = Temporal.PlainMonthDay.from("12-15"); +assert(md1.equals(md1), "same object"); +assert.sameValue(md1.equals(md2), false, "different object"); + +assert(md1.equals("01-22"), "same string"); +assert.sameValue(md2.equals("01-22"), false, "different string"); + +assert(md1.equals({ month: 1, day: 22 }), "same property bag"); +assert.sameValue(md2.equals({ month: 1, day: 22 }), false, "different property bag"); + +assert.throws(TypeError, () => md1.equals({ month: 1 }), "missing field in property bag"); + +const mdYear1 = new Temporal.PlainMonthDay(1, 1, undefined, 1972); +const mdYear2 = new Temporal.PlainMonthDay(1, 1, undefined, 2000); +assert.sameValue(mdYear1.equals(mdYear2), false, "different reference years"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin.js new file mode 100644 index 000000000000..55ab76a8a5a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: > + Tests that Temporal.PlainMonthDay.prototype.equals + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.equals), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.equals), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.equals), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.prototype.equals.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-fields-iterable.js new file mode 100644 index 000000000000..0dfd84fff868 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-fields-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainmonthday.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalMonthDay(_other_). + sec-temporal-totemporalmonthday step 2.f: + f. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const date = new Temporal.PlainMonthDay(5, 2, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +date.equals({ monthCode: "M06", day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..9dd90917e0f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainMonthDay(5, 2, calendar); +instance.equals({ monthCode: "M05", day: 3, calendar }); +assert.sameValue(calendar.monthDayFromFieldsCallCount, 1); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to monthDayFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realMonthDayFromFields = Temporal.Calendar.prototype.monthDayFromFields; +let monthDayFromFieldsCallCount = 0; +Temporal.Calendar.prototype.monthDayFromFields = function (fields, options) { + monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return realMonthDayFromFields.call(this, fields, options); +} + +instance.equals("2000-05-03"); +assert.sameValue(monthDayFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.monthDayFromFields = realMonthDayFromFields; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-temporal-object.js new file mode 100644 index 000000000000..18bf4ab7b657 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainmonthday.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalMonthDay(_other_). + sec-temporal-totemporalmonthday step 3.e: + e. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const monthday = new Temporal.PlainMonthDay(5, 2, temporalObject); + monthday.equals({ monthCode: "M06", day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendars.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendars.js new file mode 100644 index 000000000000..f9dab6bad178 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendars.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: Basic tests for equals() calendar handling +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get calendar a.toString", + "call calendar a.toString", + "get calendar b.toString", + "call calendar b.toString", +]; +const actual = []; +const calendar = (id) => { + return TemporalHelpers.toPrimitiveObserver(actual, id, `calendar ${id}`); +}; + +const mdA = new Temporal.PlainMonthDay(2, 7, calendar("a")); +const mdB = new Temporal.PlainMonthDay(2, 7, calendar("b")); +const mdC = new Temporal.PlainMonthDay(2, 7, calendar("c"), 1974); + +assert.sameValue(mdA.equals(mdC), false, "different year"); +assert.compareArray(actual, [], "Should not check calendar"); + +assert.sameValue(mdA.equals(mdB), false, "different calendar"); +assert.compareArray(actual, expected, "Should check calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..4e55198b9023 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainmonthday.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainMonthDay(5, 2); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/length.js new file mode 100644 index 000000000000..ec7544dcd543 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: Temporal.PlainMonthDay.prototype.equals.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.equals, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/name.js new file mode 100644 index 000000000000..af13dbd19f5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: Temporal.PlainMonthDay.prototype.equals.name is "equals". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.equals, "name", { + value: "equals", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/not-a-constructor.js new file mode 100644 index 000000000000..95a9c7edaf7d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: > + Temporal.PlainMonthDay.prototype.equals does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.prototype.equals(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.equals), false, + "isConstructor(Temporal.PlainMonthDay.prototype.equals)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/prop-desc.js new file mode 100644 index 000000000000..be8b0f09e46a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: The "equals" property of Temporal.PlainMonthDay.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.prototype.equals, + "function", + "`typeof PlainMonthDay.prototype.equals` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay.prototype, "equals", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/year-zero.js new file mode 100644 index 000000000000..26e1eb8de7c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.equals +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-08", + "-000000-08-24", + "-000000-08-24T15:43:27", + "-000000-08-24T15:43:27+01:00[UTC]" +]; +const instance = new Temporal.PlainMonthDay(5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/builtin.js new file mode 100644 index 000000000000..bff7b36ec889 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.getisofields +description: > + Tests that Temporal.PlainMonthDay.prototype.getISOFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.getISOFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.getISOFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.getISOFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.prototype.getISOFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-names.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-names.js new file mode 100644 index 000000000000..10befbf63e9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-names.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.getisofields +description: Correct field names on the object returned from getISOFields +features: [Temporal] +---*/ + +const md = new Temporal.PlainMonthDay(5, 2); + +const result = md.getISOFields(); +assert.sameValue(result.isoYear, 1972, "isoYear result"); +assert.sameValue(result.isoMonth, 5, "isoMonth result"); +assert.sameValue(result.isoDay, 2, "isoDay result"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-prop-desc.js new file mode 100644 index 000000000000..5368edce1b06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-prop-desc.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.getisofields +description: Properties on the returned object have the correct descriptor +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoMonth", + "isoYear", +]; + +const md = new Temporal.PlainMonthDay(5, 2); +const result = md.getISOFields(); + +for (const property of expected) { + verifyProperty(result, property, { + writable: true, + enumerable: true, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-traversal-order.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-traversal-order.js new file mode 100644 index 000000000000..8b96d2c07dee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-traversal-order.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.getisofields +description: Properties added in correct order to object returned from getISOFields +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoMonth", + "isoYear", +]; + +const md = new Temporal.PlainMonthDay(5, 2); +const result = md.getISOFields(); + +assert.compareArray(Object.keys(result), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/length.js new file mode 100644 index 000000000000..903ef1efc632 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.getisofields +description: Temporal.PlainMonthDay.prototype.getISOFields.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.getISOFields, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/name.js new file mode 100644 index 000000000000..ce60fb8d129f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.getisofields +description: Temporal.PlainMonthDay.prototype.getISOFields.name is "getISOFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.getISOFields, "name", { + value: "getISOFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/not-a-constructor.js new file mode 100644 index 000000000000..af8903f789fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.getisofields +description: > + Temporal.PlainMonthDay.prototype.getISOFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.prototype.getISOFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.getISOFields), false, + "isConstructor(Temporal.PlainMonthDay.prototype.getISOFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prop-desc.js new file mode 100644 index 000000000000..8efe7565c93d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.getisofields +description: The "getISOFields" property of Temporal.PlainMonthDay.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.prototype.getISOFields, + "function", + "`typeof PlainMonthDay.prototype.getISOFields` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay.prototype, "getISOFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/unsupported.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/unsupported.js new file mode 100644 index 000000000000..2f5caf148875 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/unsupported.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainmonthday.prototype.monthcode +description: There is no 'month' property on Temporal.PlainMonthDay +features: [Temporal] +---*/ + +const md = new Temporal.PlainMonthDay(1, 15); +assert.sameValue(md.month, undefined); +assert.sameValue("month" in md, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/basic.js new file mode 100644 index 000000000000..992e1da428aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/basic.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainmonthday.prototype.monthcode +description: Basic tests for monthCode(). +features: [Temporal] +---*/ + +const md = new Temporal.PlainMonthDay(1, 15); +assert.sameValue(md.monthCode, "M01"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/prop-desc.js new file mode 100644 index 000000000000..d9886d599af5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainmonthday.prototype.monthcode +description: The "monthCode" property of Temporal.PlainMonthDay.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "monthCode"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/prop-desc.js new file mode 100644 index 000000000000..cbb96ec02d33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-plainmonthday-prototype +description: The "prototype" property of Temporal.PlainMonthDay +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.PlainMonthDay.prototype, "object"); +assert.notSameValue(Temporal.PlainMonthDay.prototype, null); + +verifyProperty(Temporal.PlainMonthDay, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..9682facdb0ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tojson +description: > + Tests that Temporal.PlainMonthDay.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/calendarname.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/calendarname.js new file mode 100644 index 000000000000..de6f2df79275 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/calendarname.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.protoype.tojson +description: toJSON doesn't take calendarName into account. +features: [Temporal] +---*/ + +const tests = [ + [[], "05-02"], + [[{ toString() { return "custom"; } }], "1972-05-02[u-ca=custom]"], + [[{ toString() { return "iso8601"; } }], "05-02"], + [[{ toString() { return "ISO8601"; } }], "1972-05-02[u-ca=ISO8601]"], + [[{ toString() { return "\u0131so8601"; } }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i +]; +const options = { + get calendarName() { + TemporalHelpers.assertUnreachable("calendarName should not be accessed"); + return ""; + } +}; + +for (const [args, expected] of tests) { + const monthday = new Temporal.PlainMonthDay(5, 2, ...args); + const result = monthday.toJSON(options); + assert.sameValue(result, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/length.js new file mode 100644 index 000000000000..c4a5342fb832 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tojson +description: Temporal.PlainMonthDay.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/name.js new file mode 100644 index 000000000000..5a262f607f56 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tojson +description: Temporal.PlainMonthDay.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..b9f24d320c2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tojson +description: > + Temporal.PlainMonthDay.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.toJSON), false, + "isConstructor(Temporal.PlainMonthDay.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..a87d0aec4e84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tojson +description: The "toJSON" property of Temporal.PlainMonthDay.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.prototype.toJSON, + "function", + "`typeof PlainMonthDay.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js new file mode 100644 index 000000000000..83b34b566805 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js @@ -0,0 +1,58 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +// For PlainMonthDay, the ISO reference year is only present in the string if +// the calendar is not ISO 8601 +class NotISO extends Temporal.Calendar { + constructor() { super("iso8601"); } + toString() { return "not-iso"; } +} +const calendar = new NotISO(); + +let instance = new Temporal.PlainMonthDay(12, 3, calendar, -100000); +assert.sameValue(instance.toJSON(), "-100000-12-03[u-ca=not-iso]", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(4, 5, calendar, -10000); +assert.sameValue(instance.toJSON(), "-010000-04-05[u-ca=not-iso]", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(6, 7, calendar, -9999); +assert.sameValue(instance.toJSON(), "-009999-06-07[u-ca=not-iso]", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 9, calendar, -1000); +assert.sameValue(instance.toJSON(), "-001000-08-09[u-ca=not-iso]", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(10, 9, calendar, -999); +assert.sameValue(instance.toJSON(), "-000999-10-09[u-ca=not-iso]", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 7, calendar, -1); +assert.sameValue(instance.toJSON(), "-000001-08-07[u-ca=not-iso]", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(6, 5, calendar, 0); +assert.sameValue(instance.toJSON(), "0000-06-05[u-ca=not-iso]", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(4, 3, calendar, 1); +assert.sameValue(instance.toJSON(), "0001-04-03[u-ca=not-iso]", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(2, 10, calendar, 999); +assert.sameValue(instance.toJSON(), "0999-02-10[u-ca=not-iso]", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(1, 23, calendar, 1000); +assert.sameValue(instance.toJSON(), "1000-01-23[u-ca=not-iso]", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(4, 5, calendar, 9999); +assert.sameValue(instance.toJSON(), "9999-04-05[u-ca=not-iso]", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(6, 7, calendar, 10000); +assert.sameValue(instance.toJSON(), "+010000-06-07[u-ca=not-iso]", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 9, calendar, 100000); +assert.sameValue(instance.toJSON(), "+100000-08-09[u-ca=not-iso]", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin.js new file mode 100644 index 000000000000..065a2edb6d8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: > + Tests that Temporal.PlainMonthDay.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/length.js new file mode 100644 index 000000000000..57b1b9a17329 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: Temporal.PlainMonthDay.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/name.js new file mode 100644 index 000000000000..6eb256811a9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: Temporal.PlainMonthDay.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 000000000000..51875a532a68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: > + Temporal.PlainMonthDay.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.toLocaleString), false, + "isConstructor(Temporal.PlainMonthDay.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/prop-desc.js new file mode 100644 index 000000000000..0ea4b0da1552 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.PlainMonthDay.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.prototype.toLocaleString, + "function", + "`typeof PlainMonthDay.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/argument-not-object.js new file mode 100644 index 000000000000..1bf8aeb1b53b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/argument-not-object.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: Throws a TypeError if the argument is not an Object, before any other observable actions +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[null, undefined, true, 3.1416, "a string", Symbol("symbol"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarThrowEverything(); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + assert.throws(TypeError, () => plainMonthDay.toPlainDate(primitive)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/basic.js new file mode 100644 index 000000000000..c5fb593dff9c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/basic.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: Basic tests for toPlainDate(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const md = Temporal.PlainMonthDay.from("01-22"); +const d = md.toPlainDate({ year: 2002 }); +TemporalHelpers.assertPlainDate(d, 2002, 1, "M01", 22); + +assert.throws(TypeError, () => md.toPlainDate({ something: 'nothing' }), "missing fields"); + +const leapDay = Temporal.PlainMonthDay.from('02-29'); +assert.throws(RangeError, () => leapDay.toPlainDate({ year: 2019 })); +TemporalHelpers.assertPlainDate(leapDay.toPlainDate({ year: 2020 }), 2020, 2, "M02", 29); + +const options = { + get overflow() { + TemporalHelpers.assertUnreachable("Should not get overflow option"); + return ""; + } +}; +TemporalHelpers.assertPlainDate(leapDay.toPlainDate({ year: 2020 }, options), 2020, 2, "M02", 29); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin.js new file mode 100644 index 000000000000..442d2216f3bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: > + Tests that Temporal.PlainMonthDay.prototype.toPlainDate + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.toPlainDate), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.toPlainDate), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.toPlainDate), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.prototype.toPlainDate.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fields-iterable.js new file mode 100644 index 000000000000..b5df24348160 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainmonthday.prototype.toplaindate step 4: + 4. Let _receiverFieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"monthCode"* »). + sec-temporal.plainmonthday.prototype.toplaindate step 7: + 7. Let _inputFieldNames_ be ? CalendarFields(_calendar_, « *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "day", + "monthCode", +]; +const expected2 = [ + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const monthday = new Temporal.PlainMonthDay(5, 2, calendar); +monthday.toPlainDate({ year: 1997 }); + +assert.sameValue(calendar.fieldsCallCount, 2, "fields() method called twice"); +assert.compareArray(calendar.fieldsCalledWith[0], expected1, "fields() method called first time with correct args"); +assert.compareArray(calendar.fieldsCalledWith[1], expected2, "fields() method called second time with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole first iterable"); +assert(calendar.iteratorExhausted[1], "iterated through the whole second iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js new file mode 100644 index 000000000000..81a521f214ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: > + with() should throw a TypeError if mergeFields() returns a primitive, + without passing the value on to any other calendar methods +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive); + const instance = new Temporal.PlainMonthDay(5, 2, calendar); + assert.throws(TypeError, () => instance.toPlainDate({ year: 2005 }), "bad return from mergeFields() throws"); + assert.sameValue(calendar.dateFromFieldsCallCount, 0, "dateFromFields() never called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/copies-merge-fields-object.js new file mode 100644 index 000000000000..996df0e3f1c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/copies-merge-fields-object.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: The object returned from mergeFields() is copied before being passed to monthDayFromFields(). +info: | + sec-temporal.plainmonthday.prototype.toplaindate steps 9 and 11: + 9. Let _mergedFields_ be ? CalendarMergeFields(_calendar_, _fields_, _inputFields_). + 11. Set _mergedFields_ to ? PrepareTemporalFields(_mergedFields_, _mergedFieldNames_, «»). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get day", + "get day.valueOf", + "call day.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; + +const calendar = TemporalHelpers.calendarMergeFieldsGetters(); +const monthday = new Temporal.PlainMonthDay(3, 31, calendar); +monthday.toPlainDate({ year: 2000 }); + +assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..29bef34d5318 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws a RangeError if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainmonthday.prototype.toplaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainMonthDay(5, 2); + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.toPlainDate({ year: inf }), `year property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "year"); + assert.throws(RangeError, () => instance.toPlainDate({ year: obj })); + assert.compareArray(calls, ["get year.valueOf", "call year.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/length.js new file mode 100644 index 000000000000..24d7bc4cc706 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: Temporal.PlainMonthDay.prototype.toPlainDate.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.toPlainDate, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/limits.js new file mode 100644 index 000000000000..af6f4410bf01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/limits.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: Throws a RangeError if the resulting PlainDate is out of range +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const jan1 = Temporal.PlainMonthDay.from("01-01"); +const dec31 = Temporal.PlainMonthDay.from("12-31"); + +const minYear = -271821; +assert.throws(RangeError, () => jan1.toPlainDate({ year: minYear }), "jan1 min"); +const apr18 = Temporal.PlainMonthDay.from("04-18"); +assert.throws(RangeError, () => apr18.toPlainDate({ year: minYear }), "apr18 min"); +TemporalHelpers.assertPlainDate(Temporal.PlainMonthDay.from("04-19").toPlainDate({ year: minYear }), + minYear, 4, "M04", 19, "apr19 min"); +TemporalHelpers.assertPlainDate(jan1.toPlainDate({ year: minYear + 1 }), + minYear + 1, 1, "M01", 1, "jan1 min"); + +const maxYear = 275760; +assert.throws(RangeError, () => dec31.toPlainDate({ year: maxYear }), "dec31 max"); +const sep14 = Temporal.PlainMonthDay.from("09-14"); +assert.throws(RangeError, () => sep14.toPlainDate({ year: maxYear }), "sep14 max"); +TemporalHelpers.assertPlainDate(Temporal.PlainMonthDay.from("09-13").toPlainDate({ year: maxYear }), + maxYear, 9, "M09", 13, "max"); +TemporalHelpers.assertPlainDate(dec31.toPlainDate({ year: maxYear - 1 }), + maxYear - 1, 12, "M12", 31, "dec31 max"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/name.js new file mode 100644 index 000000000000..242a293816b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: Temporal.PlainMonthDay.prototype.toPlainDate.name is "toPlainDate". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.toPlainDate, "name", { + value: "toPlainDate", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/not-a-constructor.js new file mode 100644 index 000000000000..7c5ddecda3f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: > + Temporal.PlainMonthDay.prototype.toPlainDate does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.prototype.toPlainDate(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.toPlainDate), false, + "isConstructor(Temporal.PlainMonthDay.prototype.toPlainDate)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/prop-desc.js new file mode 100644 index 000000000000..f507516a10ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.toplaindate +description: The "toPlainDate" property of Temporal.PlainMonthDay.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.prototype.toPlainDate, + "function", + "`typeof PlainMonthDay.prototype.toPlainDate` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay.prototype, "toPlainDate", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin.js new file mode 100644 index 000000000000..f9f8435a3190 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tostring +description: > + Tests that Temporal.PlainMonthDay.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js new file mode 100644 index 000000000000..93809e4f6cde --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.protoype.tostring +description: If calendarName is "always", the calendar ID should be included. +features: [Temporal] +---*/ + +const tests = [ + [[], "1972-05-02[u-ca=iso8601]"], + [[{ toString() { return "custom"; } }], "1972-05-02[u-ca=custom]"], + [[{ toString() { return "iso8601"; } }], "1972-05-02[u-ca=iso8601]"], + [[{ toString() { return "ISO8601"; } }], "1972-05-02[u-ca=ISO8601]"], + [[{ toString() { return "\u0131so8601"; } }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i +]; + +for (const [args, expected] of tests) { + const monthday = new Temporal.PlainMonthDay(5, 2, ...args); + const result = monthday.toString({ calendarName: "always" }); + assert.sameValue(result, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-auto.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-auto.js new file mode 100644 index 000000000000..937a59c7c074 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-auto.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.protoype.tostring +description: If calendarName is "auto", "iso8601" should be omitted. +features: [Temporal] +---*/ + +const tests = [ + [[], "05-02"], + [[{ toString() { return "custom"; } }], "1972-05-02[u-ca=custom]"], + [[{ toString() { return "iso8601"; } }], "05-02"], + [[{ toString() { return "ISO8601"; } }], "1972-05-02[u-ca=ISO8601]"], + [[{ toString() { return "\u0131so8601"; } }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i +]; + +for (const [args, expected] of tests) { + const monthday = new Temporal.PlainMonthDay(5, 2, ...args); + const result = monthday.toString({ calendarName: "auto" }); + assert.sameValue(result, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-invalid-string.js new file mode 100644 index 000000000000..355cd99ae4d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-invalid-string.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.protoype.tostring +description: RangeError thrown when calendarName option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plainmonthday.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const monthday = new Temporal.PlainMonthDay(5, 2); +for (const calendarName of ["ALWAYS", "sometimes", "other string"]) { + assert.throws(RangeError, () => monthday.toString({ calendarName })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-never.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-never.js new file mode 100644 index 000000000000..0f860f891896 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-never.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.protoype.tostring +description: If calendarName is "never", the calendar ID should be omitted. +features: [Temporal] +---*/ + +const tests = [ + [[], "05-02"], + [[{ toString() { return "custom"; } }], "1972-05-02"], + [[{ toString() { return "iso8601"; } }], "05-02"], + [[{ toString() { return "ISO8601"; } }], "1972-05-02"], + [[{ toString() { return "\u0131so8601"; } }], "1972-05-02"], // dotless i +]; + +for (const [args, expected] of tests) { + const monthday = new Temporal.PlainMonthDay(5, 2, ...args); + const result = monthday.toString({ calendarName: "never" }); + assert.sameValue(result, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-undefined.js new file mode 100644 index 000000000000..02841aa053fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-undefined.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.protoype.tostring +description: Fallback value for calendarName option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plainmonthday.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const tests = [ + [[], "05-02"], + [[{ toString() { return "custom"; } }], "1972-05-02[u-ca=custom]"], + [[{ toString() { return "iso8601"; } }], "05-02"], + [[{ toString() { return "ISO8601"; } }], "1972-05-02[u-ca=ISO8601]"], + [[{ toString() { return "\u0131so8601"; } }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i +]; + +for (const [args, expected] of tests) { + const monthday = new Temporal.PlainMonthDay(5, 2, ...args); + const explicit = monthday.toString({ calendarName: undefined }); + assert.sameValue(explicit, expected, "default calendarName option is auto"); + + const implicit = monthday.toString({}); + assert.sameValue(implicit, expected, "default calendarName option is auto"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-wrong-type.js new file mode 100644 index 000000000000..c72556f21727 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.protoype.tostring +description: Type conversions for calendarName option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plainmonthday.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const monthday = new Temporal.PlainMonthDay(5, 2, calendar); + +TemporalHelpers.checkStringOptionWrongType("calendarName", "auto", + (calendarName) => monthday.toString({ calendarName }), + (result, descr) => assert.sameValue(result, "1972-05-02[u-ca=custom]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/length.js new file mode 100644 index 000000000000..098a61b1d80b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tostring +description: Temporal.PlainMonthDay.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/name.js new file mode 100644 index 000000000000..5fe7c6c49e52 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tostring +description: Temporal.PlainMonthDay.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..2676ca48bafd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tostring +description: > + Temporal.PlainMonthDay.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.toString), false, + "isConstructor(Temporal.PlainMonthDay.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-undefined.js new file mode 100644 index 000000000000..489f39249b1f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tostring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const tests = [ + [[], "05-02"], + [[{ toString() { return "custom"; } }], "1972-05-02[u-ca=custom]"], + [[{ toString() { return "iso8601"; } }], "05-02"], + [[{ toString() { return "ISO8601"; } }], "1972-05-02[u-ca=ISO8601]"], + [[{ toString() { return "\u0131so8601"; } }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i +]; + +for (const [args, expected] of tests) { + const monthday = new Temporal.PlainMonthDay(5, 2, ...args); + const explicit = monthday.toString(undefined); + assert.sameValue(explicit, expected, "default calendarName option is auto"); + + const implicit = monthday.toString(); + assert.sameValue(implicit, expected, "default calendarName option is auto"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..3aa5843d64db --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tostring +description: The "toString" property of Temporal.PlainMonthDay.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.prototype.toString, + "function", + "`typeof PlainMonthDay.prototype.toString` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js new file mode 100644 index 000000000000..4aec1db7c823 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js @@ -0,0 +1,58 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +// For PlainMonthDay, the ISO reference year is only present in the string if +// the calendar is not ISO 8601 +class NotISO extends Temporal.Calendar { + constructor() { super("iso8601"); } + toString() { return "not-iso"; } +} +const calendar = new NotISO(); + +let instance = new Temporal.PlainMonthDay(12, 3, calendar, -100000); +assert.sameValue(instance.toString(), "-100000-12-03[u-ca=not-iso]", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(4, 5, calendar, -10000); +assert.sameValue(instance.toString(), "-010000-04-05[u-ca=not-iso]", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(6, 7, calendar, -9999); +assert.sameValue(instance.toString(), "-009999-06-07[u-ca=not-iso]", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 9, calendar, -1000); +assert.sameValue(instance.toString(), "-001000-08-09[u-ca=not-iso]", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(10, 9, calendar, -999); +assert.sameValue(instance.toString(), "-000999-10-09[u-ca=not-iso]", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 7, calendar, -1); +assert.sameValue(instance.toString(), "-000001-08-07[u-ca=not-iso]", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(6, 5, calendar, 0); +assert.sameValue(instance.toString(), "0000-06-05[u-ca=not-iso]", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(4, 3, calendar, 1); +assert.sameValue(instance.toString(), "0001-04-03[u-ca=not-iso]", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(2, 10, calendar, 999); +assert.sameValue(instance.toString(), "0999-02-10[u-ca=not-iso]", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(1, 23, calendar, 1000); +assert.sameValue(instance.toString(), "1000-01-23[u-ca=not-iso]", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(4, 5, calendar, 9999); +assert.sameValue(instance.toString(), "9999-04-05[u-ca=not-iso]", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(6, 7, calendar, 10000); +assert.sameValue(instance.toString(), "+010000-06-07[u-ca=not-iso]", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 9, calendar, 100000); +assert.sameValue(instance.toString(), "+100000-08-09[u-ca=not-iso]", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/basic.js new file mode 100644 index 000000000000..2064c843dbad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/basic.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.valueof +description: Basic tests for valueOf(). +features: [Temporal] +---*/ + +const plainMonthDay = Temporal.PlainMonthDay.from("1963-02-13"); +const plainMonthDay2 = Temporal.PlainMonthDay.from("1963-02-13"); + +assert.throws(TypeError, () => plainMonthDay.valueOf(), "valueOf"); +assert.throws(TypeError, () => plainMonthDay < plainMonthDay, "<"); +assert.throws(TypeError, () => plainMonthDay <= plainMonthDay, "<="); +assert.throws(TypeError, () => plainMonthDay > plainMonthDay, ">"); +assert.throws(TypeError, () => plainMonthDay >= plainMonthDay, ">="); +assert.sameValue(plainMonthDay === plainMonthDay, true, "==="); +assert.sameValue(plainMonthDay === plainMonthDay2, false, "==="); +assert.sameValue(plainMonthDay !== plainMonthDay, false, "!=="); +assert.sameValue(plainMonthDay !== plainMonthDay2, true, "!=="); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/builtin.js new file mode 100644 index 000000000000..54fb5afc58e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.valueof +description: > + Tests that Temporal.PlainMonthDay.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/length.js new file mode 100644 index 000000000000..ae2fc8ad3349 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.valueof +description: Temporal.PlainMonthDay.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/name.js new file mode 100644 index 000000000000..43c00dd9cc95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.valueof +description: Temporal.PlainMonthDay.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/not-a-constructor.js new file mode 100644 index 000000000000..806c92111754 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.valueof +description: > + Temporal.PlainMonthDay.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.valueOf), false, + "isConstructor(Temporal.PlainMonthDay.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/prop-desc.js new file mode 100644 index 000000000000..913be0409e88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.valueof +description: The "valueOf" property of Temporal.PlainMonthDay.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.prototype.valueOf, + "function", + "`typeof PlainMonthDay.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/basic.js new file mode 100644 index 000000000000..89330e6f0dce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/basic.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Basic tests for with(). +includes: [compareArray.js, temporalHelpers.js] +features: [Symbol, Temporal] +---*/ + +const md = Temporal.PlainMonthDay.from("01-15"); + +TemporalHelpers.assertPlainMonthDay(md.with({ day: 22 }), + "M01", 22, "with({day})"); + +TemporalHelpers.assertPlainMonthDay(md.with({ monthCode: "M12" }), + "M12", 15, "with({monthCode})"); + +assert.throws(TypeError, () => md.with({ month: 12 }), "with({month})"); + +TemporalHelpers.assertPlainMonthDay(md.with({ month: 12, monthCode: "M12" }), + "M12", 15, "with({month, monthCode}) agree"); + +assert.throws(RangeError, () => md.with({ month: 12, monthCode: "M11" }), "with({month, monthCode}) disagree"); + +TemporalHelpers.assertPlainMonthDay(md.with({ year: 2000, month: 12 }), + "M12", 15, "with({year, month})"); + +TemporalHelpers.assertPlainMonthDay(md.with({ year: 2000 }), + "M01", 15, "with({year})"); + +assert.throws(TypeError, () => md.with({ day: 1, calendar: "iso8601" }), "with({calendar})"); + +assert.throws(TypeError, () => md.with({ day: 1, timeZone: "UTC" }), "with({timeZone})"); + +assert.throws(TypeError, () => md.with({}), "with({})"); +assert.throws(TypeError, () => md.with({ months: 12 }), "with({months})"); + +TemporalHelpers.assertPlainMonthDay(md.with({ monthCode: "M12", days: 1 }), + "M12", 15, "with({monthCode, days})"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin.js new file mode 100644 index 000000000000..71b5d3f842a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: > + Tests that Temporal.PlainMonthDay.prototype.with + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.with), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.with), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.with), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainMonthDay.prototype.with.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-arguments.js new file mode 100644 index 000000000000..b43434ba6c05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-arguments.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Correct options value is passed to calendar method +info: | + MonthDayFromFields ( calendar, fields [ , options ] ) + + 5. Let monthDay be ? Invoke(calendar, "monthDayFromFields", « fields, options »). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const options = {}; +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + monthDayFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.sameValue(args[1], options, "args[1]"); + return super.monthDayFromFields(...args); + } +} +const plainMonthDay = new Temporal.PlainMonthDay(7, 2, new CustomCalendar()); +const result = plainMonthDay.with({ monthCode: "M05" }, options); +TemporalHelpers.assertPlainMonthDay(result, "M05", 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fields-iterable.js new file mode 100644 index 000000000000..aeaea42189d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fields-iterable.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainmonthday.prototype.with step 9: + 9. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const monthday = new Temporal.PlainMonthDay(5, 2, calendar); +monthday.with({ day: 6 }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-merge-fields-returns-primitive.js new file mode 100644 index 000000000000..f2f91c8f44aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-merge-fields-returns-primitive.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: > + with() should throw a TypeError if mergeFields() returns a primitive, + without passing the value on to any other calendar methods +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive); + const instance = new Temporal.PlainMonthDay(5, 2, calendar); + assert.throws(TypeError, () => instance.with({ year: 2005 }), "bad return from mergeFields() throws"); + assert.sameValue(calendar.monthDayFromFieldsCallCount, 0, "monthDayFromFields() never called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copies-merge-fields-object.js new file mode 100644 index 000000000000..56382db5964d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copies-merge-fields-object.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: The object returned from mergeFields() is copied before being passed to monthDayFromFields(). +info: | + sec-temporal.plainmonthday.prototype.with steps 13–15: + 13. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialMonthDay_). + 14. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»). + 15. Return ? MonthDayFromFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get day", + "get day.valueOf", + "call day.valueOf", + "get month", // PlainMonthDay.month property does not exist, no valueOf + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", // undefined, no valueOf +]; + +const calendar = TemporalHelpers.calendarMergeFieldsGetters(); +const monthday = new Temporal.PlainMonthDay(3, 31, calendar); +monthday.with({ day: 1 }); + +assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copy-properties-not-undefined.js new file mode 100644 index 000000000000..849f94fad716 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copy-properties-not-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: PreparePartialTemporalFields copies only defined properties of source object +info: | + 4. For each value _property_ of _fieldNames_, do + a. Let _value_ be ? Get(_fields_, _property_). + b. If _value_ is not *undefined*, then + ... + iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainMonthDay = new Temporal.PlainMonthDay(10, 31); + +TemporalHelpers.assertPlainMonthDay(plainMonthDay.with({ day: 1, monthCode: undefined }), + "M10", 1, + "only the properties that are present and defined in the plain object are copied" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..6334cdb0a393 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/infinity-throws-rangeerror.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainmonthday.prototype.with +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainMonthDay(5, 2); + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.with({ day: inf }, { overflow }), `day property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "day"); + assert.throws(RangeError, () => instance.with({ day: obj }, { overflow })); + assert.compareArray(calls, ["get day.valueOf", "call day.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/length.js new file mode 100644 index 000000000000..dc250d6ced50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Temporal.PlainMonthDay.prototype.with.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.with, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/name.js new file mode 100644 index 000000000000..89b50b63f69e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Temporal.PlainMonthDay.prototype.with.name is "with". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainMonthDay.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/not-a-constructor.js new file mode 100644 index 000000000000..055b291e9cc6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: > + Temporal.PlainMonthDay.prototype.with does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainMonthDay.prototype.with(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.with), false, + "isConstructor(Temporal.PlainMonthDay.prototype.with)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-invalid.js new file mode 100644 index 000000000000..b2d83d28ef2c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainMonthDay(2, 2); +[null, true, "hello", Symbol("foo"), 1, 1n].forEach((badOptions) => + assert.throws(TypeError, () => instance.with({ day: 17 }, badOptions)) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-undefined.js new file mode 100644 index 000000000000..d92609ca76b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const monthday = new Temporal.PlainMonthDay(2, 2); +const fields = { day: 100 }; + +const explicit = monthday.with(fields, undefined); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = monthday.with(fields); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/order-of-operations.js new file mode 100644 index 000000000000..b4daf4e74098 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/order-of-operations.js @@ -0,0 +1,54 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Properties on an object passed to with() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainMonthDay(5, 2); +const expected = [ + "get calendar", + "get timeZone", + "get day", + "get day.valueOf", + "call day.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; +const actual = []; +const fields = { + year: 1.7, + month: 1.7, + monthCode: "M01", + day: 1.7, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.with(argument); +TemporalHelpers.assertPlainMonthDay(result, "M01", 1); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js new file mode 100644 index 000000000000..56c9561b180e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainmonthday.prototype.with step 16: + 16. Return ? MonthDayFromFields(_calendar_, _fields_, _options_). +features: [Temporal] +---*/ + +const monthday = new Temporal.PlainMonthDay(5, 2); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => monthday.with({ day: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-undefined.js new file mode 100644 index 000000000000..852aace42840 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainmonthday.prototype.with step 16: + 16. Return ? MonthDayFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const monthday = new Temporal.PlainMonthDay(5, 2); +const explicit = monthday.with({ day: 33 }, { overflow: undefined }); +TemporalHelpers.assertPlainMonthDay(explicit, "M05", 31, "default overflow is constrain"); +const implicit = monthday.with({ day: 33 }, {}); +TemporalHelpers.assertPlainMonthDay(implicit, "M05", 31, "default overflow is constrain"); +const lambda = monthday.with({ day: 33 }, () => {}); +TemporalHelpers.assertPlainMonthDay(lambda, "M05", 31, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-wrong-type.js new file mode 100644 index 000000000000..def4a8d629c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainmonthday.prototype.with step 16: + 16. Return ? MonthDayFromFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const monthday = new Temporal.PlainMonthDay(5, 2); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => monthday.with({ day: 8 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainMonthDay(result, "M05", 8, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/prop-desc.js new file mode 100644 index 000000000000..e1c06253cae9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: The "with" property of Temporal.PlainMonthDay.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainMonthDay.prototype.with, + "function", + "`typeof PlainMonthDay.prototype.with` is `function`" +); + +verifyProperty(Temporal.PlainMonthDay.prototype, "with", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/subclassing-ignored.js new file mode 100644 index 000000000000..43c84a63c330 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.with +description: Objects of a subclass are never created as return values for with() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainMonthDay, + [5, 2], + "with", + [{ day: 20 }], + (result) => TemporalHelpers.assertPlainMonthDay(result, "M05", 20), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-undefined.js new file mode 100644 index 000000000000..c1067f696120 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: referenceISOYear argument defaults to 1972 if not given +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const args = [5, 2, calendar]; + +const dateExplicit = new Temporal.PlainMonthDay(...args, undefined); +assert.sameValue(dateExplicit.getISOFields().isoYear, 1972, "default referenceISOYear is 1972"); + +const dateImplicit = new Temporal.PlainMonthDay(...args); +assert.sameValue(dateImplicit.getISOFields().isoYear, 1972, "default referenceISOYear is 1972"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/shell.js index e69de29bb2d1..1d70b7579ee9 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/basic.js new file mode 100644 index 000000000000..60f29323c642 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/basic.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Basic tests for the PlainTime constructor. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [15, 23, 30, 123, 456, 789]; +const plainTime = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(plainTime, ...args); +assert.sameValue(plainTime.calendar.id, "iso8601", "calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/builtin.js new file mode 100644 index 000000000000..067ea7ae43b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Tests that Temporal.PlainTime meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.PlainTime.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-cast.js new file mode 100644 index 000000000000..afc44727014a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-cast.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: compare() casts its arguments +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("08:44:15.321"); +const t2 = Temporal.PlainTime.from("14:23:30.123"); + +assert.sameValue(Temporal.PlainTime.compare({ hour: 16, minute: 34 }, t2), 1, "one object"); +assert.sameValue(Temporal.PlainTime.compare("16:34", t2), 1, "one string"); +assert.throws(TypeError, () => Temporal.PlainTime.compare({ hours: 16 }, t2), "one missing property"); + +assert.sameValue(Temporal.PlainTime.compare(t1, { hour: 16, minute: 34 }), -1, "two object"); +assert.sameValue(Temporal.PlainTime.compare(t1, "16:34"), -1, "two string"); +assert.throws(TypeError, () => Temporal.PlainTime.compare(t1, { hours: 16 }), "two missing property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..a84fabc012e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-no-implicit-midnight.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const midnight = new Temporal.PlainTime(); +assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, midnight), + "Date-only string throws, does not implicitly convert to midnight (first argument)" +); +assert.throws( + RangeError, + () => Temporal.PlainTime.compare(midnight, arg), + "Date-only string throws, does not implicitly convert to midnight (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..678537134879 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,70 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const midnight = new Temporal.PlainTime(); + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, midnight), + `${string} is ambiguous and requires T prefix (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(midnight, arg), + `${string} is ambiguous and requires T prefix (second argument)` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + Temporal.PlainTime.compare(arg, midnight); + Temporal.PlainTime.compare(midnight, arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, midnight), + 'space is not accepted as a substitute for T prefix (first argument)' + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(midnight, arg), + 'space is not accepted as a substitute for T prefix (second argument)' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => { + Temporal.PlainTime.compare(arg, midnight); + Temporal.PlainTime.compare(midnight, arg); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-time-designator.js new file mode 100644 index 000000000000..78bc8e8a3175 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-time-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +features: [Temporal, arrow-function] +---*/ + +const halfPast = new Temporal.PlainTime(0, 30); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + assert.sameValue(Temporal.PlainTime.compare(arg, halfPast), 0, `T prefix is accepted: ${arg} (first argument)`); + assert.sameValue(Temporal.PlainTime.compare(halfPast, arg), 0, `T prefix is accepted: ${arg} (second argument)`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..ef9b3cae377c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-utc-designator.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const plainTime = new Temporal.PlainTime(); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, plainTime), + "String with UTC designator should not be valid as a PlainTime (first argument)" + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(plainTime, arg), + "String with UTC designator should not be valid as a PlainTime (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..5ef86caf224f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); +const time = new Temporal.PlainTime(16, 50, 35, 0, 0, 1); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result1 = Temporal.PlainTime.compare(time, datetime); +assert.sameValue(result1, 0); + +const result2 = Temporal.PlainTime.compare(datetime, time); +assert.sameValue(result2, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..b5f95f205f22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, Infinity, -Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + + assert.throws(RangeError, () => Temporal.PlainTime.compare(datetime, time)); + assert.throws(RangeError, () => Temporal.PlainTime.compare(time, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..f183a46feabb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.PlainTime.compare(datetime, time), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); + assert.throws( + TypeError, + () => Temporal.PlainTime.compare(time, datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..da01ee93a653 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + + assert.throws(RangeError, () => Temporal.PlainTime.compare(datetime, time)); + assert.throws(RangeError, () => Temporal.PlainTime.compare(time, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..366f7025d91e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + + assert.throws(TypeError, () => Temporal.PlainTime.compare(datetime, time)); + assert.throws(TypeError, () => Temporal.PlainTime.compare(time, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/basic.js new file mode 100644 index 000000000000..054f7aa4cdbe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/basic.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Basic tests for compare() +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("08:44:15.321"); +const t1bis = Temporal.PlainTime.from("08:44:15.321"); +const t2 = Temporal.PlainTime.from("14:23:30.123"); + +assert.sameValue(Temporal.PlainTime.compare(t1, t1), 0, "same object"); +assert.sameValue(Temporal.PlainTime.compare(t1, t1bis), 0, "different object"); +assert.sameValue(Temporal.PlainTime.compare(t1, t2), -1, "before"); +assert.sameValue(Temporal.PlainTime.compare(t2, t1), 1, "after"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/builtin.js new file mode 100644 index 000000000000..9df7635369c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Tests that Temporal.PlainTime.compare meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.compare), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.compare), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.compare), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.compare.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/calendar-temporal-object.js new file mode 100644 index 000000000000..97cb9eae3d8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalTime(_one_). + 2. Set _two_ to ? ToTemporalTime(_two_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => Temporal.PlainTime.compare({ hour: 12, minute: 30, calendar: temporalObject }, time)); + assert.throws(RangeError, () => Temporal.PlainTime.compare(time, { hour: 12, minute: 30, calendar: temporalObject })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/length.js new file mode 100644 index 000000000000..a49280dcaff9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Temporal.PlainTime.compare.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.compare, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/name.js new file mode 100644 index 000000000000..9ca4422b8d28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Temporal.PlainTime.compare.name is "compare" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.compare, "name", { + value: "compare", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/not-a-constructor.js new file mode 100644 index 000000000000..bdd9aaf58390 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Temporal.PlainTime.compare does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.compare(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.compare), false, + "isConstructor(Temporal.PlainTime.compare)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/plaintime-propertybag-no-time-units.js new file mode 100644 index 000000000000..206d860ebf15 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/plaintime-propertybag-no-time-units.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Missing time units in property bag default to 0 +features: [Temporal] +---*/ + +const props = {}; +assert.throws(TypeError, () => Temporal.PlainTime.compare(props, new Temporal.PlainTime(0, 30)), "TypeError if at least one property is not present"); + +props.minute = 30; +const result = Temporal.PlainTime.compare(props, new Temporal.PlainTime(0, 30)); +assert.sameValue(result, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/prop-desc.js new file mode 100644 index 000000000000..51c83d239bbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: The "compare" property of Temporal.PlainTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.compare, + "function", + "`typeof PlainTime.compare` is `function`" +); + +verifyProperty(Temporal.PlainTime, "compare", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/use-internal-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/use-internal-slots.js new file mode 100644 index 000000000000..c430217b1c60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/use-internal-slots.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-comparetemporaltime +description: compare() ignores the observable properties and uses internal slots +features: [Temporal] +---*/ + +function CustomError() {} + +class AvoidGettersTime extends Temporal.PlainTime { + get hour() { + throw new CustomError(); + } + get minute() { + throw new CustomError(); + } + get second() { + throw new CustomError(); + } + get millisecond() { + throw new CustomError(); + } + get microsecond() { + throw new CustomError(); + } + get nanosecond() { + throw new CustomError(); + } +} + +const one = new AvoidGettersTime(12, 34, 56, 987, 654, 321); +const two = new AvoidGettersTime(6, 54, 32, 123, 456, 789); +assert.sameValue(Temporal.PlainTime.compare(one, two), 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/year-zero.js new file mode 100644 index 000000000000..8610156170fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Negative zero, as an extended year, fails +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const bad = "-000000-12-07T03:24:30"; + +assert.throws( + RangeError, + () => Temporal.PlainTime.compare(bad, time), + "Cannot use minus zero as extended year (first argument)" +); + +assert.throws( + RangeError, + () => Temporal.PlainTime.compare(time, bad), + "Cannot use minus zero as extended year (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/constructor.js new file mode 100644 index 000000000000..777e8d7310d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Temporal.PlainTime constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.PlainTime()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-number.js new file mode 100644 index 000000000000..58fb40657151 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-number.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Number argument is converted to string +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const result = Temporal.PlainTime.from(1523); +TemporalHelpers.assertPlainTime(result, 15, 23, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object-leap-second.js new file mode 100644 index 000000000000..a0a045c4d512 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object-leap-second.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Object argument handles leap seconds according to the overflow option. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +for (const options of [undefined, {}, { overflow: "constrain" }]) { + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 23, minute: 59, second: 60 }, options), + 23, 59, 59, 0, 0, 0); + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 12, minute: 30, second: 60 }, options), + 12, 30, 59, 0, 0, 0); + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 23, minute: 59, second: 60, millisecond: 170 }, options), + 23, 59, 59, 170, 0, 0); +} + +const options = { overflow: "reject" }; +assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 23, minute: 59, second: 60 }, options)); +assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 12, minute: 30, second: 60 }, options)); +assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 23, minute: 59, second: 60, millisecond: 170 }, options)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object.js new file mode 100644 index 000000000000..f02a090c3417 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Plain object argument is supported and ignores plural properties +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 15, minute: 23 }), + 15, 23, 0, 0, 0, 0); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ minute: 30, microsecond: 555 }), + 0, 30, 0, 0, 555, 0); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ year: 2019, month: 10, day: 1, hour: 14, minute: 20, second: 36 }), + 14, 20, 36, 0, 0, 0); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hours: 2, minute: 30, microsecond: 555 }), + 0, 30, 0, 0, 555, 0); + +assert.throws(TypeError, () => Temporal.PlainTime.from({})); +assert.throws(TypeError, () => Temporal.PlainTime.from({ minutes: 12 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaindatetime.js new file mode 100644 index 000000000000..48b48c7b17be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaindatetime.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((plainDateTime) => { + const result = Temporal.PlainTime.from(plainDateTime); + TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 321); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaintime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaintime.js new file mode 100644 index 000000000000..00ceb306f5be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaintime.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: A PlainTime object is copied, not returned directly +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("11:42:00"); +const result = Temporal.PlainTime.from(plainTime); +assert.notSameValue(result, plainTime); +TemporalHelpers.assertPlainTime(result, 11, 42, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-leap-second.js new file mode 100644 index 000000000000..f64a291ee307 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-leap-second.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Leap second is replaced by :59 in ISO strings. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +for (const options of [undefined, {}, { overflow: "constrain" }, { overflow: "reject" }]) { + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("23:59:60", options), + 23, 59, 59, 0, 0, 0); + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("12:30:60", options), + 12, 30, 59, 0, 0, 0); + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("23:59:60.170", options), + 23, 59, 59, 170, 0, 0); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..7269411e5a16 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-no-implicit-midnight.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..8e84fb980a23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,54 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + `${string} is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + Temporal.PlainTime.from(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + 'space is not accepted as a substitute for T prefix' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => Temporal.PlainTime.from(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-trailing-junk.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-trailing-junk.js new file mode 100644 index 000000000000..847f9ae138f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-trailing-junk.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown if a string argument has trailing junk +features: [Temporal, arrow-function] +---*/ + +const arg = "15:23:30.100junk"; +assert.throws(RangeError, () => Temporal.PlainTime.from(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-calendar.js new file mode 100644 index 000000000000..326fe1ef8bc7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-calendar.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-totemporaltime +description: Strings with non-ISO calendars are not supported. +info: | + b. Let result be ? ParseTemporalTimeString(string). + d. If result.[[Calendar]] is not one of undefined or "iso8601", then + i. Throw a RangeError exception. +features: [Temporal] +---*/ + +const isoString = "2004-03-21T10:00:00"; + +const valid = [ + "", + "[u-ca=iso8601]", +]; + +for (const s of valid) { + const input = isoString + s; + const plainTime = Temporal.PlainTime.from(input); + assert.sameValue(plainTime.calendar.id, "iso8601"); +} + +const invalid = [ + "[u-ca=indian]", + "[u-ca=hebrew]", +]; + +for (const s of invalid) { + const input = isoString + s; + assert.throws(RangeError, () => Temporal.PlainTime.from(input)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-time-designator.js new file mode 100644 index 000000000000..a693dc780681 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-time-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = Temporal.PlainTime.from(arg); + TemporalHelpers.assertPlainTime(result, 0, 30, 0, 0, 0, 0, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..9597cc3b3a5d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-utc-designator.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string.js new file mode 100644 index 000000000000..c1f4bc0d5887 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string.js @@ -0,0 +1,60 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Various ISO strings supported +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const tests = [ + ["15:23", 15, 23, 0, 0, 0, 0], + ["15:23:30", 15, 23, 30, 0, 0, 0], + ["15:23:30.123", 15, 23, 30, 123, 0, 0], + ["15:23:30.123456", 15, 23, 30, 123, 456, 0], + ["15:23:30.123456789", 15, 23, 30, 123, 456, 789], + ["1976-11-18T15:23:30.1", 15, 23, 30, 100, 0, 0], + ["1976-11-18T15:23:30.12", 15, 23, 30, 120, 0, 0], + ["1976-11-18T15:23:30.123", 15, 23, 30, 123, 0, 0], + ["1976-11-18T15:23:30.1234", 15, 23, 30, 123, 400, 0], + ["1976-11-18T15:23:30.12345", 15, 23, 30, 123, 450, 0], + ["1976-11-18T15:23:30.123456", 15, 23, 30, 123, 456, 0], + ["1976-11-18T15:23:30.1234567", 15, 23, 30, 123, 456, 700], + ["1976-11-18T15:23:30.12345678", 15, 23, 30, 123, 456, 780], + ["1976-11-18T15:23:30.123456789", 15, 23, 30, 123, 456, 789], + ["1976-11-18T15:23:30,12", 15, 23, 30, 120, 0, 0], + ["1976-11-18T15:23:30.12\u221202:00", 15, 23, 30, 120, 0, 0], + ["152330", 15, 23, 30, 0, 0, 0], + ["152330.1", 15, 23, 30, 100, 0, 0], + ["152330-08", 15, 23, 30, 0, 0, 0], + ["152330.1-08", 15, 23, 30, 100, 0, 0], + ["152330-0800", 15, 23, 30, 0, 0, 0], + ["152330.1-0800", 15, 23, 30, 100, 0, 0], + ["1976-11-18T152330.1+00:00", 15, 23, 30, 100, 0, 0], + ["19761118T15:23:30.1+00:00", 15, 23, 30, 100, 0, 0], + ["1976-11-18T15:23:30.1+0000", 15, 23, 30, 100, 0, 0], + ["1976-11-18T152330.1+0000", 15, 23, 30, 100, 0, 0], + ["19761118T15:23:30.1+0000", 15, 23, 30, 100, 0, 0], + ["19761118T152330.1+00:00", 15, 23, 30, 100, 0, 0], + ["19761118T152330.1+0000", 15, 23, 30, 100, 0, 0], + ["+001976-11-18T152330.1+00:00", 15, 23, 30, 100, 0, 0], + ["+0019761118T15:23:30.1+00:00", 15, 23, 30, 100, 0, 0], + ["+001976-11-18T15:23:30.1+0000", 15, 23, 30, 100, 0, 0], + ["+001976-11-18T152330.1+0000", 15, 23, 30, 100, 0, 0], + ["+0019761118T15:23:30.1+0000", 15, 23, 30, 100, 0, 0], + ["+0019761118T152330.1+00:00", 15, 23, 30, 100, 0, 0], + ["+0019761118T152330.1+0000", 15, 23, 30, 100, 0, 0], + ["15", 15, 0, 0, 0, 0, 0], + ["T15:23:30", 15, 23, 30, 0, 0, 0], + ["t152330", 15, 23, 30, 0, 0, 0], +]; + +for (const [input, ...expected] of tests) { + const result = Temporal.PlainTime.from(input); + assert.sameValue(expected.length, 6, input); + TemporalHelpers.assertPlainTime(result, ...expected, input); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..7674e134138b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaintime.from step 4: + 4. Return ? ToTemporalTime(_temporalTime_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const time = Temporal.PlainTime.from(datetime); + +TemporalHelpers.assertPlainTime(time, 1, 1, 1, 1, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..158a658a1f7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = Temporal.PlainTime.from(datetime); +TemporalHelpers.assertPlainTime(result, 16, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..354e99cf5460 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => Temporal.PlainTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..5ee3f89ac8ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaintime.from +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.PlainTime.from(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..bd2e640887dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => Temporal.PlainTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..350fbd57c0c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => Temporal.PlainTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/builtin.js new file mode 100644 index 000000000000..5748262b20d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Tests that Temporal.PlainTime.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/calendar-temporal-object.js new file mode 100644 index 000000000000..60c93ebc22b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/calendar-temporal-object.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.from step 4: + 4. Return ? ToTemporalTime(_temporalTime_, _overflow_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, calendar: temporalObject })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..266c3fd7ce38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainTime.from({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => Temporal.PlainTime.from({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/length.js new file mode 100644 index 000000000000..e76663b3ec02 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Temporal.PlainTime.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/name.js new file mode 100644 index 000000000000..7eab2a4535e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Temporal.PlainTime.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/not-a-constructor.js new file mode 100644 index 000000000000..3f3eb71b6b4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Temporal.PlainTime.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.from), false, + "isConstructor(Temporal.PlainTime.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js new file mode 100644 index 000000000000..2bce19d35dab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: overflow property is extracted with ISO-invalid string argument. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get overflow", + "get overflow.toString", + "call overflow.toString", +]; + +let actual = []; +const object = { + get overflow() { + actual.push("get overflow"); + return TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); + } +}; + +assert.throws(RangeError, () => Temporal.PlainTime.from("24:60", object)); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-invalid.js new file mode 100644 index 000000000000..d1a96183481e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-invalid.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; + +for (const badOptions of values) { + assert.throws(TypeError, () => Temporal.PlainTime.from({ hours: 12 }, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-undefined.js new file mode 100644 index 000000000000..cb91de40961a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const fields = { hour: 12, minute: 60 }; + +const explicit = Temporal.PlainTime.from(fields, undefined); +assert.sameValue(explicit.minute, 59, "default overflow is constrain"); + +const implicit = Temporal.PlainTime.from(fields); +assert.sameValue(implicit.minute, 59, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/order-of-operations.js new file mode 100644 index 000000000000..25094ad51828 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/order-of-operations.js @@ -0,0 +1,59 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Properties on an object passed to from() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get calendar", + "get hour", + "get hour.valueOf", + "call hour.valueOf", + "get microsecond", + "get microsecond.valueOf", + "call microsecond.valueOf", + "get millisecond", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get minute", + "get minute.valueOf", + "call minute.valueOf", + "get nanosecond", + "get nanosecond.valueOf", + "call nanosecond.valueOf", + "get second", + "get second.valueOf", + "call second.valueOf", +]; +const actual = []; +const fields = { + hour: 1.7, + minute: 1.7, + second: 1.7, + millisecond: 1.7, + microsecond: 1.7, + nanosecond: 1.7, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + if (key === "calendar") return Temporal.Calendar.from("iso8601"); + const result = target[key]; + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = Temporal.PlainTime.from(argument); +TemporalHelpers.assertPlainTime(result, 1, 1, 1, 1, 1, 1); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-constrain.js new file mode 100644 index 000000000000..f90f3ab47273 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-constrain.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: constrain value for overflow option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 26 }, { overflow: "constrain" }), + 23, 0, 0, 0, 0, 0); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 22 }, { overflow: "constrain" }), + 22, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js new file mode 100644 index 000000000000..3ea17b312d8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.from step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainTime(12), + { hour: 12 }, + "12:00", +]; + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-reject.js new file mode 100644 index 000000000000..de14a1a54839 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-reject.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: reject value for overflow option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 26 }, { overflow: "reject" })); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 22 }, { overflow: "reject" }), + 22, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-undefined.js new file mode 100644 index 000000000000..8783aaba7e33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-undefined.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.from step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainTime(12), + "12:00", +]; +validValues.forEach((value) => { + const explicit = Temporal.PlainTime.from(value, { overflow: undefined }); + TemporalHelpers.assertPlainTime(explicit, 12, 0, 0, 0, 0, 0, "overflow is ignored"); + const implicit = Temporal.PlainTime.from(value, {}); + TemporalHelpers.assertPlainTime(implicit, 12, 0, 0, 0, 0, 0, "overflow is ignored"); + const lambda = Temporal.PlainTime.from(value, () => {}); + TemporalHelpers.assertPlainTime(lambda, 12, 0, 0, 0, 0, 0, "overflow is ignored"); +}); + +const propertyBag = { hour: 26 }; +const explicit = Temporal.PlainTime.from(propertyBag, { overflow: undefined }); +TemporalHelpers.assertPlainTime(explicit, 23, 0, 0, 0, 0, 0, "default overflow is constrain"); +const implicit = Temporal.PlainTime.from(propertyBag, {}); +TemporalHelpers.assertPlainTime(implicit, 23, 0, 0, 0, 0, 0, "default overflow is constrain"); +const lambda = Temporal.PlainTime.from(propertyBag, () => {}); +TemporalHelpers.assertPlainTime(lambda, 23, 0, 0, 0, 0, 0, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-wrong-type.js new file mode 100644 index 000000000000..65a751e10eef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.from step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainTime(12), + { hour: 12 }, + "12:00", +]; +validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => Temporal.PlainTime.from(value, { overflow }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 0, 0, 0, 0, 0, descr), +)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/plaintime-propertybag-no-time-units.js new file mode 100644 index 000000000000..d0dcd88db8ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/plaintime-propertybag-no-time-units.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Missing time units in property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const props = {}; +assert.throws(TypeError, () => Temporal.PlainTime.from(props), "TypeError if at least one property is not present"); + +props.minute = 30; +const result = Temporal.PlainTime.from(props); +TemporalHelpers.assertPlainTime(result, 0, 30, 0, 0, 0, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/prop-desc.js new file mode 100644 index 000000000000..fce91759d7b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: The "from" property of Temporal.PlainTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.from, + "function", + "`typeof PlainTime.from` is `function`" +); + +verifyProperty(Temporal.PlainTime, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/subclassing-ignored.js new file mode 100644 index 000000000000..6911f533d3d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/subclassing-ignored.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.PlainTime, + "from", + ["12:34:56.987654321"], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 321), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/year-zero.js new file mode 100644 index 000000000000..1bd2c09ff889 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/year-zero.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-12-07T03:24:30', + '-000000-12-07T03:24:30+01:00[UTC]' +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { Temporal.PlainTime.from(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/hour-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/hour-undefined.js new file mode 100644 index 000000000000..60c5537943df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/hour-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Hour argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const explicit = new Temporal.PlainTime(undefined); +TemporalHelpers.assertPlainTime(explicit, 0, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(); +TemporalHelpers.assertPlainTime(implicit, 0, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..6d73ab55c10a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/infinity-throws-rangeerror.js @@ -0,0 +1,60 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime throws a RangeError if any value is Infinity +esid: sec-temporal.plaintime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainTime(Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, 0, 0, Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite hour", + [O(Infinity, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf"] + ], + [ + "infinite minute", + [O(1, "hour"), O(Infinity, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf"] + ], + [ + "infinite second", + [O(1, "hour"), O(1, "minute"), O(Infinity, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf"] + ], + [ + "infinite millisecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(Infinity, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf"] + ], + [ + "infinite microsecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(Infinity, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf", "get microsecond.valueOf", "call microsecond.valueOf"] + ], + [ + "infinite nanosecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(Infinity, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf", "get microsecond.valueOf", "call microsecond.valueOf", "get nanosecond.valueOf", "call nanosecond.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainTime(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/length.js new file mode 100644 index 000000000000..f295b90025de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Temporal.PlainTime.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/microsecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/microsecond-undefined.js new file mode 100644 index 000000000000..d0bc70ec8a6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/microsecond-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Microsecond argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [12, 34, 56, 123]; + +const explicit = new Temporal.PlainTime(...args, undefined); +TemporalHelpers.assertPlainTime(explicit, ...args, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(implicit, ...args, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/millisecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/millisecond-undefined.js new file mode 100644 index 000000000000..7b7dc0e52b9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/millisecond-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Millisecond argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [12, 34, 56]; + +const explicit = new Temporal.PlainTime(...args, undefined); +TemporalHelpers.assertPlainTime(explicit, ...args, 0, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(implicit, ...args, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/minute-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/minute-undefined.js new file mode 100644 index 000000000000..d429e952c0d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/minute-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Minute argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const hour = 12; + +const explicit = new Temporal.PlainTime(hour, undefined); +TemporalHelpers.assertPlainTime(explicit, hour, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(hour); +TemporalHelpers.assertPlainTime(implicit, hour, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/name.js new file mode 100644 index 000000000000..5db577b359b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Temporal.PlainTime.name is "PlainTime" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime, "name", { + value: "PlainTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/nanosecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/nanosecond-undefined.js new file mode 100644 index 000000000000..b1d21cabaa6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/nanosecond-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Nanosecond argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [12, 34, 56, 123, 456]; + +const explicit = new Temporal.PlainTime(...args, undefined); +TemporalHelpers.assertPlainTime(explicit, ...args, 0, "explicit"); + +const implicit = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(implicit, ...args, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..6c3efde1af43 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-infinity-throws-rangeerror.js @@ -0,0 +1,60 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate throws a RangeError if any value is -Infinity +esid: sec-temporal.plaintime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainTime(-Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, 0, 0, -Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite hour", + [O(-Infinity, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf"] + ], + [ + "infinite minute", + [O(1, "hour"), O(-Infinity, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf"] + ], + [ + "infinite second", + [O(1, "hour"), O(1, "minute"), O(-Infinity, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf"] + ], + [ + "infinite millisecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(-Infinity, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf"] + ], + [ + "infinite microsecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(-Infinity, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf", "get microsecond.valueOf", "call microsecond.valueOf"] + ], + [ + "infinite nanosecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(-Infinity, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf", "get microsecond.valueOf", "call microsecond.valueOf", "get nanosecond.valueOf", "call nanosecond.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainTime(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-zero.js new file mode 100644 index 000000000000..ead1776bcd74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-zero.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Negative zero arguments are treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(-0, -0, -0, -0, -0, -0); +TemporalHelpers.assertPlainTime(plainTime, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prop-desc.js new file mode 100644 index 000000000000..22139579e5d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: The "PlainTime" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime, + "function", + "`typeof PlainTime` is `function`" +); + +verifyProperty(Temporal, "PlainTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration.js new file mode 100644 index 000000000000..c7d899ee2298 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Duration arguments are supported. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const duration = Temporal.Duration.from("PT16H"); +TemporalHelpers.assertPlainTime(plainTime.add(duration), + 7, 23, 30, 123, 456, 789); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-higher-units.js new file mode 100644 index 000000000000..2d1bb31cb19e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-higher-units.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Higher units are ignored. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const values = [ + new Temporal.Duration(0, 0, 0, 1), + new Temporal.Duration(0, 0, 1), + new Temporal.Duration(0, 1), + new Temporal.Duration(1), + { days: 1 }, + { weeks: 1 }, + { months: 1 }, + { years: 1 }, + "P1D", + "P1W", + "P1M", + "P1Y", +]; +for (const value of values) { + TemporalHelpers.assertPlainTime(plainTime.add(value), + 15, 23, 30, 123, 456, 789); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-not-object.js new file mode 100644 index 000000000000..b9f0a246b633 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Passing a primitive other than string to add() throws +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +assert.throws(RangeError, () => instance.add(undefined), "undefined"); +assert.throws(RangeError, () => instance.add(null), "null"); +assert.throws(RangeError, () => instance.add(true), "boolean"); +assert.throws(RangeError, () => instance.add(""), "empty string"); +assert.throws(TypeError, () => instance.add(Symbol()), "Symbol"); +assert.throws(RangeError, () => instance.add(7), "number"); +assert.throws(RangeError, () => instance.add(7n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object-invalid.js new file mode 100644 index 000000000000..bdd103ae0524 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Mixed positive and negative values or missing properties always throw +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +assert.throws(RangeError, () => plainTime.add({ hours: 1, minutes: -6 }), "mixed signs"); +assert.throws(TypeError, () => plainTime.add({}), "no properties"); +assert.throws(TypeError, () => plainTime.add({ hour: 12 }), "only singular 'hour' property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object.js new file mode 100644 index 000000000000..892022465d19 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Plain object arguments are supported. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.add({ hours: 16 }), + 7, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.add({ minutes: 45 }), + 16, 8, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.add({ seconds: 800 }), + 15, 36, 50, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.add({ milliseconds: 800 }), + 15, 23, 30, 923, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.add({ microseconds: 800 }), + 15, 23, 30, 124, 256, 789); +TemporalHelpers.assertPlainTime(plainTime.add({ nanoseconds: 300 }), + 15, 23, 30, 123, 457, 89); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("07:23:30.123456789").add({ hours: -16 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("16:08:30.123456789").add({ minutes: -45 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:36:50.123456789").add({ seconds: -800 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.923456789").add({ milliseconds: -800 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.124256789").add({ microseconds: -800 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.123457089").add({ nanoseconds: -300 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.add({ minute: 1, hours: 1 }), + 16, 23, 30, 123, 456, 789); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..215481fe2fee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const midnight = new Temporal.PlainTime(); + +TemporalHelpers.assertPlainTime(midnight.add("PT1.03125H"), 1, 1, 52, 500, 0, 0, + "positive fractional units rounded with correct rounding mode"); +TemporalHelpers.assertPlainTime(midnight.add("-PT1.03125H"), 22, 58, 7, 500, 0, 0, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..15c7b3ddaac5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const resultHours = instance.add("-PT24.567890123H"); +TemporalHelpers.assertPlainTime(resultHours, 23, 25, 55, 595, 557, 201, "negative fractional hours"); + +const resultMinutes = instance.add("-PT1440.567890123M"); +TemporalHelpers.assertPlainTime(resultMinutes, 23, 59, 25, 926, 592, 621, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string.js new file mode 100644 index 000000000000..fe63233cd2b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +const result = instance.add("PT3M"); +TemporalHelpers.assertPlainTime(result, 12, 37, 56, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/balance-negative-time-units.js new file mode 100644 index 000000000000..0d0d2f58a23f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/balance-negative-time-units.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal.plaintime.prototype.add step 4: + 4. Let _result_ be ? AddTime(_temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); + +const result1 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result1, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result2, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result3, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result4, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result5, 0, 59, 1, 1, 1, 1, "minutes balance"); + +const result6 = time.add(new Temporal.Duration(0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result6, 23, 1, 1, 1, 1, 1, "hours mod 24"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/builtin.js new file mode 100644 index 000000000000..c64eaf8ea5e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: > + Tests that Temporal.PlainTime.prototype.add + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.add), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.add), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.add), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.add.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..acc963766211 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime.prototype.add throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plaintime.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/length.js new file mode 100644 index 000000000000..a5081e08c535 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Temporal.PlainTime.prototype.add.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.add, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/name.js new file mode 100644 index 000000000000..f0774dbe6163 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Temporal.PlainTime.prototype.add.name is "add". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.add, "name", { + value: "add", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..981c026dbec3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime.prototype.add throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plaintime.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..e256ce95d6b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.add({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/not-a-constructor.js new file mode 100644 index 000000000000..41a2780463bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: > + Temporal.PlainTime.prototype.add does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.add(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.add), false, + "isConstructor(Temporal.PlainTime.prototype.add)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/options-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/options-ignored.js new file mode 100644 index 000000000000..44bf7959f5c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/options-ignored.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Options argument is ignored. +includes: [temporalHelpers.js] +features: [Symbol, Temporal] +---*/ + +const values = [ + undefined, + null, + true, + "hello", + Symbol("foo"), + 1, + 1n, + {}, + () => {}, + { get overflow() { throw new Test262Error("should not get overflow") } }, +]; + +const time = Temporal.PlainTime.from("15:23:30.123456789"); +for (const options of values) { + TemporalHelpers.assertPlainTime(time.add({ hours: 1 }, options), + 16, 23, 30, 123, 456, 789); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/order-of-operations.js new file mode 100644 index 000000000000..e5ffd4ce18a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Properties on an object passed to add() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.add(argument); +TemporalHelpers.assertPlainTime(result, 13, 35, 57, 988, 655, 322); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/prop-desc.js new file mode 100644 index 000000000000..3d644c0f8cbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: The "add" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.add, + "function", + "`typeof PlainTime.prototype.add` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "add", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/subclassing-ignored.js new file mode 100644 index 000000000000..ee8b3f4871a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Objects of a subclass are never created as return values for add() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainTime, + [12, 34, 56, 987, 654, 321], + "add", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 322), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/calendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/calendar/prop-desc.js new file mode 100644 index 000000000000..600777f4dfdb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/calendar/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.calendar +description: The "calendar" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "calendar"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-cast.js new file mode 100644 index 000000000000..9ad32ba51ac4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-cast.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: equals() casts its argument +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("08:44:15.321"); + +assert.sameValue(t1.equals({ hour: 14, minute: 23, second: 30, millisecond: 123 }), false, "object"); +assert.sameValue(t1.equals({ hour: 8, minute: 44, second: 15, millisecond: 321 }), true, "object"); +assert.sameValue(t1.equals("14:23:30.123"), false, "string"); +assert.sameValue(t1.equals("08:44:15.321"), true, "string"); +assert.throws(TypeError, () => t1.equals({}), "no properties"); +assert.throws(TypeError, () => t1.equals({ hours: 8 }), "only plural property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..97498bce9f98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +assert.throws( + RangeError, + () => instance.equals(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..332a2908dd2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.equals(arg), + `${string} is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.equals(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.equals(arg), + 'space is not accepted as a substitute for T prefix' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => instance.equals(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-time-designator.js new file mode 100644 index 000000000000..b86dfccb792d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-time-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(0, 30, 0, 0, 0, 0); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.equals(arg); + assert.sameValue(result, true, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..354f03d57323 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-wrong-type.js new file mode 100644 index 000000000000..7d50260cadb1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-wrong-type.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Appropriate error thrown when argument cannot be converted to a valid string +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainTime.from({ minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +assert.throws(RangeError, () => instance.equals(undefined), "undefined"); +assert.throws(RangeError, () => instance.equals(null), "null"); +assert.throws(RangeError, () => instance.equals(true), "true"); +assert.throws(RangeError, () => instance.equals(""), "empty string"); +assert.throws(TypeError, () => instance.equals(Symbol()), "symbol"); +assert.throws(RangeError, () => instance.equals(1), "1"); +assert.throws(TypeError, () => instance.equals({}), "plain object"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..1c9376d11792 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaintime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +assert(new Temporal.PlainTime(1, 1, 1, 1, 0, 999).equals(datetime)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..c10a2222c2c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainTime(16, 50, 35, 0, 0, 1); +const result = instance.equals(datetime); +assert.sameValue(result, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..5719f46da804 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..dddeee36ad5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.equals(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..08ea0be491e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..c85d96fbc404 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/basic.js new file mode 100644 index 000000000000..e391f8e1dd87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/basic.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Basic tests for equals() +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("08:44:15.321"); +const t1bis = Temporal.PlainTime.from("08:44:15.321"); +const t2 = Temporal.PlainTime.from("14:23:30.123"); +assert.sameValue(t1.equals(t1), true, "same object"); +assert.sameValue(t1.equals(t1bis), true, "different object"); +assert.sameValue(t1.equals(t2), false, "different times"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/builtin.js new file mode 100644 index 000000000000..14bdeb760a04 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: > + Tests that Temporal.PlainTime.prototype.equals + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.equals), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.equals), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.equals), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.equals.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/calendar-temporal-object.js new file mode 100644 index 000000000000..e0295c5d33b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/calendar-temporal-object.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => time.equals({ hour: 12, minute: 30, calendar: temporalObject })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/length.js new file mode 100644 index 000000000000..8842dce86db5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Temporal.PlainTime.prototype.equals.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.equals, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/name.js new file mode 100644 index 000000000000..e5f188b73cca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Temporal.PlainTime.prototype.equals.name is "equals". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.equals, "name", { + value: "equals", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/not-a-constructor.js new file mode 100644 index 000000000000..11d55bd1ed3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: > + Temporal.PlainTime.prototype.equals does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.equals(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.equals), false, + "isConstructor(Temporal.PlainTime.prototype.equals)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/plaintime-propertybag-no-time-units.js new file mode 100644 index 000000000000..4b3ea1c730a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/plaintime-propertybag-no-time-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Missing time units in property bag default to 0 +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(0, 30, 0, 0, 0, 0); + +const props = {}; +assert.throws(TypeError, () => instance.equals(props), "TypeError if at least one property is not present"); + +props.minute = 30; +const result = instance.equals(props); +assert.sameValue(result, true, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/prop-desc.js new file mode 100644 index 000000000000..da054b2b3f2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: The "equals" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.equals, + "function", + "`typeof PlainTime.prototype.equals` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "equals", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/year-zero.js new file mode 100644 index 000000000000..affab7b21225 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-12-07T03:24:30', + '-000000-12-07T03:24:30+01:00[UTC]' +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/builtin.js new file mode 100644 index 000000000000..7d71500ec91e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: > + Tests that Temporal.PlainTime.prototype.getISOFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.getISOFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.getISOFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.getISOFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.getISOFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-names.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-names.js new file mode 100644 index 000000000000..57101281b572 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-names.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Correct field names on the object returned from getISOFields +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const result = time.getISOFields(); +assert.sameValue(result.isoHour, 12, "isoHour result"); +assert.sameValue(result.isoMinute, 34, "isoMinute result"); +assert.sameValue(result.isoSecond, 56, "isoSecond result"); +assert.sameValue(result.isoMillisecond, 987, "isoMillisecond result"); +assert.sameValue(result.isoMicrosecond, 654, "isoMicrosecond result"); +assert.sameValue(result.isoNanosecond, 321, "isoNanosecond result"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-prop-desc.js new file mode 100644 index 000000000000..81345ba910af --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-prop-desc.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Properties on the returned object have the correct descriptor +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoHour", + "isoMicrosecond", + "isoMillisecond", + "isoMinute", + "isoNanosecond", + "isoSecond", +]; + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const result = time.getISOFields(); + +for (const property of expected) { + verifyProperty(result, property, { + writable: true, + enumerable: true, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-traversal-order.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-traversal-order.js new file mode 100644 index 000000000000..efad885cb7bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-traversal-order.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Properties added in correct order to object returned from getISOFields +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoHour", + "isoMicrosecond", + "isoMillisecond", + "isoMinute", + "isoNanosecond", + "isoSecond", +]; + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const result = time.getISOFields(); + +assert.compareArray(Object.keys(result), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/length.js new file mode 100644 index 000000000000..90d423f298e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Temporal.PlainTime.prototype.getISOFields.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.getISOFields, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/name.js new file mode 100644 index 000000000000..8ef16c432cef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Temporal.PlainTime.prototype.getISOFields.name is "getISOFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.getISOFields, "name", { + value: "getISOFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/not-a-constructor.js new file mode 100644 index 000000000000..609fb5087317 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: > + Temporal.PlainTime.prototype.getISOFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.getISOFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.getISOFields), false, + "isConstructor(Temporal.PlainTime.prototype.getISOFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prop-desc.js new file mode 100644 index 000000000000..005eb70a9db0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: The "getISOFields" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.getISOFields, + "function", + "`typeof PlainTime.prototype.getISOFields` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "getISOFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/prop-desc.js new file mode 100644 index 000000000000..6277fd49411f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.hour +description: The "hour" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "hour"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/prop-desc.js new file mode 100644 index 000000000000..7b299f3827d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.microsecond +description: The "microsecond" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "microsecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/prop-desc.js new file mode 100644 index 000000000000..fd864af1907f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.millisecond +description: The "millisecond" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "millisecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/prop-desc.js new file mode 100644 index 000000000000..03b55d78d387 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.minute +description: The "minute" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "minute"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/prop-desc.js new file mode 100644 index 000000000000..21c0e2d3ced5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.nanosecond +description: The "nanosecond" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "nanosecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/prop-desc.js new file mode 100644 index 000000000000..84b34b29618e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-plaintime-prototype +description: The "prototype" property of Temporal.PlainTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.PlainTime.prototype, "object"); +assert.notSameValue(Temporal.PlainTime.prototype, null); + +verifyProperty(Temporal.PlainTime, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/builtin.js new file mode 100644 index 000000000000..7535a67544b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: > + Tests that Temporal.PlainTime.prototype.round + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.round), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.round), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.round), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.round.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/length.js new file mode 100644 index 000000000000..9d70c1585eb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Temporal.PlainTime.prototype.round.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.round, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/name.js new file mode 100644 index 000000000000..005ddfb2d843 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Temporal.PlainTime.prototype.round.name is "round". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.round, "name", { + value: "round", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/not-a-constructor.js new file mode 100644 index 000000000000..bae3bd7f4cf2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: > + Temporal.PlainTime.prototype.round does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.round(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.round), false, + "isConstructor(Temporal.PlainTime.prototype.round)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/prop-desc.js new file mode 100644 index 000000000000..72a70b43fd5b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: The "round" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.round, + "function", + "`typeof PlainTime.prototype.round` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "round", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/rounding-cross-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/rounding-cross-midnight.js new file mode 100644 index 000000000000..e21c60a69e00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/rounding-cross-midnight.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Rounding can cross midnight +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("23:59:59.999999999"); +for (const smallestUnit of ["hour", "minute", "second", "millisecond", "microsecond"]) { + TemporalHelpers.assertPlainTime(plainTime.round({ smallestUnit }), 0, 0, 0, 0, 0, 0); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-hours.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-hours.js new file mode 100644 index 000000000000..9c995aeb2f72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-hours.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 1 }), + 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 2 }), + 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 3 }), + 3, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 4 }), + 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 6 }), + 6, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 8 }), + 0, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 12 }), + 0, 0, 0, 0, 0, 0, "hours"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-invalid.js new file mode 100644 index 000000000000..3ee77213ab05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-invalid.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests roundingIncrement restrictions. +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("08:22:36.123456789"); + +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "hours", roundingIncrement: 11 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "minutes", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "seconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "hours", roundingIncrement: 24 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "minutes", roundingIncrement: 60 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "seconds", roundingIncrement: 60 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 1000 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-microseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-microseconds.js new file mode 100644 index 000000000000..18ff82caeee9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-microseconds.js @@ -0,0 +1,60 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 1 }), + 3, 34, 56, 987, 654, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 2 }), + 3, 34, 56, 987, 654, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 4 }), + 3, 34, 56, 987, 656, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 5 }), + 3, 34, 56, 987, 655, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 8 }), + 3, 34, 56, 987, 656, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 10 }), + 3, 34, 56, 987, 650, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 20 }), + 3, 34, 56, 987, 660, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 25 }), + 3, 34, 56, 987, 650, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 40 }), + 3, 34, 56, 987, 640, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 50 }), + 3, 34, 56, 987, 650, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 100 }), + 3, 34, 56, 987, 700, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 125 }), + 3, 34, 56, 987, 625, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 200 }), + 3, 34, 56, 987, 600, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 250 }), + 3, 34, 56, 987, 750, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 500 }), + 3, 34, 56, 987, 500, 0, "microseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-milliseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-milliseconds.js new file mode 100644 index 000000000000..e28334d9cc9b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-milliseconds.js @@ -0,0 +1,60 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 1 }), + 3, 34, 56, 988, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 2 }), + 3, 34, 56, 988, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 4 }), + 3, 34, 56, 988, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 5 }), + 3, 34, 56, 990, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 8 }), + 3, 34, 56, 984, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 10 }), + 3, 34, 56, 990, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 20 }), + 3, 34, 56, 980, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 25 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 40 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 50 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 100 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 125 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 200 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 250 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 500 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-minutes.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-minutes.js new file mode 100644 index 000000000000..87cf21a2943f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-minutes.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 1 }), + 3, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 2 }), + 3, 34, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 3 }), + 3, 36, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 4 }), + 3, 36, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 5 }), + 3, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 6 }), + 3, 36, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 10 }), + 3, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 12 }), + 3, 36, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 15 }), + 3, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 20 }), + 3, 40, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 30 }), + 3, 30, 0, 0, 0, 0, "minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nan.js new file mode 100644 index 000000000000..3272f5d3f955 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nan.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.round step 11: + 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +assert.throws(RangeError, () => time.round({ smallestUnit: 'second', roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nanoseconds.js new file mode 100644 index 000000000000..00d09e50620d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nanoseconds.js @@ -0,0 +1,60 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 1 }), + 3, 34, 56, 987, 654, 321, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 2 }), + 3, 34, 56, 987, 654, 322, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 4 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 5 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 8 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 10 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 20 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 25 }), + 3, 34, 56, 987, 654, 325, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 40 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 50 }), + 3, 34, 56, 987, 654, 300, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 100 }), + 3, 34, 56, 987, 654, 300, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 125 }), + 3, 34, 56, 987, 654, 375, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 200 }), + 3, 34, 56, 987, 654, 400, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 250 }), + 3, 34, 56, 987, 654, 250, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 500 }), + 3, 34, 56, 987, 654, 500, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-non-integer.js new file mode 100644 index 000000000000..67dd7a3a8ff4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +const result = time.round({ smallestUnit: "nanosecond", roundingIncrement: 2.5 }); +TemporalHelpers.assertPlainTime(result, 12, 34, 56, 0, 0, 6, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..36cb3616cfa9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: -Infinity })); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: -1 })); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: 0 })); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-seconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-seconds.js new file mode 100644 index 000000000000..120806bb3eb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-seconds.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 1 }), + 3, 34, 57, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 2 }), + 3, 34, 56, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 3 }), + 3, 34, 57, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 4 }), + 3, 34, 56, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 5 }), + 3, 34, 55, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 6 }), + 3, 34, 54, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 10 }), + 3, 35, 0, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 12 }), + 3, 35, 0, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 15 }), + 3, 35, 0, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 20 }), + 3, 35, 0, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 30 }), + 3, 35, 0, 0, 0, 0, "seconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-undefined.js new file mode 100644 index 000000000000..071d677df3bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.round step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const explicit = time.round({ smallestUnit: 'second', roundingIncrement: undefined }); +TemporalHelpers.assertPlainTime(explicit, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1"); + +const implicit = time.round({ smallestUnit: 'second' }); +TemporalHelpers.assertPlainTime(implicit, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..c6466af90eb0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.round step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => time.round({ smallestUnit: 'second', roundingIncrement }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 57, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-ceil.js new file mode 100644 index 000000000000..6b6642bec605 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-ceil.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "ceil". +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const plainTime = Temporal.PlainTime.from("13:46:23.123456789"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hour", roundingMode: "ceil" }), + 14, 0, 0, 0, 0, 0, "hour"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minute", roundingMode: "ceil" }), + 13, 47, 0, 0, 0, 0, "minute"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "second", roundingMode: "ceil" }), + 13, 46, 24, 0, 0, 0, "second"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "millisecond", roundingMode: "ceil" }), + 13, 46, 23, 124, 0, 0, "millisecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microsecond", roundingMode: "ceil" }), + 13, 46, 23, 123, 457, 0, "microsecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanosecond", roundingMode: "ceil" }), + 13, 46, 23, 123, 456, 789, "nanosecond"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-floor.js new file mode 100644 index 000000000000..c9add31b3579 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-floor.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "floor". +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const plainTime = Temporal.PlainTime.from("13:46:23.123456789"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hour", roundingMode: "floor" }), + 13, 0, 0, 0, 0, 0, "hour"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minute", roundingMode: "floor" }), + 13, 46, 0, 0, 0, 0, "minute"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "second", roundingMode: "floor" }), + 13, 46, 23, 0, 0, 0, "second"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "millisecond", roundingMode: "floor" }), + 13, 46, 23, 123, 0, 0, "millisecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microsecond", roundingMode: "floor" }), + 13, 46, 23, 123, 456, 0, "microsecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanosecond", roundingMode: "floor" }), + 13, 46, 23, 123, 456, 789, "nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfExpand.js new file mode 100644 index 000000000000..cadd4d2b7bec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfExpand.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "floor". +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const plainTime = Temporal.PlainTime.from("13:46:23.123456789"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hour", roundingMode: "halfExpand" }), + 14, 0, 0, 0, 0, 0, "hour"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minute", roundingMode: "halfExpand" }), + 13, 46, 0, 0, 0, 0, "minute"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "second", roundingMode: "halfExpand" }), + 13, 46, 23, 0, 0, 0, "second"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "millisecond", roundingMode: "halfExpand" }), + 13, 46, 23, 123, 0, 0, "millisecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microsecond", roundingMode: "halfExpand" }), + 13, 46, 23, 123, 457, 0, "microsecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanosecond", roundingMode: "halfExpand" }), + 13, 46, 23, 123, 456, 789, "nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js new file mode 100644 index 000000000000..f241f77d0da7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => time.round({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-trunc.js new file mode 100644 index 000000000000..943e8d67ae5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-trunc.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "trunc". +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const plainTime = Temporal.PlainTime.from("13:46:23.123456789"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hour", roundingMode: "trunc" }), + 13, 0, 0, 0, 0, 0, "hour"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minute", roundingMode: "trunc" }), + 13, 46, 0, 0, 0, 0, "minute"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "second", roundingMode: "trunc" }), + 13, 46, 23, 0, 0, 0, "second"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "millisecond", roundingMode: "trunc" }), + 13, 46, 23, 123, 0, 0, "millisecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microsecond", roundingMode: "trunc" }), + 13, 46, 23, 123, 456, 0, "microsecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanosecond", roundingMode: "trunc" }), + 13, 46, 23, 123, 456, 789, "nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-undefined.js new file mode 100644 index 000000000000..8ec1da0fd65f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-undefined.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode undefined. +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const plainTime = Temporal.PlainTime.from("13:46:23.123456789"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hour", roundingMode: undefined }), + 14, 0, 0, 0, 0, 0, "hour"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hour" }), + 14, 0, 0, 0, 0, 0, "hour"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minute", roundingMode: undefined }), + 13, 46, 0, 0, 0, 0, "minute"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minute" }), + 13, 46, 0, 0, 0, 0, "minute"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "second", roundingMode: undefined }), + 13, 46, 23, 0, 0, 0, "second"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "second" }), + 13, 46, 23, 0, 0, 0, "second"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "millisecond", roundingMode: undefined }), + 13, 46, 23, 123, 0, 0, "millisecond"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "millisecond" }), + 13, 46, 23, 123, 0, 0, "millisecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microsecond", roundingMode: undefined }), + 13, 46, 23, 123, 457, 0, "microsecond"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microsecond" }), + 13, 46, 23, 123, 457, 0, "microsecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanosecond", roundingMode: undefined }), + 13, 46, 23, 123, 456, 789, "nanosecond"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanosecond" }), + 13, 46, 23, 123, 456, 789, "nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-wrong-type.js new file mode 100644 index 000000000000..8d5bdb93c731 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand", + (roundingMode) => time.round({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 123, 988, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-disallowed-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-disallowed-units.js new file mode 100644 index 000000000000..1329fc9a642d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-disallowed-units.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Specifically disallowed units for the smallestUnit option +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const invalidUnits = [ + "era", + "eras", + "year", + "month", + "week", + "years", + "months", + "weeks", + "day", + "days", +]; +invalidUnits.forEach((smallestUnit) => { + assert.throws( + RangeError, + () => instance.round({ smallestUnit }), + `{ smallestUnit: "${smallestUnit}" } should not be allowed as an argument to round` + ); + assert.throws( + RangeError, + () => instance.round(smallestUnit), + `"${smallestUnit}" should not be allowed as an argument to round` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js new file mode 100644 index 000000000000..0d347dc22bca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +const values = ["era", "year", "month", "week", "day", "years", "months", "weeks", "days", "nonsense", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => time.round({ smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-missing.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-missing.js new file mode 100644 index 000000000000..389f5d99d3b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-missing.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when smallestUnit option is missing +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +assert.throws(TypeError, () => plainTime.round()); +assert.throws(RangeError, () => plainTime.round({})); +assert.throws(RangeError, () => plainTime.round({ roundingIncrement: 1, roundingMode: "ceil" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..524ce45ca5f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => time.round({ smallestUnit }), validUnits); +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => time.round(smallestUnit), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-string-shorthand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-string-shorthand.js new file mode 100644 index 000000000000..803dab893351 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-string-shorthand.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: String as first argument is equivalent to options bag with smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +validUnits.forEach((smallestUnit) => { + const full = instance.round({ smallestUnit }); + const shorthand = instance.round(smallestUnit); + TemporalHelpers.assertPlainTimesEqual(shorthand, full, `"${smallestUnit}" as first argument to round is equivalent to options bag`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-wrong-type.js new file mode 100644 index 000000000000..0b68fac1fa93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => time.round({ smallestUnit }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 123, 988, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/subclassing-ignored.js new file mode 100644 index 000000000000..b903a2b7c77a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainTime, + [12, 34, 56, 987, 654, 321], + "round", + [{ smallestUnit: 'second' }], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 57, 0, 0, 0), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/prop-desc.js new file mode 100644 index 000000000000..071c2436e41a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.second +description: The "second" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "second"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-cast.js new file mode 100644 index 000000000000..7f851b1f70bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-cast.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Casts the argument +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertDuration(plainTime.since("16:34"), + 0, 0, 0, 0, /* hours = */ -1, /* minutes = */ -10, /* seconds = */ -29, -876, -543, -211, "string"); +TemporalHelpers.assertDuration(plainTime.since({ hour: 16, minute: 34 }), + 0, 0, 0, 0, /* hours = */ -1, /* minutes = */ -10, /* seconds = */ -29, -876, -543, -211, "object"); + +assert.throws(TypeError, () => plainTime.since({}), "empty"); +assert.throws(TypeError, () => plainTime.since({ minutes: 30 }), "only plural 'minutes'"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..eb168cbd6b34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +assert.throws( + RangeError, + () => instance.since(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..307d3974f7d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.since(arg), + `${string} is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.since(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.since(arg), + 'space is not accepted as a substitute for T prefix' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => instance.since(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-time-designator.js new file mode 100644 index 000000000000..267656fcb592 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-time-designator.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(1, 0, 0, 0, 0, 1); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.since(arg); + TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 30, 0, 0, 0, 1, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..744bbec39a3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..fbde74a95556 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaintime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const diff = new Temporal.PlainTime().since(datetime); + +TemporalHelpers.assertDuration(diff, 0, 0, 0, 0, -1, -1, -1, -1, 0, -999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..64800bf4dd62 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainTime(15); +const result = instance.since(datetime); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, -1, -50, -35, 0, 0, -1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..ec4f41496cea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..0a612be57d34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.since(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..77f66bdc6328 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..43c42b4a0a39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js new file mode 100644 index 000000000000..94e93652dae6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal.plaintime.prototype.since step 12: + 12. Let _result_ be ! DifferenceTime(_other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); + +const result1 = time.since(new Temporal.PlainTime(0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = time.since(new Temporal.PlainTime(0, 0, 0, 0, 2)); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = time.since(new Temporal.PlainTime(0, 0, 0, 2)); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = time.since(new Temporal.PlainTime(0, 0, 2)); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = time.since(new Temporal.PlainTime(0, 2)); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = time.since(new Temporal.PlainTime(2)); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/basic.js new file mode 100644 index 000000000000..00e78a3a8933 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/basic.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Basic usage +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const one = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const two = new Temporal.PlainTime(14, 23, 30, 123, 456, 789); +const three = new Temporal.PlainTime(13, 30, 30, 123, 456, 789); + +TemporalHelpers.assertDuration(one.since(two), + 0, 0, 0, 0, /* hours = */ 1, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(two.since(one), + 0, 0, 0, 0, /* hours = */ -1, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(one.since(three), + 0, 0, 0, 0, /* hours = */ 1, 53, 0, 0, 0, 0); +TemporalHelpers.assertDuration(three.since(one), + 0, 0, 0, 0, /* hours = */ -1, -53, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/builtin.js new file mode 100644 index 000000000000..b7d0c5a19012 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: > + Tests that Temporal.PlainTime.prototype.since + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.since), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.since), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.since), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.since.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/calendar-temporal-object.js new file mode 100644 index 000000000000..2e0d8c9efb91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/calendar-temporal-object.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => time.since({ hour: 12, minute: 30, calendar: temporalObject })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js new file mode 100644 index 000000000000..8bc3b4c89688 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..fb0480e73be9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => later.since(earlier, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..d7619bf6503b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +const units = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => later.since(earlier, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-undefined.js new file mode 100644 index 000000000000..c4322453f2dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); + +const explicit = later.since(earlier, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-wrong-type.js new file mode 100644 index 000000000000..3cbe135c6281 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "second", + (largestUnit) => later.since(earlier, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 3661, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit.js new file mode 100644 index 000000000000..7ed94eca9b2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: PlainTime.since with various largestUnit values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ +const fourFortyEight = new Temporal.PlainTime(4, 48, 55); +const elevenFiftyNine = new Temporal.PlainTime(11, 59, 58); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, 'does not include higher units than necessary (largest unit unspecified)'); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight, { largestUnit: 'auto' }), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, 'does not include higher units than necessary (largest unit is auto)'); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight, { largestUnit: 'hours' }), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, 'does not include higher units than necessary (largest unit is hours)'); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight, { largestUnit: 'minutes' }), 0, 0, 0, 0, 0, 431, 3, 0, 0, 0, 'does not include higher units than necessary (largest unit is minutes)'); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight, { largestUnit: 'seconds' }), 0, 0, 0, 0, 0, 0, 25863, 0, 0, 0, 'does not include higher units than necessary (largest unit is seconds)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/length.js new file mode 100644 index 000000000000..e1a665f4a98d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Temporal.PlainTime.prototype.since.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.since, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/name.js new file mode 100644 index 000000000000..a6f787515ca2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Temporal.PlainTime.prototype.since.name is "since". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.since, "name", { + value: "since", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/not-a-constructor.js new file mode 100644 index 000000000000..e12fd8bfcf93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: > + Temporal.PlainTime.prototype.since does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.since(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.since), false, + "isConstructor(Temporal.PlainTime.prototype.since)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-invalid.js new file mode 100644 index 000000000000..fcab44fb6433 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-invalid.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +const time = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const one = new Temporal.PlainTime(16, 23, 30, 123, 456, 789); + +for (const badOptions of values) { + assert.throws(TypeError, () => time.since(one, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-undefined.js new file mode 100644 index 000000000000..b2a3909319c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(18, 34, 56, 987, 654, 322); + +const explicit = later.since(earlier, undefined); +assert.sameValue(explicit.hours, 6, "default largest unit is hours"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = later.since(earlier); +assert.sameValue(implicit.hours, 6, "default largest unit is hours"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/prop-desc.js new file mode 100644 index 000000000000..abe7123e7a11 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: The "since" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.since, + "function", + "`typeof PlainTime.prototype.since` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "since", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/result-sub-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/result-sub-second.js new file mode 100644 index 000000000000..c8ef9d598003 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/result-sub-second.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Supports sub-second precision +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const time1 = Temporal.PlainTime.from("10:23:15"); +const time2 = Temporal.PlainTime.from("17:15:57.250250250"); + +TemporalHelpers.assertDuration(time2.since(time1, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 24762250, 250, 250, "milliseconds"); + +TemporalHelpers.assertDuration(time2.since(time1, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 0, 24762250250, 250, "microseconds"); + +TemporalHelpers.assertDuration(time2.since(time1, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 0, 0, 24762250250250, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-hours.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-hours.js new file mode 100644 index 000000000000..f51a5f6fd009 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-hours.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 3 }), + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 4 }), + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 6 }), + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 8 }), + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 12 }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "hours"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-invalid.js new file mode 100644 index 000000000000..2d56ee681819 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-invalid.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests roundingIncrement restrictions. +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "hours", roundingIncrement: 11 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "hours", roundingIncrement: 24 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 60 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 60 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 1000 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-microseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-microseconds.js new file mode 100644 index 000000000000..34ba8a576179 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-microseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 865, 196, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 195, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 865, 192, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 865, 190, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 865, 180, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 865, 175, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 865, 160, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 865, 150, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 865, 100, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 865, 125, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-milliseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-milliseconds.js new file mode 100644 index 000000000000..f67c767a573b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-milliseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 860, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 860, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 850, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 840, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 850, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 800, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 750, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 800, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 750, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 500, 0, 0, "milliseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-minutes.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-minutes.js new file mode 100644 index 000000000000..3e445b82a9ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-minutes.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 34, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 3 }), + 0, 0, 0, 0, 10, 33, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 32, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 6 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 12 }), + 0, 0, 0, 0, 10, 24, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 15 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 20, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 30 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nan.js new file mode 100644 index 000000000000..8b3a65361656 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nanoseconds.js new file mode 100644 index 000000000000..e88b145a0799 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nanoseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 533, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 530, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 528, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 530, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 520, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 525, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 520, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 400, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-non-integer.js new file mode 100644 index 000000000000..58e9f670ad91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +const result = later.since(earlier, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..dfcdf5505e78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -1 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 0 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-seconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-seconds.js new file mode 100644 index 000000000000..5c229501a2f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-seconds.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 22, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 3 }), + 0, 0, 0, 0, 10, 35, 21, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 6 }), + 0, 0, 0, 0, 10, 35, 18, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 12 }), + 0, 0, 0, 0, 10, 35, 12, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 15 }), + 0, 0, 0, 0, 10, 35, 15, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 30 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "seconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-undefined.js new file mode 100644 index 000000000000..18e6f45ccde1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); + +const explicit = later.since(earlier, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..df2cc5a4615c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => later.since(earlier, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-ceil.js new file mode 100644 index 000000000000..9c3bdee14d30 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-ceil.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingMode: "ceil" }), + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "hours", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 18, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "minutes", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 17, 5, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "seconds", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 17, 4, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "milliseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 17, 4, 864, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "microseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "nanoseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-floor.js new file mode 100644 index 000000000000..0a0a05e34130 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-floor.js @@ -0,0 +1,58 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "hours", roundingMode: "floor" }), + 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "minutes", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -18, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "seconds", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -17, -5, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "milliseconds", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -17, -4, -865, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "microseconds", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -17, -4, -864, -198, 0, "microseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "nanoseconds", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfExpand.js new file mode 100644 index 000000000000..a77802497feb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfExpand.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "hours", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "minutes", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 5, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "seconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, -5, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "milliseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 4, 864, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "microseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, -4, -864, -198, 0, "microseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "nanoseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js new file mode 100644 index 000000000000..57629e65466c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-trunc.js new file mode 100644 index 000000000000..df602da454e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-trunc.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "hours", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "minutes", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "seconds", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "milliseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "microseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "nanoseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-undefined.js new file mode 100644 index 000000000000..12148d8a5242 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-undefined.js @@ -0,0 +1,93 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingMode: undefined }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "hours", roundingMode: undefined }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "hours" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "minutes", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "minutes" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds" }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "seconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "seconds" }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "milliseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "milliseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "microseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "microseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "nanoseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "nanoseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-wrong-type.js new file mode 100644 index 000000000000..3c55d28bc479 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js new file mode 100644 index 000000000000..cae946d1569f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..7d346ef74d2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => later.since(earlier, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-undefined.js new file mode 100644 index 000000000000..f5095ffddf0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); + +const explicit = later.since(earlier, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const lambda = later.since(earlier, () => {}); +TemporalHelpers.assertDuration(lambda, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-wrong-type.js new file mode 100644 index 000000000000..9ad775290918 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => later.since(earlier, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/year-zero.js new file mode 100644 index 000000000000..d79f1cde682b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-12-07T03:24:30', + '-000000-12-07T03:24:30+01:00[UTC]' +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration.js new file mode 100644 index 000000000000..d8b5bd7a94fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Duration arguments are supported. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const duration = Temporal.Duration.from("PT16H"); +TemporalHelpers.assertPlainTime(plainTime.subtract(duration), + 23, 23, 30, 123, 456, 789); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-higher-units.js new file mode 100644 index 000000000000..8b42d39033c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-higher-units.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Higher units are ignored. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const values = [ + new Temporal.Duration(0, 0, 0, 1), + new Temporal.Duration(0, 0, 1), + new Temporal.Duration(0, 1), + new Temporal.Duration(1), + { days: 1 }, + { weeks: 1 }, + { months: 1 }, + { years: 1 }, + "P1D", + "P1W", + "P1M", + "P1Y", +]; +for (const value of values) { + TemporalHelpers.assertPlainTime(plainTime.subtract(value), + 15, 23, 30, 123, 456, 789); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-not-object.js new file mode 100644 index 000000000000..a63ff7cb486c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Passing a primitive other than string to subtract() throws +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +assert.throws(RangeError, () => instance.subtract(undefined), "undefined"); +assert.throws(RangeError, () => instance.subtract(null), "null"); +assert.throws(RangeError, () => instance.subtract(true), "boolean"); +assert.throws(RangeError, () => instance.subtract(""), "empty string"); +assert.throws(TypeError, () => instance.subtract(Symbol()), "Symbol"); +assert.throws(RangeError, () => instance.subtract(7), "number"); +assert.throws(RangeError, () => instance.subtract(7n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object-invalid.js new file mode 100644 index 000000000000..8bcce753382a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Mixed positive and negative values or missing properties always throw +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +assert.throws(RangeError, () => plainTime.subtract({ hours: 1, minutes: -6 }), "mixed signs"); +assert.throws(TypeError, () => plainTime.subtract({}), "no properties"); +assert.throws(TypeError, () => plainTime.subtract({ hour: 12 }), "only singular 'hour' property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object.js new file mode 100644 index 000000000000..d21ddb9ce81e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Plain object arguments are supported. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.subtract({ hours: 16 }), + 23, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.subtract({ minutes: 45 }), + 14, 38, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.subtract({ seconds: 45 }), + 15, 22, 45, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.subtract({ milliseconds: 800 }), + 15, 23, 29, 323, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.subtract({ microseconds: 800 }), + 15, 23, 30, 122, 656, 789); +TemporalHelpers.assertPlainTime(plainTime.subtract({ nanoseconds: 800 }), + 15, 23, 30, 123, 455, 989); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("23:23:30.123456789").subtract({ hours: -16 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("14:38:30.123456789").subtract({ minutes: -45 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:22:45.123456789").subtract({ seconds: -45 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:29.323456789").subtract({ milliseconds: -800 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.122656789").subtract({ microseconds: -800 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.123455989").subtract({ nanoseconds: -800 }), + 15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.subtract({ minute: 1, hours: 1 }), + 14, 23, 30, 123, 456, 789); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..f1ce3233a6c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const midnight = new Temporal.PlainTime(); + +TemporalHelpers.assertPlainTime(midnight.subtract("PT1.03125H"), 22, 58, 7, 500, 0, 0, + "positive fractional units rounded with correct rounding mode"); +TemporalHelpers.assertPlainTime(midnight.subtract("-PT1.03125H"), 1, 1, 52, 500, 0, 0, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..8f4ad1b8b3d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const resultHours = instance.subtract("-PT24.567890123H"); +TemporalHelpers.assertPlainTime(resultHours, 0, 34, 4, 404, 442, 799, "negative fractional hours"); + +const resultMinutes = instance.subtract("-PT1440.567890123M"); +TemporalHelpers.assertPlainTime(resultMinutes, 0, 0, 34, 73, 407, 379, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string.js new file mode 100644 index 000000000000..62ddb4c104da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +const result = instance.subtract("PT3M"); +TemporalHelpers.assertPlainTime(result, 12, 31, 56, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/balance-negative-time-units.js new file mode 100644 index 000000000000..1c90b59d0cf9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/balance-negative-time-units.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal.plaintime.prototype.subtract step 4: + 4. Let _result_ be ? AddTime(_temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); + +const result1 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result1, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result2, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result3, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result4, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result5, 0, 59, 1, 1, 1, 1, "minutes balance"); + +const result6 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result6, 23, 1, 1, 1, 1, 1, "hours mod 24"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/builtin.js new file mode 100644 index 000000000000..f4a8ed4d0da0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: > + Tests that Temporal.PlainTime.prototype.subtract + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.subtract), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.subtract), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.subtract), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.subtract.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..9fae515bab8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime.prototype.subtract throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plaintime.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/length.js new file mode 100644 index 000000000000..6d47aa47211e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Temporal.PlainTime.prototype.subtract.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.subtract, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/name.js new file mode 100644 index 000000000000..86a3d576ebd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Temporal.PlainTime.prototype.subtract.name is "subtract". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.subtract, "name", { + value: "subtract", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..5e7bc884fb88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime.prototype.subtract throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plaintime.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..be17682d2cf9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.subtract({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/not-a-constructor.js new file mode 100644 index 000000000000..072da559c41d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: > + Temporal.PlainTime.prototype.subtract does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.subtract(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.subtract), false, + "isConstructor(Temporal.PlainTime.prototype.subtract)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/options-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/options-ignored.js new file mode 100644 index 000000000000..98590abaee24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/options-ignored.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Options argument is ignored. +includes: [temporalHelpers.js] +features: [Symbol, Temporal] +---*/ + +const values = [ + undefined, + null, + true, + "hello", + Symbol("foo"), + 1, + 1n, + {}, + () => {}, + { get overflow() { throw new Test262Error("should not get overflow") } }, +]; + +const time = Temporal.PlainTime.from("15:23:30.123456789"); +for (const options of values) { + TemporalHelpers.assertPlainTime(time.subtract({ hours: 1 }, options), + 14, 23, 30, 123, 456, 789); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/order-of-operations.js new file mode 100644 index 000000000000..e499c0a3aca2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Properties on an object passed to subtract() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.subtract(argument); +TemporalHelpers.assertPlainTime(result, 11, 33, 55, 986, 653, 320); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/prop-desc.js new file mode 100644 index 000000000000..edda251cf840 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: The "subtract" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.subtract, + "function", + "`typeof PlainTime.prototype.subtract` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "subtract", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/subclassing-ignored.js new file mode 100644 index 000000000000..3cf8dc52a903 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Objects of a subclass are never created as return values for subtract() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainTime, + [12, 34, 56, 987, 654, 321], + "subtract", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 320), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..64b83f935850 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: > + Tests that Temporal.PlainTime.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/length.js new file mode 100644 index 000000000000..a1fa8b2e3c9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: Temporal.PlainTime.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/name.js new file mode 100644 index 000000000000..d900bcd5bc7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: Temporal.PlainTime.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..3aaff59047d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: > + Temporal.PlainTime.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toJSON), false, + "isConstructor(Temporal.PlainTime.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..d9a41bfcf39a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: The "toJSON" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toJSON, + "function", + "`typeof PlainTime.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/builtin.js new file mode 100644 index 000000000000..e6af716c699d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: > + Tests that Temporal.PlainTime.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/length.js new file mode 100644 index 000000000000..626a8f7207e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: Temporal.PlainTime.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/name.js new file mode 100644 index 000000000000..cd6f7bd90418 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: Temporal.PlainTime.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 000000000000..4f5fd664fb42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: > + Temporal.PlainTime.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toLocaleString), false, + "isConstructor(Temporal.PlainTime.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/prop-desc.js new file mode 100644 index 000000000000..febb8c707cee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toLocaleString, + "function", + "`typeof PlainTime.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string.js new file mode 100644 index 000000000000..1ea5af8ba9b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: > + toLocaleString return a string. +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.sameValue(typeof time.toLocaleString("en", { timeStyle: "short" }), "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-plaindatetime.js new file mode 100644 index 000000000000..55cd85850a2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-plaindatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.toplaindatetime +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaintime.prototype.toplaindatetime step 3: + 3. Set _temporalDate_ to ? ToTemporalDate(_temporalDate_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const time = new Temporal.PlainTime(6, 54, 32, 123, 456, 789); + const result = time.toPlainDateTime(datetime); + TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 6, 54, 32, 123, 456, 789); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js new file mode 100644 index 000000000000..cf1c22603498 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..123e4e10af65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..868f43cc76e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..965ea631461f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.toPlainDateTime(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..49cd26bb5b09 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..3fb6bebbba60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/basic.js new file mode 100644 index 000000000000..309c26fee5e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/basic.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.toplaindatetime +description: Basic tests for toPlainDateTime(). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("11:30:23.123456789"); + +const plainDate = plainTime.toPlainDateTime(Temporal.PlainDate.from("1976-11-18")); +TemporalHelpers.assertPlainDateTime(plainDate, 1976, 11, "M11", 18, 11, 30, 23, 123, 456, 789, "PlainDate"); + +const optionBag = plainTime.toPlainDateTime({ year: 1976, month: 11, day: 18 }); +TemporalHelpers.assertPlainDateTime(optionBag, 1976, 11, "M11", 18, 11, 30, 23, 123, 456, 789, "option bag"); + +const string = plainTime.toPlainDateTime("1976-11-18"); +TemporalHelpers.assertPlainDateTime(string, 1976, 11, "M11", 18, 11, 30, 23, 123, 456, 789, "string"); + +assert.throws(TypeError, () => plainTime.toPlainDateTime({ year: 1976 }), "missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/builtin.js new file mode 100644 index 000000000000..f463135fb4d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Tests that Temporal.PlainTime.prototype.toPlainDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toPlainDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toPlainDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toPlainDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toPlainDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..e1ac31f5e6fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321, calendar); +instance.toPlainDateTime({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-fields-iterable.js new file mode 100644 index 000000000000..8a1896b1ca09 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-fields-iterable.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaintime.prototype.toplaindatetime step 3: + 3. Set _temporalDate_ to ? ToTemporalDate(_temporalDate_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const time = new Temporal.PlainTime(13, 3); +const calendar = TemporalHelpers.calendarFieldsIterable(); +time.toPlainDateTime({ year: 2000, month: 5, day: 3, calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-temporal-object.js new file mode 100644 index 000000000000..455d7f2d7bda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.prototype.toplaindatetime step 3: + 3. Set _temporalDate_ to ? ToTemporalDate(_temporalDate_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const time = new Temporal.PlainTime(13, 3); + const result = time.toPlainDateTime({ year: 2000, month: 5, day: 3, calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..5b0c37fe2bf9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.toplaindatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.toPlainDateTime({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.toPlainDateTime({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/length.js new file mode 100644 index 000000000000..7d480f399355 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Temporal.PlainTime.prototype.toPlainDateTime.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toPlainDateTime, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/name.js new file mode 100644 index 000000000000..0b2ee2262e4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Temporal.PlainTime.prototype.toPlainDateTime.name is "toPlainDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toPlainDateTime, "name", { + value: "toPlainDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/not-a-constructor.js new file mode 100644 index 000000000000..feab75d01cde --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Temporal.PlainTime.prototype.toPlainDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toPlainDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toPlainDateTime), false, + "isConstructor(Temporal.PlainTime.prototype.toPlainDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/prop-desc.js new file mode 100644 index 000000000000..f5259bcc890c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: The "toPlainDateTime" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toPlainDateTime, + "function", + "`typeof PlainTime.prototype.toPlainDateTime` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toPlainDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/year-zero.js new file mode 100644 index 000000000000..953e60032744 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws( + RangeError, + () => { instance.toPlainDateTime(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/basic.js new file mode 100644 index 000000000000..9f7b7d56d3cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/basic.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Basic tests for toString() +features: [Temporal] +---*/ + +assert.sameValue(new Temporal.PlainTime(15, 23).toString(), "15:23:00"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30).toString(), "15:23:30"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30, 123).toString(), "15:23:30.123"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30, 123, 400).toString(), "15:23:30.1234"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30, 123, 456).toString(), "15:23:30.123456"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30, 123, 456, 789).toString(), "15:23:30.123456789"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/builtin.js new file mode 100644 index 000000000000..3181b5fbb3ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: > + Tests that Temporal.PlainTime.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js new file mode 100644 index 000000000000..5ff6358d240e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: auto value for fractionalSecondDigits option +features: [Temporal] +---*/ + +const tests = [ + ["15:23", "15:23:00"], + ["15:23:30", "15:23:30"], + ["15:23:30.1234", "15:23:30.1234"], +]; + +for (const [input, expected] of tests) { + const plainTime = Temporal.PlainTime.from(input); + assert.sameValue(plainTime.toString({ fractionalSecondDigits: "auto" }), expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js new file mode 100644 index 000000000000..6d6e33846183 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values +info: | + sec-getstringornumberoption step 4: + 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaintime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); + +for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos"]) { + assert.throws(RangeError, () => time.toString({ fractionalSecondDigits })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan.js new file mode 100644 index 000000000000..10322e548eff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaintime.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js new file mode 100644 index 000000000000..39677ed913ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Rounding for fractionalSecondDigits option +info: | + sec-getstringornumberoption step 3.b: + b. Return floor(ℝ(_value_)). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaintime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); + +const string = time.toString({ fractionalSecondDigits: 2.5 }); +assert.sameValue(string, "12:34:56.98", "fractionalSecondDigits 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js new file mode 100644 index 000000000000..2564bedfea06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Number for fractionalSecondDigits option +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("15:23"); +const t2 = Temporal.PlainTime.from("15:23:30"); +const t3 = Temporal.PlainTime.from("15:23:30.1234"); +assert.sameValue(t3.toString({ fractionalSecondDigits: 0 }), "15:23:30"); +assert.sameValue(t1.toString({ fractionalSecondDigits: 2 }), "15:23:00.00"); +assert.sameValue(t2.toString({ fractionalSecondDigits: 2 }), "15:23:30.00"); +assert.sameValue(t3.toString({ fractionalSecondDigits: 2 }), "15:23:30.12"); +assert.sameValue(t3.toString({ fractionalSecondDigits: 3 }), "15:23:30.123"); +assert.sameValue(t3.toString({ fractionalSecondDigits: 6 }), "15:23:30.123400"); +assert.sameValue(t1.toString({ fractionalSecondDigits: 7 }), "15:23:00.0000000"); +assert.sameValue(t2.toString({ fractionalSecondDigits: 7 }), "15:23:30.0000000"); +assert.sameValue(t3.toString({ fractionalSecondDigits: 7 }), "15:23:30.1234000"); +assert.sameValue(t3.toString({ fractionalSecondDigits: 9 }), "15:23:30.123400000"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js new file mode 100644 index 000000000000..89d198c1a152 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option out of range +info: | + sec-getstringornumberoption step 3.a: + a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaintime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); + +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: -Infinity })); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: -1 })); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: 10 })); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js new file mode 100644 index 000000000000..216d78438157 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Fallback value for fractionalSecondDigits option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaintime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const tests = [ + ["15:23", "15:23:00"], + ["15:23:30", "15:23:30"], + ["15:23:30.1234", "15:23:30.1234"], +]; + +for (const [input, expected] of tests) { + const time = Temporal.PlainTime.from(input); + + const explicit = time.toString({ fractionalSecondDigits: undefined }); + assert.sameValue(explicit, expected, "default fractionalSecondDigits is auto"); + + const implicit = time.toString({}); + assert.sameValue(implicit, expected, "default fractionalSecondDigits is auto"); + + const lambda = time.toString(() => {}); + assert.sameValue(lambda, expected, "default fractionalSecondDigits is auto"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js new file mode 100644 index 000000000000..9c3dec82eb14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Type conversions for fractionalSecondDigits option +info: | + sec-getoption steps 8–9: + 8. Else if _type_ is Number, then + a. Set _value_ to ? ToNumber(value). + b. ... + 9. Else, + a. Set _value_ to ? ToString(value). + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.plaintime.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); +TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(time); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/length.js new file mode 100644 index 000000000000..6cec08483426 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Temporal.PlainTime.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/name.js new file mode 100644 index 000000000000..779870e99c22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Temporal.PlainTime.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..63cbd85a1726 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: > + Temporal.PlainTime.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toString), false, + "isConstructor(Temporal.PlainTime.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-invalid.js new file mode 100644 index 000000000000..369e679f35c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-invalid.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const instance = Temporal.PlainTime.from("12:56:32"); +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; + +for (const badOptions of values) { + assert.throws(TypeError, () => instance.toString(badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-undefined.js new file mode 100644 index 000000000000..bf5e2f9e02e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const tests = [ + ["15:23", "15:23:00"], + ["15:23:30", "15:23:30"], + ["15:23:30.1234", "15:23:30.1234"], +]; + +for (const [input, expected] of tests) { + const time = Temporal.PlainTime.from(input); + + const explicit = time.toString(undefined); + assert.sameValue(explicit, expected, "default precision is auto and no rounding"); + + const implicit = time.toString(); + assert.sameValue(implicit, expected, "default precision is auto and no rounding"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..483fac8d9eb4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: The "toString" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toString, + "function", + "`typeof PlainTime.prototype.toString` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js new file mode 100644 index 000000000000..34a879298786 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Rounding can cross midnight +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("23:59:59.999999999"); +for (const roundingMode of ["ceil", "halfExpand"]) { + assert.sameValue(plainTime.toString({ fractionalSecondDigits: 8, roundingMode }), "00:00:00.00000000"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js new file mode 100644 index 000000000000..70a304f979dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: ceil value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "ceil" }); +assert.sameValue(result1, "12:34:56.123988", "roundingMode is ceil"); + +const result2 = time.toString({ smallestUnit: "millisecond", roundingMode: "ceil" }); +assert.sameValue(result2, "12:34:56.124", "roundingMode is ceil"); + +const result3 = time.toString({ smallestUnit: "second", roundingMode: "ceil" }); +assert.sameValue(result3, "12:34:57", "roundingMode is ceil"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js new file mode 100644 index 000000000000..e8f38a6c009a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: floor value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "floor" }); +assert.sameValue(result1, "12:34:56.123987", "roundingMode is floor"); + +const result2 = time.toString({ smallestUnit: "millisecond", roundingMode: "floor" }); +assert.sameValue(result2, "12:34:56.123", "roundingMode is floor"); + +const result3 = time.toString({ smallestUnit: "second", roundingMode: "floor" }); +assert.sameValue(result3, "12:34:56", "roundingMode is floor"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js new file mode 100644 index 000000000000..70ad19dc10a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: halfExpand value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "halfExpand" }); +assert.sameValue(result1, "12:34:56.123988", "roundingMode is halfExpand"); + +const result2 = time.toString({ smallestUnit: "millisecond", roundingMode: "halfExpand" }); +assert.sameValue(result2, "12:34:56.124", "roundingMode is halfExpand"); + +const result3 = time.toString({ smallestUnit: "second", roundingMode: "halfExpand" }); +assert.sameValue(result3, "12:34:56", "roundingMode is halfExpand"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js new file mode 100644 index 000000000000..fc54b131f008 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => time.toString({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js new file mode 100644 index 000000000000..ab2dcfcc9283 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: trunc value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "trunc" }); +assert.sameValue(result1, "12:34:56.123987", "roundingMode is trunc"); + +const result2 = time.toString({ smallestUnit: "millisecond", roundingMode: "trunc" }); +assert.sameValue(result2, "12:34:56.123", "roundingMode is trunc"); + +const result3 = time.toString({ smallestUnit: "second", roundingMode: "trunc" }); +assert.sameValue(result3, "12:34:56", "roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-undefined.js new file mode 100644 index 000000000000..6ec201a3b8fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Fallback value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const explicit1 = time.toString({ smallestUnit: "microsecond", roundingMode: undefined }); +assert.sameValue(explicit1, "12:34:56.123987", "default roundingMode is trunc"); +const implicit1 = time.toString({ smallestUnit: "microsecond" }); +assert.sameValue(implicit1, "12:34:56.123987", "default roundingMode is trunc"); + +const explicit2 = time.toString({ smallestUnit: "millisecond", roundingMode: undefined }); +assert.sameValue(explicit2, "12:34:56.123", "default roundingMode is trunc"); +const implicit2 = time.toString({ smallestUnit: "millisecond" }); +assert.sameValue(implicit2, "12:34:56.123", "default roundingMode is trunc"); + +const explicit3 = time.toString({ smallestUnit: "second", roundingMode: undefined }); +assert.sameValue(explicit3, "12:34:56", "default roundingMode is trunc"); +const implicit3 = time.toString({ smallestUnit: "second" }); +assert.sameValue(implicit3, "12:34:56", "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-wrong-type.js new file mode 100644 index 000000000000..47bef2495c5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => time.toString({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => assert.sameValue(result, "12:34:56.123987", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js new file mode 100644 index 000000000000..32b4161fde2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: fractionalSecondDigits option is not used with smallestUnit present +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const tests = [ + ["minute", "12:34"], + ["second", "12:34:56"], + ["millisecond", "12:34:56.789"], + ["microsecond", "12:34:56.789999"], + ["nanosecond", "12:34:56.789999999"], +]; + +for (const [smallestUnit, expected] of tests) { + const string = time.toString({ + smallestUnit, + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } + }); + assert.sameValue(string, expected, smallestUnit); +} + +assert.throws(RangeError, () => time.toString({ + smallestUnit: "hour", + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } +})); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js new file mode 100644 index 000000000000..695b867608b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +for (const smallestUnit of ["era", "year", "month", "day", "hour", "nonsense", "other string", "m\u0131nute", "SECOND"]) { + assert.throws(RangeError, () => time.toString({ smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..4be152fae9f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const validUnits = [ + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => time.toString({ smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-undefined.js new file mode 100644 index 000000000000..3822faf567c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-undefined.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Fallback value for smallestUnit option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const explicit1 = time.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 }); +assert.sameValue(explicit1, "12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits"); +const implicit1 = time.toString({ fractionalSecondDigits: 6 }); +assert.sameValue(implicit1, "12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits"); + +const explicit2 = time.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 }); +assert.sameValue(explicit2, "12:34:56.123", "default smallestUnit defers to fractionalSecondDigits"); +const implicit2 = time.toString({ fractionalSecondDigits: 3 }); +assert.sameValue(implicit2, "12:34:56.123", "default smallestUnit defers to fractionalSecondDigits"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js new file mode 100644 index 000000000000..e899c4e8148a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Valid units for the smallestUnit option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +assert.sameValue(time.toString({ smallestUnit: "minute" }), "12:34"); +assert.sameValue(time.toString({ smallestUnit: "second" }), "12:34:56"); +assert.sameValue(time.toString({ smallestUnit: "millisecond" }), "12:34:56.789"); +assert.sameValue(time.toString({ smallestUnit: "microsecond" }), "12:34:56.789999"); +assert.sameValue(time.toString({ smallestUnit: "nanosecond" }), "12:34:56.789999999"); + +const time2 = new Temporal.PlainTime(12, 34); +assert.sameValue(time2.toString({ smallestUnit: "minute" }), "12:34"); +assert.sameValue(time2.toString({ smallestUnit: "second" }), "12:34:00"); +assert.sameValue(time2.toString({ smallestUnit: "millisecond" }), "12:34:00.000"); +assert.sameValue(time2.toString({ smallestUnit: "microsecond" }), "12:34:00.000000"); +assert.sameValue(time2.toString({ smallestUnit: "nanosecond" }), "12:34:00.000000000"); + +const notValid = [ + "year", + "month", + "week", + "day", + "hour", +]; + +notValid.forEach((smallestUnit) => { + assert.throws(RangeError, () => time.toString({ smallestUnit }), smallestUnit); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-wrong-type.js new file mode 100644 index 000000000000..777877c8bba1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => time.toString({ smallestUnit }), + (result, descr) => assert.sameValue(result, "12:34:56.123987", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-plaindatetime.js new file mode 100644 index 000000000000..fd674c47017d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-plaindatetime.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.tozoneddatetime +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 5: + 5. Let _temporalDate_ be ? ToTemporalDate(_temporalDateLike_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const time = new Temporal.PlainTime(6, 54, 32, 123, 456, 789); + const result = time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" }); + assert.sameValue(result.year, 2000, "year result"); + assert.sameValue(result.month, 5, "month result"); + assert.sameValue(result.day, 2, "day result"); + assert.sameValue(result.hour, 6, "hour result"); + assert.sameValue(result.minute, 54, "minute result"); + assert.sameValue(result.second, 32, "second result"); + assert.sameValue(result.millisecond, 123, "millisecond result"); + assert.sameValue(result.microsecond, 456, "microsecond result"); + assert.sameValue(result.nanosecond, 789, "nanosecond result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-primitive.js new file mode 100644 index 000000000000..7b7b3cddc6b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-primitive.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.tozoneddatetime +description: TypeError thrown if a primitive is passed as the argument +info: | + Temporal.PlainTime.prototype.toZonedDateTime ( item ) + + 3. If Type(item) is not Object, then + a. Throw a TypeError exception. +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainTime.from("00:00"); + +assert.throws(TypeError, () => instance.toZonedDateTime(undefined), "undefined"); +assert.throws(TypeError, () => instance.toZonedDateTime(null), "null"); +assert.throws(TypeError, () => instance.toZonedDateTime(true), "true"); +assert.throws(TypeError, () => instance.toZonedDateTime(""), "empty string"); +assert.throws(TypeError, () => instance.toZonedDateTime(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.toZonedDateTime(1), "1"); +assert.throws(TypeError, () => instance.toZonedDateTime(1n), "1n"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js new file mode 100644 index 000000000000..32d184877c2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg }), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..cacb2fbf2810 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg }), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..79c1bf10beec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..e2bece3a1eaa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..0bfb99450544 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..f1756d94b457 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/basic.js new file mode 100644 index 000000000000..63c7b643b791 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/basic.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.tozoneddatetime +description: Basic tests for toZonedDateTime(). +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from('12:00'); +const plainDate = Temporal.PlainDate.from('2020-07-08'); +const timeZone = Temporal.TimeZone.from('-07:00'); + +const objects = plainTime.toZonedDateTime({ timeZone, plainDate }); +assert.sameValue(objects.epochNanoseconds, 1594234800000000000n, "objects: epochNanoseconds"); +assert.sameValue(objects.timeZone, timeZone, "objects: timeZone"); + +const timeZoneString = plainTime.toZonedDateTime({ timeZone: "-07:00", plainDate }); +assert.sameValue(timeZoneString.epochNanoseconds, 1594234800000000000n, "timeZone string: epochNanoseconds"); +assert.sameValue(timeZoneString.timeZone.id, "-07:00", "timeZone string: timeZone"); + +const plainDateString = plainTime.toZonedDateTime({ timeZone, plainDate: "2020-07-08" }); +assert.sameValue(plainDateString.epochNanoseconds, 1594234800000000000n, "plainDate string: epochNanoseconds"); +assert.sameValue(plainDateString.timeZone.id, "-07:00", "plainDate string: timeZone"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/builtin.js new file mode 100644 index 000000000000..ea480e24331e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Tests that Temporal.PlainTime.prototype.toZonedDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toZonedDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toZonedDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toZonedDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toZonedDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..edcc4dc3150f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.PlainTime(); +instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(1970, 1, 1, calendar), timeZone }); +assert.sameValue(calendar.dateAddCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..187323860d1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321, calendar); +instance.toZonedDateTime({ plainDate: { year: 2000, month: 5, day: 3, calendar }, timeZone: new Temporal.TimeZone("UTC") }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-fields-iterable.js new file mode 100644 index 000000000000..b96686f5db24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-fields-iterable.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 5: + 3. Let _temporalDate_ be ? ToTemporalDate(_temporalDateLike_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const time = new Temporal.PlainTime(13, 3); +const calendar = TemporalHelpers.calendarFieldsIterable(); +time.toZonedDateTime({ plainDate: { year: 2000, month: 5, day: 3, calendar }, timeZone: "UTC" }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-temporal-object.js new file mode 100644 index 000000000000..1097b3f143e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 5: + 5. Let _temporalDate_ be ? ToTemporalDate(_temporalDateLike_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const time = new Temporal.PlainTime(13, 3); + const result = time.toZonedDateTime({ timeZone: "UTC", plainDate: { year: 2000, month: 5, day: 3, calendar: temporalObject } }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..e47eaaa99ae8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.tozoneddatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/length.js new file mode 100644 index 000000000000..231e5cd87754 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Temporal.PlainTime.prototype.toZonedDateTime.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toZonedDateTime, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/name.js new file mode 100644 index 000000000000..ff102582d9da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Temporal.PlainTime.prototype.toZonedDateTime.name is "toZonedDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toZonedDateTime, "name", { + value: "toZonedDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/not-a-constructor.js new file mode 100644 index 000000000000..2009c22bafe1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Temporal.PlainTime.prototype.toZonedDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toZonedDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toZonedDateTime), false, + "isConstructor(Temporal.PlainTime.prototype.toZonedDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..702bbfe6b585 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.tozoneddatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in plainDate`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/prop-desc.js new file mode 100644 index 000000000000..d40ceb75dcee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: The "toZonedDateTime" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toZonedDateTime, + "function", + "`typeof PlainTime.prototype.toZonedDateTime` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toZonedDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..9fc31c7ac232 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const plainDate = new Temporal.PlainDate(2000, 5, 2); + assert.throws(RangeError, () => time.toZonedDateTime({ plainDate, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..c28178934f77 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const plainDate = new Temporal.PlainDate(2000, 5, 2); + timeZone.getPossibleInstantsFor = function () { + return []; + }; + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.toZonedDateTime({ plainDate, timeZone }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..7f6d258c4e58 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const plainDate = new Temporal.PlainDate(2000, 5, 2); + assert.throws(RangeError, () => time.toZonedDateTime({ plainDate, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..775477496f67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const plainDate = new Temporal.PlainDate(2000, 5, 2); + assert.throws(TypeError, () => time.toZonedDateTime({ plainDate, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..80ca4a77ad48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 10: + 10. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "2000-05-02T12:34:56.987654321", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + time.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:30:00", + "2030-01-01T01:30:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const time = new Temporal.PlainTime(0, 30); + time.toZonedDateTime({ plainDate: new Temporal.PlainDate(2030, 1, 1), timeZone }); +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..640a77d5c3e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..d3fe3666e386 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/year-zero.js new file mode 100644 index 000000000000..80535e1bc7a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws( + RangeError, + () => { instance.toZonedDateTime({ plainDate: arg }); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-cast.js new file mode 100644 index 000000000000..4e386255e055 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-cast.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Casts the argument +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertDuration(plainTime.until("16:34"), + 0, 0, 0, 0, /* hours = */ 1, /* minutes = */ 10, /* seconds = */ 29, 876, 543, 211, "string"); +TemporalHelpers.assertDuration(plainTime.until({ hour: 16, minute: 34 }), + 0, 0, 0, 0, /* hours = */ 1, /* minutes = */ 10, /* seconds = */ 29, 876, 543, 211, "object"); + +assert.throws(TypeError, () => plainTime.until({}), "empty"); +assert.throws(TypeError, () => plainTime.until({ minutes: 30 }), "only plural 'minutes'"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..62217c639c56 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +assert.throws( + RangeError, + () => instance.until(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..50df5412fca0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.until(arg), + `${string} is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.until(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.until(arg), + 'space is not accepted as a substitute for T prefix' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => instance.until(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-time-designator.js new file mode 100644 index 000000000000..9e45d7400c76 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-time-designator.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(1, 0, 0, 0, 0, 1); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.until(arg); + TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, -30, 0, 0, 0, -1, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..7fde7180ab90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..0970d70a7ece --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaintime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const diff = new Temporal.PlainTime().until(datetime); + +TemporalHelpers.assertDuration(diff, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..870c32353e10 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainTime(15); +const result = instance.until(datetime); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..6ddbff9658a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..9ff9542c40fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.until(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..6f1d01ff2944 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..b86fba5de51a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js new file mode 100644 index 000000000000..f843b547cfae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal.plaintime.prototype.until step 11: + 11. Let _result_ be ! DifferenceTime(_temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); + +const result1 = new Temporal.PlainTime(0, 0, 0, 0, 0, 2).until(time); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = new Temporal.PlainTime(0, 0, 0, 0, 2).until(time); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = new Temporal.PlainTime(0, 0, 0, 2).until(time); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = new Temporal.PlainTime(0, 0, 2).until(time); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = new Temporal.PlainTime(0, 2).until(time); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = new Temporal.PlainTime(2).until(time); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/basic.js new file mode 100644 index 000000000000..25fcdaf427d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/basic.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Basic usage +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const one = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const two = new Temporal.PlainTime(16, 23, 30, 123, 456, 789); +const three = new Temporal.PlainTime(17, 0, 30, 123, 456, 789); + +TemporalHelpers.assertDuration(one.until(two), + 0, 0, 0, 0, /* hours = */ 1, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(two.until(one), + 0, 0, 0, 0, /* hours = */ -1, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(one.until(three), + 0, 0, 0, 0, /* hours = */ 1, 37, 0, 0, 0, 0); +TemporalHelpers.assertDuration(three.until(one), + 0, 0, 0, 0, /* hours = */ -1, -37, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/builtin.js new file mode 100644 index 000000000000..791d6abf1d78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: > + Tests that Temporal.PlainTime.prototype.until + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.until), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.until), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.until), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.until.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/calendar-temporal-object.js new file mode 100644 index 000000000000..73bd0c05e95e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/calendar-temporal-object.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => time.until({ hour: 12, minute: 30, calendar: temporalObject })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js new file mode 100644 index 000000000000..d5cc7f06aeb6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..9438b68d03fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => earlier.until(later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..a30e4684b533 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +const units = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => earlier.until(later, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-undefined.js new file mode 100644 index 000000000000..6b895c9c82e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); + +const explicit = earlier.until(later, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-wrong-type.js new file mode 100644 index 000000000000..a3afa56d7f6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "second", + (largestUnit) => earlier.until(later, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 3661, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit.js new file mode 100644 index 000000000000..28d07834d873 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: PlainTime.until with various largestUnit values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ +const fourFortyEight = new Temporal.PlainTime(4, 48, 55); +const elevenFiftyNine = new Temporal.PlainTime(11, 59, 58); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, "does not include higher units than necessary (largest unit unspecified)"); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine, { largestUnit: "auto" }), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, "does not include higher units than necessary (largest unit is auto)"); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine, { largestUnit: "hours" }), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, "does not include higher units than necessary (largest unit is hours)"); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine, { largestUnit: "minutes" }), 0, 0, 0, 0, 0, 431, 3, 0, 0, 0, "does not include higher units than necessary (largest unit is minutes)"); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine, { largestUnit: "seconds" }), 0, 0, 0, 0, 0, 0, 25863, 0, 0, 0, "does not include higher units than necessary (largest unit is seconds)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/length.js new file mode 100644 index 000000000000..52df3730c98c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Temporal.PlainTime.prototype.until.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.until, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/name.js new file mode 100644 index 000000000000..ffa71815de2c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Temporal.PlainTime.prototype.until.name is "until". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.until, "name", { + value: "until", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/not-a-constructor.js new file mode 100644 index 000000000000..5b19fde1f28b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: > + Temporal.PlainTime.prototype.until does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.until(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.until), false, + "isConstructor(Temporal.PlainTime.prototype.until)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-invalid.js new file mode 100644 index 000000000000..7f1b6d124aff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-invalid.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +const time = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const one = new Temporal.PlainTime(16, 23, 30, 123, 456, 789); + +for (const badOptions of values) { + assert.throws(TypeError, () => time.until(one, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-undefined.js new file mode 100644 index 000000000000..d0160e162c32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(18, 34, 56, 987, 654, 322); + +const explicit = earlier.until(later, undefined); +assert.sameValue(explicit.hours, 6, "default largest unit is hours"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = earlier.until(later); +assert.sameValue(implicit.hours, 6, "default largest unit is hours"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/prop-desc.js new file mode 100644 index 000000000000..e22bbfa49c6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: The "until" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.until, + "function", + "`typeof PlainTime.prototype.until` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "until", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/result-sub-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/result-sub-second.js new file mode 100644 index 000000000000..4488fb67ebaf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/result-sub-second.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Supports sub-second precision +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const time1 = Temporal.PlainTime.from("10:23:15"); +const time2 = Temporal.PlainTime.from("17:15:57.250250250"); + +TemporalHelpers.assertDuration(time1.until(time2, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 24762250, 250, 250, "milliseconds"); + +TemporalHelpers.assertDuration(time1.until(time2, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 0, 24762250250, 250, "microseconds"); + +TemporalHelpers.assertDuration(time1.until(time2, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 0, 0, 24762250250250, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-hours.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-hours.js new file mode 100644 index 000000000000..23ce813182d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-hours.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 3 }), + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 4 }), + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 6 }), + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 8 }), + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 12 }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "hours"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-invalid.js new file mode 100644 index 000000000000..d24005b1ff14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-invalid.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests roundingIncrement restrictions. +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "hours", roundingIncrement: 11 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "hours", roundingIncrement: 24 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 60 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 60 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 1000 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-microseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-microseconds.js new file mode 100644 index 000000000000..4814ada190ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-microseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 865, 196, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 195, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 865, 192, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 865, 190, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 865, 180, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 865, 175, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 865, 160, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 865, 150, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 865, 100, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 865, 125, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-milliseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-milliseconds.js new file mode 100644 index 000000000000..c9d49c4a0f5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-milliseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 860, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 860, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 850, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 840, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 850, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 800, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 750, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 800, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 750, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 500, 0, 0, "milliseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-minutes.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-minutes.js new file mode 100644 index 000000000000..928488a8e92b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-minutes.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 34, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 3 }), + 0, 0, 0, 0, 10, 33, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 32, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 6 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 12 }), + 0, 0, 0, 0, 10, 24, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 15 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 20, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 30 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nan.js new file mode 100644 index 000000000000..b36cd7605f20 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.until step 10: + 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nanoseconds.js new file mode 100644 index 000000000000..e67633b28a9b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nanoseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 533, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 530, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 528, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 530, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 520, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 525, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 520, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 400, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-non-integer.js new file mode 100644 index 000000000000..2f1612d79388 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +const result = earlier.until(later, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..ca6ae62391b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-seconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-seconds.js new file mode 100644 index 000000000000..1dc8b53a66c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-seconds.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 22, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 3 }), + 0, 0, 0, 0, 10, 35, 21, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 6 }), + 0, 0, 0, 0, 10, 35, 18, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 12 }), + 0, 0, 0, 0, 10, 35, 12, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 15 }), + 0, 0, 0, 0, 10, 35, 15, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 30 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "seconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-undefined.js new file mode 100644 index 000000000000..ceb69689dad3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.until step 10: + 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); + +const explicit = earlier.until(later, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..2492807ea830 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.until step 10: + 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => earlier.until(later, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-ceil.js new file mode 100644 index 000000000000..f4f72919d7ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-ceil.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingMode: "ceil" }), + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "hours", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 18, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "minutes", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 17, 5, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "seconds", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 17, 4, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "milliseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 17, 4, 864, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "microseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "nanoseconds", roundingMode: "ceil" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-floor.js new file mode 100644 index 000000000000..f9a6f854e42e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-floor.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "hours", roundingMode: "floor" }), + 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "minutes", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -18, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "seconds", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -17, -5, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "milliseconds", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -17, -4, -865, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "microseconds", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -17, -4, -864, -198, 0, "microseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingMode: "floor" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "nanoseconds", roundingMode: "floor" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfExpand.js new file mode 100644 index 000000000000..2a6bd77f959a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfExpand.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "hours", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "minutes", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 5, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "seconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, -5, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "milliseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 4, 864, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "microseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, -4, -864, -198, 0, "microseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "nanoseconds", roundingMode: "halfExpand" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js new file mode 100644 index 000000000000..6e9d4c9680a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-trunc.js new file mode 100644 index 000000000000..2cd15b94cad7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-trunc.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "hours", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "minutes", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "seconds", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "milliseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "microseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "nanoseconds", roundingMode: "trunc" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-undefined.js new file mode 100644 index 000000000000..c339dd94f2d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-undefined.js @@ -0,0 +1,93 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingMode: undefined }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "hours", roundingMode: undefined }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "hours" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "minutes", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "minutes" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds" }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "seconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "seconds" }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "milliseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "milliseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "microseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "microseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "nanoseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "nanoseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-wrong-type.js new file mode 100644 index 000000000000..454a995e7a27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js new file mode 100644 index 000000000000..678c111d5426 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..3cf5c2a43ece --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => earlier.until(later, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-undefined.js new file mode 100644 index 000000000000..6b03b807ff98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); + +const explicit = earlier.until(later, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const lambda = earlier.until(later, () => {}); +TemporalHelpers.assertDuration(lambda, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-wrong-type.js new file mode 100644 index 000000000000..a5619b88789e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => earlier.until(later, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/year-zero.js new file mode 100644 index 000000000000..81869181aed2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-12-07T03:24:30', + '-000000-12-07T03:24:30+01:00[UTC]' +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/basic.js new file mode 100644 index 000000000000..64672f5bebd0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/basic.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: Basic tests for valueOf(). +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("09:36:29.123456789"); +const plainTime2 = Temporal.PlainTime.from("09:36:29.123456789"); + +assert.throws(TypeError, () => plainTime.valueOf(), "valueOf"); +assert.throws(TypeError, () => plainTime < plainTime, "<"); +assert.throws(TypeError, () => plainTime <= plainTime, "<="); +assert.throws(TypeError, () => plainTime > plainTime, ">"); +assert.throws(TypeError, () => plainTime >= plainTime, ">="); +assert.sameValue(plainTime === plainTime, true, "==="); +assert.sameValue(plainTime === plainTime2, false, "==="); +assert.sameValue(plainTime !== plainTime, false, "!=="); +assert.sameValue(plainTime !== plainTime2, true, "!=="); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/builtin.js new file mode 100644 index 000000000000..f46b29f58fcf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: > + Tests that Temporal.PlainTime.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/length.js new file mode 100644 index 000000000000..71133142c0d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: Temporal.PlainTime.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/name.js new file mode 100644 index 000000000000..e7f50f75fc50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: Temporal.PlainTime.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/not-a-constructor.js new file mode 100644 index 000000000000..0d8e6cb64f8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: > + Temporal.PlainTime.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.valueOf), false, + "isConstructor(Temporal.PlainTime.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/prop-desc.js new file mode 100644 index 000000000000..9ab2c2e48e32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: The "valueOf" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.valueOf, + "function", + "`typeof PlainTime.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/argument-not-object.js new file mode 100644 index 000000000000..105336fc37c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/argument-not-object.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: TypeError is thrown if a primitive is passed, including ISO strings +info: | + Temporal.PlainTime.prototype.with ( temporalTimeLike [ , options ] ) + + 3. If Type(temporalTimeLike) is not Object, then + a. Throw a TypeError exception. +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws(TypeError, () => instance.with(undefined), "undefined"); +assert.throws(TypeError, () => instance.with(null), "null"); +assert.throws(TypeError, () => instance.with(true), "true"); +assert.throws(TypeError, () => instance.with(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.with(1), "1"); +assert.throws(TypeError, () => instance.with(1n), "1n"); + +const strings = [ + "", + "18:05:42.577", + "2019-05-17T18:05:42.577", + "2019-05-17T18:05:42.577Z", + "2019-05-17", + "42", +]; +for (const s of strings) { + assert.throws(TypeError, () => instance.with(s), s); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/basic.js new file mode 100644 index 000000000000..914340ab3c0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/basic.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Basic tests for with(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime, 15, 23, 30, 123, 456, 789, "initial"); + +const hour = plainTime.with({ hour: 3 }); +TemporalHelpers.assertPlainTime(hour, 3, 23, 30, 123, 456, 789, "hour"); + +const minute = plainTime.with({ minute: 3 }); +TemporalHelpers.assertPlainTime(minute, 15, 3, 30, 123, 456, 789, "minute"); + +const second = plainTime.with({ second: 3 }); +TemporalHelpers.assertPlainTime(second, 15, 23, 3, 123, 456, 789, "second"); + +const millisecond = plainTime.with({ millisecond: 3 }); +TemporalHelpers.assertPlainTime(millisecond, 15, 23, 30, 3, 456, 789, "millisecond"); + +const microsecond = plainTime.with({ microsecond: 3 }); +TemporalHelpers.assertPlainTime(microsecond, 15, 23, 30, 123, 3, 789, "microsecond"); + +const nanosecond = plainTime.with({ nanosecond: 3 }); +TemporalHelpers.assertPlainTime(nanosecond, 15, 23, 30, 123, 456, 3, "nanosecond"); + +const combined = plainTime.with({ minute: 8, nanosecond: 3 }); +TemporalHelpers.assertPlainTime(combined, 15, 8, 30, 123, 456, 3, "combined"); + +const plural = plainTime.with({ minutes: 8, nanosecond: 3 }); +TemporalHelpers.assertPlainTime(plural, 15, 23, 30, 123, 456, 3, "plural"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/builtin.js new file mode 100644 index 000000000000..563b2814e325 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: > + Tests that Temporal.PlainTime.prototype.with + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.with), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.with), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.with), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.with.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/copy-properties-not-undefined.js new file mode 100644 index 000000000000..3147ac4c0ffb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/copy-properties-not-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: PreparePartialTemporalFields copies only defined properties of source object +info: | + 4. For each value _property_ of _fieldNames_, do + a. Let _value_ be ? Get(_fields_, _property_). + b. If _value_ is not *undefined*, then + ... + iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(9, 45, 55); + +TemporalHelpers.assertPlainTime(plainTime.with({ hour: 8, second: undefined }), + 8, 45, 55, 0, 0, 0, + "only the properties that are present and defined in the plain object are copied" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..ba2d089dfa26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.with +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +[Infinity, -Infinity].forEach((inf) => { + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.with({ [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.with({ [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/length.js new file mode 100644 index 000000000000..d1f23c9f78c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Temporal.PlainTime.prototype.with.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.with, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/name.js new file mode 100644 index 000000000000..6ff9a05df9b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Temporal.PlainTime.prototype.with.name is "with". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/not-a-constructor.js new file mode 100644 index 000000000000..15dde1eeef17 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: > + Temporal.PlainTime.prototype.with does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.with(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.with), false, + "isConstructor(Temporal.PlainTime.prototype.with)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-invalid.js new file mode 100644 index 000000000000..18c1c5724ddc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12); +for (const badOptions of [null, true, "hello", Symbol("foo"), 1, 1n]) { + assert.throws(TypeError, () => plainTime.with({ hour: 3 }, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-undefined.js new file mode 100644 index 000000000000..6f42e0f26d50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-undefined.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +includes: [temporalHelpers.js] +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const fields = { minute: 60 }; + +const explicit = time.with(fields, undefined); +TemporalHelpers.assertPlainTime(explicit, 12, 59, 56, 987, 654, 321, "explicit"); + +const implicit = time.with(fields); +TemporalHelpers.assertPlainTime(implicit, 12, 59, 56, 987, 654, 321, "implicit"); + +const lambda = time.with(fields, () => {}); +TemporalHelpers.assertPlainTime(lambda, 12, 59, 56, 987, 654, 321, "lambda"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/order-of-operations.js new file mode 100644 index 000000000000..1c056cd1063f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/order-of-operations.js @@ -0,0 +1,63 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Properties on an object passed to with() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const expected = [ + "get calendar", + "get timeZone", + "get hour", + "get hour.valueOf", + "call hour.valueOf", + "get microsecond", + "get microsecond.valueOf", + "call microsecond.valueOf", + "get millisecond", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get minute", + "get minute.valueOf", + "call minute.valueOf", + "get nanosecond", + "get nanosecond.valueOf", + "call nanosecond.valueOf", + "get second", + "get second.valueOf", + "call second.valueOf", +]; +const actual = []; +const fields = { + hour: 1.7, + minute: 1.7, + second: 1.7, + millisecond: 1.7, + microsecond: 1.7, + nanosecond: 1.7, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.with(argument); +TemporalHelpers.assertPlainTime(result, 1, 1, 1, 1, 1, 1); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js new file mode 100644 index 000000000000..3207f54b62bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.prototype.with step 11: + 11. Let _overflow_ be ? ToTemporalOverflow(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12); +const values = ["", "CONSTRAIN", "balance", "other string"]; + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => time.with({ minute: 45 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-undefined.js new file mode 100644 index 000000000000..b66a7795a054 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.prototype.with step 11: + 11. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12); +const explicit = time.with({ minute: 67 }, { overflow: undefined }); +TemporalHelpers.assertPlainTime(explicit, 12, 59, 0, 0, 0, 0, "default overflow is constrain"); +const implicit = time.with({ minute: 67 }, {}); +TemporalHelpers.assertPlainTime(implicit, 12, 59, 0, 0, 0, 0, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-wrong-type.js new file mode 100644 index 000000000000..546bba2a284f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-wrong-type.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.prototype.with step 11: + 11. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => time.with({ minute: 45 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 45, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/plaintimelike-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/plaintimelike-invalid.js new file mode 100644 index 000000000000..4243d87b8abd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/plaintimelike-invalid.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Throws TypeError on an argument that is not a PlainTime-like property bag +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const tests = [ + // Step 3. + [undefined], + [null], + [true], + ["2019-05-17"], + ["2019-05-17T12:34"], + ["2019-05-17T12:34Z"], + ["18:05:42.577"], + ["42"], + [Symbol(), "symbol"], + [42, "number"], + [42n, "bigint"], + + // Step 4. + [Temporal.PlainDate.from("2019-05-17"), "PlainDate"], + [Temporal.PlainDateTime.from("2019-05-17T12:34"), "PlainDateTime"], + [Temporal.PlainMonthDay.from("2019-05-17"), "PlainMonthDay"], + [Temporal.PlainTime.from("12:34"), "PlainTime"], + [Temporal.PlainYearMonth.from("2019-05-17"), "PlainYearMonth"], + [Temporal.ZonedDateTime.from("2019-05-17T12:34Z[UTC]"), "ZonedDateTime"], + + // Step 5-6. + [{ hour: 14, calendar: "iso8601" }, "calendar"], + + // Step 7-8. + [{ hour: 14, timeZone: "UTC" }, "timeZone"], + + // Step 9. + [{}, "empty object"], + [{ hours: 14 }, "only plural property"], +]; + +for (const [value, message = String(value)] of tests) { + assert.throws(TypeError, () => plainTime.with(value), message); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/prop-desc.js new file mode 100644 index 000000000000..e3b43a3a9d3b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: The "with" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.with, + "function", + "`typeof PlainTime.prototype.with` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "with", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/subclassing-ignored.js new file mode 100644 index 000000000000..f090edad8b64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Objects of a subclass are never created as return values for with() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainTime, + [12, 34, 56, 987, 654, 321], + "with", + [{ nanosecond: 1 }], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 1), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/second-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/second-undefined.js new file mode 100644 index 000000000000..5ad4e04922fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/second-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Second argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [12, 34]; + +const explicit = new Temporal.PlainTime(...args, undefined); +TemporalHelpers.assertPlainTime(explicit, ...args, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(implicit, ...args, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/shell.js index e69de29bb2d1..1d70b7579ee9 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/basic.js new file mode 100644 index 000000000000..33fb642e754c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/basic.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: PlainYearMonth constructor works +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = new Temporal.PlainYearMonth(1976, 11); +assert.sameValue(typeof ym, "object"); +TemporalHelpers.assertPlainYearMonth(ym, 1976, 11, "M11"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/builtin.js new file mode 100644 index 000000000000..97a31b8375ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: Tests that Temporal.PlainYearMonth meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.PlainYearMonth.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-always.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-always.js new file mode 100644 index 000000000000..ad7321e2cc87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-always.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: If calendar name is to be emitted, include additional reference info +features: [Temporal] +---*/ + +const pym = new Temporal.PlainYearMonth(2019, 10, "iso8601", 31); + +assert.sameValue( + pym.toString({ calendarName: 'always' }), + "2019-10-31[u-ca=iso8601]", + "emit year-month-day if calendarName = 'always' (four-argument constructor)" +); + +const anotherPYM = Temporal.PlainYearMonth.from("2019-10-31"); // 31 will get dropped + +assert.sameValue( + anotherPYM.toString({ calendarName: 'always' }), + "2019-10-01[u-ca=iso8601]", + "emit fallback day if calendarName = 'always' (static from)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-invalid.js new file mode 100644 index 000000000000..67a3f2cf5d23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-invalid.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainYearMonth throws a RangeError if the calendar argument is invalid +esid: sec-temporal.plainyearmonth +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf"]; +const actual = []; +const args = [ + TemporalHelpers.toPrimitiveObserver(actual, 1970, "year"), + TemporalHelpers.toPrimitiveObserver(actual, 1, "month"), + "local", + TemporalHelpers.toPrimitiveObserver(actual, 1, "day") +]; +assert.throws(RangeError, () => new Temporal.PlainYearMonth(...args)); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-temporal-object.js new file mode 100644 index 000000000000..2cc6688ce106 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-temporal-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainyearmonth step 5: + 5. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = new Temporal.PlainYearMonth(2000, 5, temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-undefined.js new file mode 100644 index 000000000000..129a9980d8a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/calendar-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: Calendar argument defaults to the built-in ISO 8601 calendar +features: [Temporal] +---*/ + +const args = [2000, 5]; + +Object.defineProperty(Temporal.Calendar, "from", { + get() { + throw new Test262Error("Should not get Calendar.from"); + }, +}); + +const dateExplicit = new Temporal.PlainYearMonth(...args, undefined); +assert.sameValue(dateExplicit.calendar.toString(), "iso8601"); + +const dateImplicit = new Temporal.PlainYearMonth(...args); +assert.sameValue(dateImplicit.calendar.toString(), "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/argument-cast.js new file mode 100644 index 000000000000..0842f0967b7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/argument-cast.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: compare() casts its arguments +features: [Temporal] +---*/ + +const nov94 = Temporal.PlainYearMonth.from("1994-11"); +const jun13 = Temporal.PlainYearMonth.from("2013-06"); + +assert.sameValue(Temporal.PlainYearMonth.compare({ year: 1994, month: 11 }, jun13), -1, "one object"); +assert.sameValue(Temporal.PlainYearMonth.compare("1994-11", jun13), -1, "one string"); +assert.throws(TypeError, () => Temporal.PlainYearMonth.compare({ year: 1994 }, jun13), "one missing property"); + +assert.sameValue(Temporal.PlainYearMonth.compare(nov94, { year: 2013, month: 6 }), -1, "two object"); +assert.sameValue(Temporal.PlainYearMonth.compare(nov94, "2013-06"), -1, "two string"); +assert.throws(TypeError, () => Temporal.PlainYearMonth.compare(nov94, { year: 2013 }), "two missing property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..4e1146d55c0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/argument-string-with-utc-designator.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: RangeError thrown if a string with UTC designator is used as a PlainYearMonth +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const yearMonth = new Temporal.PlainYearMonth(2000, 5); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainYearMonth.compare(arg, yearMonth), + "String with UTC designator should not be valid as a PlainYearMonth (first argument)" + ); + assert.throws( + RangeError, + () => Temporal.PlainYearMonth.compare(yearMonth, arg), + "String with UTC designator should not be valid as a PlainYearMonth (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/basic.js new file mode 100644 index 000000000000..4614c746afe0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: Basic tests for compare() +features: [Temporal] +---*/ + +const nov94 = Temporal.PlainYearMonth.from("1994-11"); +const nov94bis = Temporal.PlainYearMonth.from("1994-11"); +const jun13 = Temporal.PlainYearMonth.from("2013-06"); +assert.sameValue(Temporal.PlainYearMonth.compare(nov94, nov94), 0, "same object"); +assert.sameValue(Temporal.PlainYearMonth.compare(nov94, nov94bis), 0, "different object"); +assert.sameValue(Temporal.PlainYearMonth.compare(nov94, jun13), -1, "before"); +assert.sameValue(Temporal.PlainYearMonth.compare(jun13, nov94), 1, "after"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/builtin.js new file mode 100644 index 000000000000..7326c02cf01e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: Tests that Temporal.PlainYearMonth.compare meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.compare), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.compare), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.compare), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.compare.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-fields-iterable.js new file mode 100644 index 000000000000..231016cb7526 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-fields-iterable.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.compare steps 1–2: + 1. Set _one_ to ? ToTemporalYearMonth(_one_). + 2. Set _two_ to ? ToTemporalYearMonth(_two_). + sec-temporal-totemporalyearmonth step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +Temporal.PlainYearMonth.compare( + { year: 2000, month: 5, calendar: calendar1 }, + { year: 2001, month: 6, calendar: calendar2 }, +); + +assert.sameValue(calendar1.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar1.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar1.iteratorExhausted[0], "iterated through the whole iterable"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-temporal-object.js new file mode 100644 index 000000000000..999876750855 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-temporal-object.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainyearmonth.compare steps 1–2: + 1. Set _one_ to ? ToTemporalYearMonth(_one_). + 2. Set _two_ to ? ToTemporalYearMonth(_two_). + sec-temporal-totemporaldate step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + Temporal.PlainYearMonth.compare( + { year: 2000, month: 5, calendar: temporalObject }, + { year: 2001, month: 6, calendar: temporalObject }, + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-yearmonthfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..44e04f2b18b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +Temporal.PlainYearMonth.compare({ year: 2000, month: 5, calendar }, { year: 2000, month: 6, calendar }); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 2); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to yearMonthFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +Temporal.PlainYearMonth.compare("2000-05-01", "2000-06-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 2); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/compare-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/compare-calendar.js new file mode 100644 index 000000000000..7578f326994c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/compare-calendar.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: compare() does not take the calendar into account +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor(id) { + super("iso8601"); + this._id = id; + } + toString() { + return this._id; + } +} + +const ym1 = new Temporal.PlainYearMonth(2000, 1, new CustomCalendar("a"), 1); +const ym2 = new Temporal.PlainYearMonth(2000, 1, new CustomCalendar("b"), 1); +assert.sameValue(Temporal.PlainYearMonth.compare(ym1, ym2), 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/compare-reference-day.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/compare-reference-day.js new file mode 100644 index 000000000000..4698e7fec45a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/compare-reference-day.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: compare() takes the reference day into account +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const ym1 = new Temporal.PlainYearMonth(2000, 1, iso, 1); +const ym2 = new Temporal.PlainYearMonth(2000, 1, iso, 2); +assert.sameValue(Temporal.PlainYearMonth.compare(ym1, ym2), -1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..ef477a5bdf6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const other = new Temporal.PlainYearMonth(2000, 5); +const base = { year: 2000, month: 5 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month"].forEach((prop) => { + assert.throws(RangeError, () => Temporal.PlainYearMonth.compare({ ...base, [prop]: inf }, other), `${prop} property cannot be ${inf}`); + + assert.throws(RangeError, () => Temporal.PlainYearMonth.compare(other, { ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, prop); + assert.throws(RangeError, () => Temporal.PlainYearMonth.compare({ ...base, [prop]: obj1 }, other)); + assert.compareArray(calls1, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, prop); + assert.throws(RangeError, () => Temporal.PlainYearMonth.compare(other, { ...base, [prop]: obj2 })); + assert.compareArray(calls2, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/length.js new file mode 100644 index 000000000000..201d6b2bc95c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: Temporal.PlainYearMonth.compare.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.compare, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/name.js new file mode 100644 index 000000000000..56aa5f08d1dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: Temporal.PlainYearMonth.compare.name is "compare". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.compare, "name", { + value: "compare", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/not-a-constructor.js new file mode 100644 index 000000000000..3606f6b5c42b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: Temporal.PlainYearMonth.compare does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.compare(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.compare), false, + "isConstructor(Temporal.PlainYearMonth.compare)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/prop-desc.js new file mode 100644 index 000000000000..5503a906557e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: The "compare" property of Temporal.PlainYearMonth +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.compare, + "function", + "`typeof PlainYearMonth.compare` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth, "compare", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/use-internal-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/use-internal-slots.js new file mode 100644 index 000000000000..fef23511f0ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/use-internal-slots.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.compare +description: compare() ignores the observable properties and uses internal slots +features: [Temporal] +---*/ + +function CustomError() {} + +class AvoidGettersYearMonth extends Temporal.PlainYearMonth { + get year() { + throw new CustomError(); + } + get month() { + throw new CustomError(); + } +} + +const one = new AvoidGettersYearMonth(2000, 5); +const two = new AvoidGettersYearMonth(2006, 3); +assert.sameValue(Temporal.PlainYearMonth.compare(one, two), -1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/year-zero.js new file mode 100644 index 000000000000..9876c58652b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/compare/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Negative zero, as an extended year, fails +esid: sec-temporal.plainyearmonth.compare +features: [Temporal] +---*/ + +const ok = new Temporal.PlainYearMonth(2000, 5); +const bad = "-000000-06"; + +assert.throws( + RangeError, + () => Temporal.PlainYearMonth.compare(bad, ok), + "Cannot use minus zero as extended year (first argument)" +); + +assert.throws( + RangeError, + () => Temporal.PlainYearMonth.compare(ok, bad), + "Cannot use minus zero as extended year (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/constructor.js new file mode 100644 index 000000000000..4b09cd9ad535 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: Temporal.PlainYearMonth constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.PlainYearMonth(1970, 1)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-number.js new file mode 100644 index 000000000000..769f34754bc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-number.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: A number argument is stringified +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainYearMonth = Temporal.PlainYearMonth.from(201906); +TemporalHelpers.assertPlainYearMonth(plainYearMonth, 2019, 6, "M06"); +const fields = plainYearMonth.getISOFields(); +assert.sameValue(fields.calendar.id, "iso8601"); +assert.sameValue(fields.isoDay, 1, "isoDay"); +assert.sameValue(fields.isoMonth, 6, "isoMonth"); +assert.sameValue(fields.isoYear, 2019, "isoYear"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-object.js new file mode 100644 index 000000000000..923b2dbd008d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-object.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: An object argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from({ year: 2019, monthCode: "M11" }), + 2019, 11, "M11", "Only monthCode"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from({ year: 2019, month: 11 }), + 2019, 11, "M11", "Only month"); +assert.throws(RangeError, + () => Temporal.PlainYearMonth.from({ year: 2019, month: 11, monthCode: "M12" }), + "Mismatch between month and monthCode"); + +const monthDayItem = { year: 2019, month: 11, get day() { throw new Test262Error("should not read the day property") } }; +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from(monthDayItem), + 2019, 11, "M11", "month with day"); + +const monthCodeDayItem = { year: 2019, monthCode: "M11", get day() { throw new Test262Error("should not read the day property") } }; +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from(monthCodeDayItem), + 2019, 11, "M11", "monthCode with day"); + +assert.throws(TypeError, + () => Temporal.PlainYearMonth.from({}), + "No properties"); +assert.throws(TypeError, + () => Temporal.PlainYearMonth.from({ year: 2019 }), + "Only year"); +assert.throws(TypeError, + () => Temporal.PlainYearMonth.from({ year: 2019, months: 6 }), + "Year and plural 'months'"); +assert.throws(TypeError, + () => Temporal.PlainYearMonth.from({ month: 6 }), + "Only month"); +assert.throws(TypeError, + () => Temporal.PlainYearMonth.from({ monthCode: "M06" }), + "Only monthCode"); +assert.throws(TypeError, + () => Temporal.PlainYearMonth.from({ year: undefined, month: 6 }), + "year explicit undefined"); + +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from({ year: 1976, month: 11, months: 12 }), + 1976, 11, "M11", "Plural property ignored"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-plaindate.js new file mode 100644 index 000000000000..fcb5e9f48d17 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-plaindate.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: A PlainYearMonth argument is cloned +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate = Temporal.PlainDate.from("1976-11-18"); +const plainYearMonth = Temporal.PlainYearMonth.from(plainDate); +TemporalHelpers.assertPlainYearMonth(plainYearMonth, 1976, 11, "M11"); +const fields = plainYearMonth.getISOFields(); +assert.sameValue(fields.calendar.id, "iso8601"); +assert.sameValue(fields.isoDay, 1, "isoDay"); +assert.sameValue(fields.isoMonth, 11, "isoMonth"); +assert.sameValue(fields.isoYear, 1976, "isoYear"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-plainyearmonth.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-plainyearmonth.js new file mode 100644 index 000000000000..b3ca9a967afe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-plainyearmonth.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: A PlainYearMonth argument is cloned +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const original = new Temporal.PlainYearMonth(2019, 11, undefined, 7); +const result = Temporal.PlainYearMonth.from(original); +assert.notSameValue(result, original); + +for (const plainYearMonth of [original, result]) { + TemporalHelpers.assertPlainYearMonth(plainYearMonth, 2019, 11, "M11"); + const fields = plainYearMonth.getISOFields(); + assert.sameValue(fields.calendar.id, "iso8601"); + assert.sameValue(fields.isoDay, 7, "isoDay"); + assert.sameValue(fields.isoMonth, 11, "isoMonth"); + assert.sameValue(fields.isoYear, 2019, "isoYear"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-invalid.js new file mode 100644 index 000000000000..42425d114932 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-invalid.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: An invalid ISO string is never supported +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.PlainYearMonth.from("2020-13", { overflow: "reject" })); +assert.throws(RangeError, () => Temporal.PlainYearMonth.from("2020-13", { overflow: "constrain" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-trailing-junk.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-trailing-junk.js new file mode 100644 index 000000000000..46d2de08e171 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-trailing-junk.js @@ -0,0 +1,13 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: RangeError thrown if a string with trailing junk is used as a PlainYearMonth +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.PlainYearMonth.from("1976-11junk")); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..36a4f9dfd01f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string-with-utc-designator.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: RangeError thrown if a string with UTC designator is used as a PlainYearMonth +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainYearMonth.from(arg), + "String with UTC designator should not be valid as a PlainYearMonth" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string.js new file mode 100644 index 000000000000..29fd2fe3cf27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/argument-string.js @@ -0,0 +1,58 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const inputs = [ + "1976-11", + "1976-11-10", + "1976-11-01T09:00:00+00:00", + "1976-11-01T00:00:00+05:00", + "197611", + "+00197611", + "1976-11-18T15:23:30.1\u221202:00", + "1976-11-18T152330.1+00:00", + "19761118T15:23:30.1+00:00", + "1976-11-18T15:23:30.1+0000", + "1976-11-18T152330.1+0000", + "19761118T15:23:30.1+0000", + "19761118T152330.1+00:00", + "19761118T152330.1+0000", + "+001976-11-18T152330.1+00:00", + "+0019761118T15:23:30.1+00:00", + "+001976-11-18T15:23:30.1+0000", + "+001976-11-18T152330.1+0000", + "+0019761118T15:23:30.1+0000", + "+0019761118T152330.1+00:00", + "+0019761118T152330.1+0000", + "1976-11-18T15:23", + "1976-11-18T15", + "1976-11-18", +]; + +for (const input of inputs) { + const plainYearMonth = Temporal.PlainYearMonth.from(input); + TemporalHelpers.assertPlainYearMonth(plainYearMonth, 1976, 11, "M11"); + const fields = plainYearMonth.getISOFields(); + assert.sameValue(fields.calendar.id, "iso8601"); + assert.sameValue(fields.isoDay, 1, "isoDay"); + assert.sameValue(fields.isoMonth, 11, "isoMonth"); + assert.sameValue(fields.isoYear, 1976, "isoYear"); +} + +const plainYearMonth = Temporal.PlainYearMonth.from("\u2212009999-11"); +TemporalHelpers.assertPlainYearMonth(plainYearMonth, -9999, 11, "M11"); +const fields = plainYearMonth.getISOFields(); +assert.sameValue(fields.calendar.id, "iso8601"); +assert.sameValue(fields.isoDay, 1, "isoDay"); +assert.sameValue(fields.isoMonth, 11, "isoMonth"); +assert.sameValue(fields.isoYear, -9999, "isoYear"); +assert.sameValue(plainYearMonth.toString(), "-009999-11"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/builtin.js new file mode 100644 index 000000000000..2a84606c4985 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Tests that Temporal.PlainYearMonth.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-fields-iterable.js new file mode 100644 index 000000000000..ee821a6ca42b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-fields-iterable.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.from step 3: + 3. Return ? ToTemporalYearMonth(_item_, _options_). + sec-temporal-totemporalyearmonth step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "month", + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +Temporal.PlainYearMonth.from({ year: 2000, month: 5, calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-temporal-object.js new file mode 100644 index 000000000000..8751b014391f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainyearmonth.from step 3: + 3. Return ? ToTemporalYearMonth(_item_, _options_). + sec-temporal-totemporaldate step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = Temporal.PlainYearMonth.from({ year: 2000, month: 5, calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-yearmonthfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..cb915d488407 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +features: [Temporal] +---*/ + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +Temporal.PlainYearMonth.from("2000-05-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..d72a58a07403 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { year: 2000, month: 5 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainYearMonth.from({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => Temporal.PlainYearMonth.from({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/length.js new file mode 100644 index 000000000000..c16c2ab6d818 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Temporal.PlainYearMonth.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/limits.js new file mode 100644 index 000000000000..4c58c233c8cf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/limits.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: PlainYearMonth.from enforces the supported range +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +["reject", "constrain"].forEach((overflow) => { + [{ year: -271821, month: 3 }, { year: 275760, month: 10 }, "-271821-03", "+275760-10"].forEach((value) => { + assert.throws(RangeError, () => Temporal.PlainYearMonth.from(value, { overflow }), + `${JSON.stringify(value)} with ${overflow}`); + }); +}); + +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from({ year: -271821, month: 4 }), + -271821, 4, "M04", "min object"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from({ year: 275760, month: 9 }), + 275760, 9, "M09", "max object"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("-271821-04"), + -271821, 4, "M04", "min string"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("+275760-09"), + 275760, 9, "M09", "max string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/name.js new file mode 100644 index 000000000000..f5484a6e7069 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Temporal.PlainYearMonth.from.name is "from". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/not-a-constructor.js new file mode 100644 index 000000000000..294db1e4ac9c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Temporal.PlainYearMonth.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.from), false, + "isConstructor(Temporal.PlainYearMonth.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/options-invalid.js new file mode 100644 index 000000000000..ee0981fd9fc3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/options-invalid.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const items = [ + { year: 2000, month: 11 }, + "2000-11", + new Temporal.PlainYearMonth(2000, 11), +]; +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; + +for (const item of items) { + for (const badOptions of values) { + assert.throws(TypeError, () => Temporal.PlainYearMonth.from(item, badOptions)); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/options-undefined.js new file mode 100644 index 000000000000..543c00814d45 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const fields = { year: 2000, month: 13 }; + +const explicit = Temporal.PlainYearMonth.from(fields, undefined); +assert.sameValue(explicit.month, 12, "default overflow is constrain"); + +const implicit = Temporal.PlainYearMonth.from(fields); +assert.sameValue(implicit.month, 12, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/order-of-operations.js new file mode 100644 index 000000000000..b30f00ef7f84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/order-of-operations.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Properties on an object passed to from() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get calendar", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; +const actual = []; +const fields = { + year: 1.7, + month: 1.7, + monthCode: "M01", +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + if (key === "calendar") return Temporal.Calendar.from("iso8601"); + const result = target[key]; + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = Temporal.PlainYearMonth.from(argument); +TemporalHelpers.assertPlainYearMonth(result, 1, 1, "M01"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-constrain.js new file mode 100644 index 000000000000..5758b6f145f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-constrain.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Reject value for overflow option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const propertyBag = { year: 2000, month: 13 }; +const plainYearMonth = Temporal.PlainYearMonth.from(propertyBag, { overflow: "constrain" }); +TemporalHelpers.assertPlainYearMonth(plainYearMonth, 2000, 12, "M12", "default overflow is constrain"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js new file mode 100644 index 000000000000..3e797078140b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporalyearmonth steps 2–3: + 2. If Type(_item_) is Object, then + ... + e. Return ? YearMonthFromFields(_calendar_, _fields_, _options_). + 3. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalYearMonth]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalYearMonth(_item_, _options_). +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainYearMonth(2000, 5), + { year: 2000, month: 5 }, + "2000-05", +]; + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainYearMonth.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-reject.js new file mode 100644 index 000000000000..26b7c85e43fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-reject.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Reject value for overflow option +features: [Temporal] +---*/ + +const bad = { year: 2019, month: 13 }; +assert.throws(RangeError, () => Temporal.PlainYearMonth.from(bad, { overflow: "reject" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-undefined.js new file mode 100644 index 000000000000..4cd22afe49ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-undefined.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporalyearmonth steps 2–3: + 2. If Type(_item_) is Object, then + ... + e. Return ? YearMonthFromFields(_calendar_, _fields_, _options_). + 3. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalYearMonth]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalYearMonth(_item_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainYearMonth(2000, 5), + "2000-05", +]; +validValues.forEach((value) => { + const explicit = Temporal.PlainYearMonth.from(value, { overflow: undefined }); + TemporalHelpers.assertPlainYearMonth(explicit, 2000, 5, "M05", "overflow is ignored"); + const implicit = Temporal.PlainYearMonth.from(value, {}); + TemporalHelpers.assertPlainYearMonth(implicit, 2000, 5, "M05", "overflow is ignored"); + const lambda = Temporal.PlainYearMonth.from(value, () => {}); + TemporalHelpers.assertPlainYearMonth(lambda, 2000, 5, "M05", "overflow is ignored"); +}); + +const propertyBag = { year: 2000, month: 13 }; +const explicit = Temporal.PlainYearMonth.from(propertyBag, { overflow: undefined }); +TemporalHelpers.assertPlainYearMonth(explicit, 2000, 12, "M12", "default overflow is constrain"); +const implicit = Temporal.PlainYearMonth.from(propertyBag, {}); +TemporalHelpers.assertPlainYearMonth(implicit, 2000, 12, "M12", "default overflow is constrain"); +const lambda = Temporal.PlainYearMonth.from(propertyBag, () => {}); +TemporalHelpers.assertPlainYearMonth(lambda, 2000, 12, "M12", "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-wrong-type.js new file mode 100644 index 000000000000..e41cc0074e7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/overflow-wrong-type.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-totemporalyearmonth steps 2–3: + 2. If Type(_item_) is Object, then + ... + e. Return ? YearMonthFromFields(_calendar_, _fields_, _options_). + 3. Perform ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalYearMonth]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + b. Return ... + 3. Return ? ToTemporalYearMonth(_item_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainYearMonth(2000, 5), + { year: 2000, month: 5 }, + "2000-05", +]; +validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => Temporal.PlainYearMonth.from(value, { overflow }), + (result, descr) => TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05", descr), +)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/prop-desc.js new file mode 100644 index 000000000000..62899152171f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: The "from" property of Temporal.PlainYearMonth +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.from, + "function", + "`typeof PlainYearMonth.from` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/subclassing-ignored.js new file mode 100644 index 000000000000..5d95ce8ce1c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/subclassing-ignored.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.PlainYearMonth, + "from", + ["2000-05"], + (result) => TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05"), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/year-zero.js new file mode 100644 index 000000000000..0340e5112b5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/from/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-06', + '-000000-06-24', + '-000000-06-24T15:43:27', + '-000000-06-24T15:43:27+01:00[UTC]' +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { Temporal.PlainYearMonth.from(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..0a7acae5bb9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/infinity-throws-rangeerror.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainYearMonth throws a RangeError if any numerical value is Infinity +esid: sec-temporal.plainyearmonth +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const isoCalendar = Temporal.Calendar.from('iso8601'); + +assert.throws(RangeError, () => new Temporal.PlainYearMonth(Infinity, 1)); +assert.throws(RangeError, () => new Temporal.PlainYearMonth(1970, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainYearMonth(1970, 1, isoCalendar, Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite year", + [O(Infinity, "year"), O(1, "month"), () => "iso8601", O(1, "day")], + ["get year.valueOf", "call year.valueOf"] + ], + [ + "infinite month", + [O(1970, "year"), O(Infinity, "month"), () => "iso8601", O(1, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf"] + ], + [ + "infinite day", + [O(1970, "year"), O(1, "month"), () => "iso8601", O(Infinity, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainYearMonth(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/length.js new file mode 100644 index 000000000000..17483bf20327 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: Temporal.PlainYearMonth.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/limits.js new file mode 100644 index 000000000000..38a4debbf03c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/limits.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: Limits for the PlainYearMonth constructor. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainYearMonth(-271821, 3), "min"); +assert.throws(RangeError, () => new Temporal.PlainYearMonth(275760, 10), "max"); +TemporalHelpers.assertPlainYearMonth(new Temporal.PlainYearMonth(-271821, 4), + -271821, 4, "M04", "min"); +TemporalHelpers.assertPlainYearMonth(new Temporal.PlainYearMonth(-271821, 4, "iso8601", 18), + -271821, 4, "M04", "min with referenceISODay"); +TemporalHelpers.assertPlainYearMonth(new Temporal.PlainYearMonth(275760, 9), + 275760, 9, "M09", "max"); +TemporalHelpers.assertPlainYearMonth(new Temporal.PlainYearMonth(275760, 9, "iso8601", 14), + 275760, 9, "M09", "max with referenceISODay"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/missing-arguments.js new file mode 100644 index 000000000000..a064ecb866fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/missing-arguments.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: RangeError thrown after processing given args when invoked without all required args +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "valueOf year", +]; +const actual = []; +const args = [ + { valueOf() { actual.push("valueOf year"); return 1; } }, +]; + +assert.throws(RangeError, () => new Temporal.PlainYearMonth(...args)); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/name.js new file mode 100644 index 000000000000..d59b60541d79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: Temporal.PlainYearMonth.name is "PlainYearMonth" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth, "name", { + value: "PlainYearMonth", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..44b6f2a03bf8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/negative-infinity-throws-rangeerror.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainYearMonth throws a RangeError if any numerical value is -Infinity +esid: sec-temporal.plainyearmonth +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const isoCalendar = Temporal.Calendar.from('iso8601'); + +assert.throws(RangeError, () => new Temporal.PlainYearMonth(-Infinity, 1)); +assert.throws(RangeError, () => new Temporal.PlainYearMonth(1970, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainYearMonth(1970, 1, isoCalendar, -Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite year", + [O(-Infinity, "year"), O(1, "month"), () => "iso8601", O(1, "day")], + ["get year.valueOf", "call year.valueOf"] + ], + [ + "infinite month", + [O(1970, "year"), O(-Infinity, "month"), () => "iso8601", O(1, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf"] + ], + [ + "infinite day", + [O(1970, "year"), O(1, "month"), () => "iso8601", O(-Infinity, "day")], + ["get year.valueOf", "call year.valueOf", "get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainYearMonth(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prop-desc.js new file mode 100644 index 000000000000..84ad1fa17f57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: The "PlainYearMonth" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth, + "function", + "`typeof PlainYearMonth` is `function`" +); + +verifyProperty(Temporal, "PlainYearMonth", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-duration-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-duration-object.js new file mode 100644 index 000000000000..0c4a2b44bcf0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-duration-object.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: A Duration object is supported as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const nov94 = Temporal.PlainYearMonth.from("1994-11"); +const diff = Temporal.Duration.from("P18Y7M"); +TemporalHelpers.assertPlainYearMonth(nov94.add(diff), 2013, 6, "M06"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-lower-units.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-lower-units.js new file mode 100644 index 000000000000..30ffc7b6b1b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-lower-units.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Using lower units in add() works +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); + +const tests = [ + [{ days: 1 }, 2019, 11, "M11"], + [{ days: 29 }, 2019, 11, "M11"], + [{ hours: 1 }, 2019, 11, "M11"], + [{ minutes: 1 }, 2019, 11, "M11"], + [{ seconds: 1 }, 2019, 11, "M11"], + [{ milliseconds: 1 }, 2019, 11, "M11"], + [{ microseconds: 1 }, 2019, 11, "M11"], + [{ nanoseconds: 1 }, 2019, 11, "M11"], + [{ days: 30 }, 2019, 12, "M12"], + [{ days: 31 }, 2019, 12, "M12"], + [{ days: 60 }, 2019, 12, "M12"], + [{ days: 61 }, 2020, 1, "M01"], + [{ hours: 720 }, 2019, 12, "M12"], + [{ minutes: 43200 }, 2019, 12, "M12"], + [{ seconds: 2592000 }, 2019, 12, "M12"], + [{ milliseconds: 2592000_000 }, 2019, 12, "M12"], + [{ microseconds: 2592000_000_000 }, 2019, 12, "M12"], + [{ nanoseconds: 2592000_000_000_000 }, 2019, 12, "M12"], +]; + +for (const [argument, ...expected] of tests) { + TemporalHelpers.assertPlainYearMonth(ym.add(argument), ...expected, "no options"); + TemporalHelpers.assertPlainYearMonth(ym.add(argument, { overflow: "constrain" }), ...expected, "constrain"); + TemporalHelpers.assertPlainYearMonth(ym.add(argument, { overflow: "reject" }), ...expected, "reject"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-not-object.js new file mode 100644 index 000000000000..99d4c525c734 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Passing a primitive other than string to add() throws +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5 }); +assert.throws(RangeError, () => instance.add(undefined), "undefined"); +assert.throws(RangeError, () => instance.add(null), "null"); +assert.throws(RangeError, () => instance.add(true), "boolean"); +assert.throws(RangeError, () => instance.add(""), "empty string"); +assert.throws(TypeError, () => instance.add(Symbol()), "Symbol"); +assert.throws(RangeError, () => instance.add(7), "number"); +assert.throws(RangeError, () => instance.add(7n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object-invalid.js new file mode 100644 index 000000000000..fb8ed07d8305 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object-invalid.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Mixed positive and negative values or missing properties always throw +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); +for (const overflow of ["constrain", "reject"]) { + assert.throws(RangeError, () => ym.add({ years: 1, months: -6 }, { overflow }), overflow) +} + +assert.throws(TypeError, () => ym.add({}), "no properties"); +assert.throws(TypeError, () => ym.add({ month: 12 }), "only singular 'month' property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object-plural.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object-plural.js new file mode 100644 index 000000000000..dbbf2c3f8241 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object-plural.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Singular properties are ignored +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); +TemporalHelpers.assertPlainYearMonth(ym.add({ month: 1, years: 1 }), 2020, 11, "M11"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object.js new file mode 100644 index 000000000000..86b3e29376fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-object.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Passing an object to add() works +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); + +const tests = [ + [{ months: 2 }, 2020, 1, "M01"], + [{ years: 1 }, 2020, 11, "M11"], + [{ months: -2 }, 2019, 9, "M09"], + [{ years: -1 }, 2018, 11, "M11"], +]; + +for (const [argument, ...expected] of tests) { + TemporalHelpers.assertPlainYearMonth(ym.add(argument), ...expected, "no options"); + TemporalHelpers.assertPlainYearMonth(ym.add(argument, { overflow: "constrain" }), ...expected, "constrain"); + TemporalHelpers.assertPlainYearMonth(ym.add(argument, { overflow: "reject" }), ...expected, "reject"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..6f8de65f1e55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); + +const resultHours = instance.add("-PT24.567890123H"); +TemporalHelpers.assertPlainYearMonth(resultHours, 2000, 5, "M05", "negative fractional hours"); + +const resultMinutes = instance.add("-PT1440.567890123M"); +TemporalHelpers.assertPlainYearMonth(resultMinutes, 2000, 5, "M05", "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-string.js new file mode 100644 index 000000000000..062b5830a3c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5 }); +const result = instance.add("P3M"); +TemporalHelpers.assertPlainYearMonth(result, 2000, 8, "M08"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/builtin.js new file mode 100644 index 000000000000..7d37c983a721 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: > + Tests that Temporal.PlainYearMonth.prototype.add + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.add), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.add), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.add), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.add.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-arguments-extra-options.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-arguments-extra-options.js new file mode 100644 index 000000000000..fabcf9c2e272 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-arguments-extra-options.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: PlainYearMonth.prototype.add should pass extra fields in copied options objects. +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 5. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "get extra", + "get overflow", +]; +const options = new Proxy({ extra: 5 }, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateAdd(date, duration, options) { + const result = super.dateAdd(date, duration, options); + options.overflow = 'meatloaf'; + return result; + } + yearMonthFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.notSameValue(args[1], options, "args[1]"); + return super.yearMonthFromFields(...args); + } +} +const plainYearMonth = new Temporal.PlainYearMonth(2000, 3, new CustomCalendar()); +const result = plainYearMonth.add({ months: 5 }, options); +TemporalHelpers.assertPlainYearMonth(result, 2000, 8, "M08"); +assert.compareArray(actual, expected, "extra field options object order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-arguments.js new file mode 100644 index 000000000000..863b5da2d82f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-arguments.js @@ -0,0 +1,62 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: PlainYearMonth.prototype.add should respect calendar arguments and pass copied options objects. +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 5. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "get overflow", + "get overflow", + "get overflow.toString", + "call overflow.toString", + "get overflow.toString", + "call overflow.toString", +]; +const options = new Proxy({ overflow: "constrain" }, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateAdd(date, duration, options) { + const result = super.dateAdd(date, duration, options); + options.overflow = 'meatloaf'; + return result; + } + yearMonthFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.notSameValue(args[1], options, "args[1]"); + return super.yearMonthFromFields(...args); + } +} + +const plainYearMonth = new Temporal.PlainYearMonth(2000, 3, new CustomCalendar()); +const result = plainYearMonth.add({ months: 10 }, options); +TemporalHelpers.assertPlainYearMonth(result, 2001, 1, "M01"); +assert.compareArray(actual, expected, "copied options object order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-datefromfields-called.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-datefromfields-called.js new file mode 100644 index 000000000000..0fbbd944e937 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-datefromfields-called.js @@ -0,0 +1,150 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: > + Calls calendar's dateFromFields method to obtain a start date for the + operation, based on the sign of the duration +info: | + 8. Let _fields_ be ? PrepareTemporalFields(_yearMonth_, _fieldNames_, «»). + 9. Let _sign_ be ! DurationSign(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _balanceResult_.[[Days]], 0, 0, 0, 0, 0, 0). + 10. If _sign_ < 0, then + a. Let _dayFromCalendar_ be ? CalendarDaysInMonth(_calendar_, _yearMonth_). + b. Let _day_ be ? ToPositiveInteger(_dayFromCalendar_). + 11. Else, + a. Let _day_ be 1. + 12. Perform ! CreateDataPropertyOrThrow(_fields_, *"day"*, _day_). + 13. Let _date_ be ? DateFromFields(_calendar_, _fields_, *undefined*). +includes: [deepEqual.js, temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCalls = []; + } + year(date) { + // years in this calendar start and end on the same day as ISO 8601 years + return date.getISOFields().isoYear; + } + month(date) { + // this calendar has 10 months of 36 days each, plus an 11th month of 5 or 6 + const { isoYear, isoMonth, isoDay } = date.getISOFields(); + const isoDate = new Temporal.PlainDate(isoYear, isoMonth, isoDay); + return Math.floor((isoDate.dayOfYear - 1) / 36) + 1; + } + monthCode(date) { + return "M" + this.month(date).toString().padStart(2, "0"); + } + day(date) { + return (date.dayOfYear - 1) % 36 + 1; + } + daysInMonth(date) { + if (this.month(date) < 11) return 36; + return this.daysInYear(date) - 360; + } + _dateFromFieldsImpl({ year, month, monthCode, day }) { + if (year === undefined) throw new TypeError("year required"); + if (month === undefined && monthCode === undefined) throw new TypeError("one of month or monthCode required"); + if (month !== undefined && month < 1) throw new RangeError("month < 1"); + if (day === undefined) throw new TypeError("day required"); + + if (monthCode !== undefined) { + const numberPart = +(monthCode.slice(1)); + if ("M" + `${numberPart}`.padStart(2, "0") !== monthCode) throw new RangeError("invalid monthCode"); + if (month === undefined) { + month = numberPart; + } else if (month !== numberPart) { + throw new RangeError("month and monthCode must match"); + } + } + + const isoDayOfYear = (month - 1) * 36 + day; + return new Temporal.PlainDate(year, 1, 1).add({ days: isoDayOfYear - 1 }).withCalendar(this); + } + dateFromFields(...args) { + this.dateFromFieldsCalls.push(args); + return this._dateFromFieldsImpl(...args); + } + yearMonthFromFields(fields, options) { + const { isoYear, isoMonth, isoDay } = this._dateFromFieldsImpl({ ...fields, day: 1 }, options).getISOFields(); + return new Temporal.PlainYearMonth(isoYear, isoMonth, this, isoDay); + } + monthDayFromFields(fields, options) { + const { isoYear, isoMonth, isoDay } = this._dateFromFieldsImpl({ ...fields, year: 2000 }, options).getISOFields(); + return new Temporal.PlainMonthDay(isoMonth, isoDay, this, isoYear); + } + dateAdd(date, duration, options) { + if (duration.months) throw new Error("adding months not implemented in this test"); + return super.dateAdd(date, duration, options); + } + toString() { + return "thirty-six"; + } +} + +const calendar = new CustomCalendar(); +const month2 = Temporal.PlainYearMonth.from({ year: 2022, month: 2, calendar }); +const lessThanOneMonth = new Temporal.Duration(0, 0, 0, 35); +const oneMonth = new Temporal.Duration(0, 0, 0, 36); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.add(lessThanOneMonth), + 2022, 2, "M02", + "adding positive less than one month's worth of days yields the same month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 1 }, + "first day of month 2 passed to dateFromFields when adding positive duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.add(oneMonth), + 2022, 3, "M03", + "adding positive one month's worth of days yields the following month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 1 }, + "first day of month 2 passed to dateFromFields when adding positive duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.add(lessThanOneMonth.negated()), + 2022, 2, "M02", + "adding negative less than one month's worth of days yields the same month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 36 }, + "last day of month 2 passed to dateFromFields when adding negative duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.add(oneMonth.negated()), + 2022, 1, "M01", + "adding negative one month's worth of days yields the previous month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 36 }, + "last day of month 2 passed to dateFromFields when adding negative duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-daysinmonth-wrong-value.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-daysinmonth-wrong-value.js new file mode 100644 index 000000000000..9f3d592298f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-daysinmonth-wrong-value.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: > + The appropriate error is thrown if the calendar's daysInMonth method returns a + value that cannot be converted to a positive integer +includes: [compareArray.js] +features: [BigInt, Symbol, Temporal] +---*/ + +const actual = []; +class CalendarDaysInMonthWrongValue extends Temporal.Calendar { + constructor(badValue) { + super("iso8601"); + this._badValue = badValue; + } + dateFromFields(fields, options) { + actual.push("call dateFromFields"); + return super.dateFromFields(fields, options); + } + daysInMonth() { + return this._badValue; + } +} +// daysInMonth is only called if we are adding a negative duration +const duration = new Temporal.Duration(-1, -1); + +[Infinity, -Infinity, -42].forEach((badValue) => { + const calendar = new CalendarDaysInMonthWrongValue(badValue); + const yearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + assert.throws(RangeError, () => yearMonth.add(duration), `daysInMonth ${badValue}`); + assert.compareArray(actual, [], "dateFromFields not called"); +}); + +[Symbol('foo'), 31n].forEach((badValue) => { + const calendar = new CalendarDaysInMonthWrongValue(badValue); + const yearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + assert.throws(TypeError, () => yearMonth.add(duration), `daysInMonth ${typeof badValue}`); + assert.compareArray(actual, [], "dateFromFields not called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-fields-iterable.js new file mode 100644 index 000000000000..7fde07066a7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-fields-iterable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.prototype.add step 8: + 8. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +yearmonth.add({ months: 1 }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..95a82a3be29c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainYearMonth.prototype.add throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plainyearmonth.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/length.js new file mode 100644 index 000000000000..b099ba32af6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Temporal.PlainYearMonth.prototype.add.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.add, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/limits.js new file mode 100644 index 000000000000..91e2f46519dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/limits.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: RangeError thrown when going out of range +features: [Temporal] +---*/ + +const max = Temporal.PlainYearMonth.from("+275760-09"); +for (const overflow of ["reject", "constrain"]) { + assert.throws(RangeError, () => max.add({ months: 1 }, { overflow }), overflow); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/month-length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/month-length.js new file mode 100644 index 000000000000..5b069be2c772 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/month-length.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: add() takes month length into account +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); + +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2019-02").add({ days: 27 }), + 2019, 2, "M02"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2019-02").add({ days: 28 }), + 2019, 3, "M03"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2020-02").add({ days: 28 }), + 2020, 2, "M02"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2020-02").add({ days: 29 }), + 2020, 3, "M03"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2019-11").add({ days: 29 }), + 2019, 11, "M11"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2019-11").add({ days: 30 }), + 2019, 12, "M12"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2020-01").add({ days: 30 }), + 2020, 1, "M01"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2020-01").add({ days: 31 }), + 2020, 2, "M02"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/name.js new file mode 100644 index 000000000000..454d8352845f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Temporal.PlainYearMonth.prototype.add.name is "add". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.add, "name", { + value: "add", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..04dafc470392 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainYearMonth.prototype.add throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plainyearmonth.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..48e4775b65ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.add({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/not-a-constructor.js new file mode 100644 index 000000000000..9648e70532d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: > + Temporal.PlainYearMonth.prototype.add does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.add(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.add), false, + "isConstructor(Temporal.PlainYearMonth.prototype.add)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/options-invalid.js new file mode 100644 index 000000000000..681b512773c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/options-invalid.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Invalid options throw +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +for (const badOptions of values) { + assert.throws(TypeError, () => ym.add({ years: 1 }, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/options-undefined.js new file mode 100644 index 000000000000..d88f373510e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/options-undefined.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +// overflow option has no effect on addition in the ISO calendar, so verify this +// with a custom calendar +class CheckedAdd extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateAdd(date, duration, options, constructor) { + this.called = true; + assert.notSameValue(options, undefined, "options not undefined"); + return super.dateAdd(date, duration, options, constructor); + } +} +const calendar = new CheckedAdd(); + +const yearmonth = new Temporal.PlainYearMonth(2000, 1, calendar); +const duration = { months: 1 }; + +yearmonth.add(duration, undefined); +yearmonth.add(duration); + +assert(calendar.called); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/order-of-operations.js new file mode 100644 index 000000000000..f45fa8413a7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Properties on an object passed to add() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.add(argument); +TemporalHelpers.assertPlainYearMonth(result, 2001, 6, "M06"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js new file mode 100644 index 000000000000..644b4d2ffcdf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.add steps 13–15: + 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_). + 14. ... + 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_). +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +const duration = new Temporal.Duration(1, 1); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-undefined.js new file mode 100644 index 000000000000..4ad42261aee7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-undefined.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.add steps 13–15: + 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_). + 14. ... + 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// In the ISO calendar, PlainYearMonth.prototype.add() actually ignores the +// overflow option. There is no addition in the ISO calendar that we could test +// which would actually show a difference between the 'constrain' and 'reject' +// values. +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +const duration = new Temporal.Duration(1, 1); +const explicit = yearmonth.add(duration, { overflow: undefined }); +TemporalHelpers.assertPlainYearMonth(explicit, 2001, 6, "M06", "default overflow is constrain"); +const implicit = yearmonth.add(duration, {}); +TemporalHelpers.assertPlainYearMonth(implicit, 2001, 6, "M06", "default overflow is constrain"); +const lambda = yearmonth.add(duration, () => {}); +TemporalHelpers.assertPlainYearMonth(lambda, 2001, 6, "M06", "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-wrong-type.js new file mode 100644 index 000000000000..434dfbdd3f56 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-wrong-type.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.add steps 13–15: + 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_). + 14. ... + 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +const duration = new Temporal.Duration(1, 1); + +// See TemporalHelpers.checkStringOptionWrongType(); this code path has +// different expectations for observable calls + +assert.throws(RangeError, () => yearmonth.add(duration, { overflow: null }), "null"); +assert.throws(RangeError, () => yearmonth.add(duration, { overflow: true }), "true"); +assert.throws(RangeError, () => yearmonth.add(duration, { overflow: false }), "false"); +assert.throws(TypeError, () => yearmonth.add(duration, { overflow: Symbol() }), "symbol"); +assert.throws(RangeError, () => yearmonth.add(duration, { overflow: 2 }), "bigint"); +assert.throws(RangeError, () => yearmonth.add(duration, { overflow: 2n }), "bigint"); +assert.throws(RangeError, () => yearmonth.add(duration, { overflow: {} }), "plain object"); + +// toString property is read once by Calendar.dateAdd() and then once again by +// calendar.yearMonthFromFields(). +const expected = [ + "get overflow.toString", + "call overflow.toString", + "get overflow.toString", + "call overflow.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); +const result = yearmonth.add(duration, { overflow: observer }); +TemporalHelpers.assertPlainYearMonth(result, 2001, 6, "M06", "object with toString"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/prop-desc.js new file mode 100644 index 000000000000..0a2af6343dcf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: The "add" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.add, + "function", + "`typeof PlainYearMonth.prototype.add` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "add", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/shell.js index e69de29bb2d1..b36293881a43 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/shell.js @@ -0,0 +1,348 @@ +// GENERATED, DO NOT EDIT +// file: deepEqual.js +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Compare two values structurally +defines: [assert.deepEqual] +---*/ + +assert.deepEqual = function(actual, expected, message) { + var format = assert.deepEqual.format; + assert( + assert.deepEqual._compare(actual, expected), + `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}` + ); +}; + +assert.deepEqual.format = function(value, seen) { + switch (typeof value) { + case 'string': + return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`; + case 'number': + case 'boolean': + case 'symbol': + case 'bigint': + return value.toString(); + case 'undefined': + return 'undefined'; + case 'function': + return `[Function${value.name ? `: ${value.name}` : ''}]`; + case 'object': + if (value === null) return 'null'; + if (value instanceof Date) return `Date "${value.toISOString()}"`; + if (value instanceof RegExp) return value.toString(); + if (!seen) { + seen = { + counter: 0, + map: new Map() + }; + } + + let usage = seen.map.get(value); + if (usage) { + usage.used = true; + return `[Ref: #${usage.id}]`; + } + + usage = { id: ++seen.counter, used: false }; + seen.map.set(value, usage); + + if (typeof Set !== "undefined" && value instanceof Set) { + return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (typeof Map !== "undefined" && value instanceof Map) { + return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (Array.isArray ? Array.isArray(value) : value instanceof Array) { + return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`; + } + let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object'; + if (tag === 'Object' && Object.getPrototypeOf(value) === null) { + tag = '[Object: null prototype]'; + } + return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`; + default: + return typeof value; + } +}; + +assert.deepEqual._compare = (function () { + var EQUAL = 1; + var NOT_EQUAL = -1; + var UNKNOWN = 0; + + function deepEqual(a, b) { + return compareEquality(a, b) === EQUAL; + } + + function compareEquality(a, b, cache) { + return compareIf(a, b, isOptional, compareOptionality) + || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality) + || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache) + || NOT_EQUAL; + } + + function compareIf(a, b, test, compare, cache) { + return !test(a) + ? !test(b) ? UNKNOWN : NOT_EQUAL + : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache); + } + + function tryCompareStrictEquality(a, b) { + return a === b ? EQUAL : UNKNOWN; + } + + function tryCompareTypeOfEquality(a, b) { + return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN; + } + + function tryCompareToStringTagEquality(a, b) { + var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined; + var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined; + return aTag !== bTag ? NOT_EQUAL : UNKNOWN; + } + + function isOptional(value) { + return value === undefined + || value === null; + } + + function compareOptionality(a, b) { + return tryCompareStrictEquality(a, b) + || NOT_EQUAL; + } + + function isPrimitiveEquatable(value) { + switch (typeof value) { + case 'string': + case 'number': + case 'bigint': + case 'boolean': + case 'symbol': + return true; + default: + return isBoxed(value); + } + } + + function comparePrimitiveEquality(a, b) { + if (isBoxed(a)) a = a.valueOf(); + if (isBoxed(b)) b = b.valueOf(); + return tryCompareStrictEquality(a, b) + || tryCompareTypeOfEquality(a, b) + || compareIf(a, b, isNaNEquatable, compareNaNEquality) + || NOT_EQUAL; + } + + function isNaNEquatable(value) { + return typeof value === 'number'; + } + + function compareNaNEquality(a, b) { + return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL; + } + + function isObjectEquatable(value) { + return typeof value === 'object'; + } + + function compareObjectEquality(a, b, cache) { + if (!cache) cache = new Map(); + return getCache(cache, a, b) + || setCache(cache, a, b, EQUAL) // consider equal for now + || cacheComparison(a, b, tryCompareStrictEquality, cache) + || cacheComparison(a, b, tryCompareToStringTagEquality, cache) + || compareIf(a, b, isValueOfEquatable, compareValueOfEquality) + || compareIf(a, b, isToStringEquatable, compareToStringEquality) + || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache) + || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache) + || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || cacheComparison(a, b, fail, cache); + } + + function isBoxed(value) { + return value instanceof String + || value instanceof Number + || value instanceof Boolean + || typeof Symbol === 'function' && value instanceof Symbol + || typeof BigInt === 'function' && value instanceof BigInt; + } + + function isValueOfEquatable(value) { + return value instanceof Date; + } + + function compareValueOfEquality(a, b) { + return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isToStringEquatable(value) { + return value instanceof RegExp; + } + + function compareToStringEquality(a, b) { + return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isArrayLikeEquatable(value) { + return (Array.isArray ? Array.isArray(value) : value instanceof Array) + || (typeof Uint8Array === 'function' && value instanceof Uint8Array) + || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray) + || (typeof Uint16Array === 'function' && value instanceof Uint16Array) + || (typeof Uint32Array === 'function' && value instanceof Uint32Array) + || (typeof Int8Array === 'function' && value instanceof Int8Array) + || (typeof Int16Array === 'function' && value instanceof Int16Array) + || (typeof Int32Array === 'function' && value instanceof Int32Array) + || (typeof Float32Array === 'function' && value instanceof Float32Array) + || (typeof Float64Array === 'function' && value instanceof Float64Array) + || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array) + || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array); + } + + function compareArrayLikeEquality(a, b, cache) { + if (a.length !== b.length) return NOT_EQUAL; + for (var i = 0; i < a.length; i++) { + if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + return EQUAL; + } + + function isStructurallyEquatable(value) { + return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference + || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference + || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference + || typeof Map === 'function' && value instanceof Map // comparable via @@iterator + || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator + } + + function compareStructuralEquality(a, b, cache) { + var aKeys = []; + for (var key in a) aKeys.push(key); + + var bKeys = []; + for (var key in b) bKeys.push(key); + + if (aKeys.length !== bKeys.length) { + return NOT_EQUAL; + } + + aKeys.sort(); + bKeys.sort(); + + for (var i = 0; i < aKeys.length; i++) { + var aKey = aKeys[i]; + var bKey = bKeys[i]; + if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + + return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || EQUAL; + } + + function isIterableEquatable(value) { + return typeof Symbol === 'function' + && typeof value[Symbol.iterator] === 'function'; + } + + function compareIteratorEquality(a, b, cache) { + if (typeof Map === 'function' && a instanceof Map && b instanceof Map || + typeof Set === 'function' && a instanceof Set && b instanceof Set) { + if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size + } + + var ar, br; + while (true) { + ar = a.next(); + br = b.next(); + if (ar.done) { + if (br.done) return EQUAL; + if (b.return) b.return(); + return NOT_EQUAL; + } + if (br.done) { + if (a.return) a.return(); + return NOT_EQUAL; + } + if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) { + if (a.return) a.return(); + if (b.return) b.return(); + return NOT_EQUAL; + } + } + } + + function compareIterableEquality(a, b, cache) { + return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache); + } + + function cacheComparison(a, b, compare, cache) { + var result = compare(a, b, cache); + if (cache && (result === EQUAL || result === NOT_EQUAL)) { + setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result)); + } + return result; + } + + function fail() { + return NOT_EQUAL; + } + + function setCache(cache, left, right, result) { + var otherCache; + + otherCache = cache.get(left); + if (!otherCache) cache.set(left, otherCache = new Map()); + otherCache.set(right, result); + + otherCache = cache.get(right); + if (!otherCache) cache.set(right, otherCache = new Map()); + otherCache.set(left, result); + } + + function getCache(cache, left, right) { + var otherCache; + var result; + + otherCache = cache.get(left); + result = otherCache && otherCache.get(right); + if (result) return result; + + otherCache = cache.get(right); + result = otherCache && otherCache.get(left); + if (result) return result; + + return UNKNOWN; + } + + return deepEqual; +})(); + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/subclassing-ignored.js new file mode 100644 index 000000000000..252b935606f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/add/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: Objects of a subclass are never created as return values for add() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainYearMonth, + [2000, 5], + "add", + [{ months: 1 }], + (result) => TemporalHelpers.assertPlainYearMonth(result, 2000, 6, "M06"), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/calendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/calendar/prop-desc.js new file mode 100644 index 000000000000..c6afa39c62e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/calendar/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.calendar +description: The "calendar" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "calendar"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInMonth/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInMonth/basic.js new file mode 100644 index 000000000000..98fcf082d9a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInMonth/basic.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.daysinmonth +description: daysInMonth works +features: [Temporal] +---*/ + +const ym = new Temporal.PlainYearMonth(1976, 11); +assert.sameValue(ym.daysInMonth, 30); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInMonth/prop-desc.js new file mode 100644 index 000000000000..33ad543f3f5d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInMonth/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.daysinmonth +description: The "daysInMonth" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "daysInMonth"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInYear/basic.js new file mode 100644 index 000000000000..72d413c67939 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInYear/basic.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.daysinyear +description: daysInYear works +features: [Temporal] +---*/ + +const ym = new Temporal.PlainYearMonth(1976, 11); +assert.sameValue(ym.daysInYear, 366); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInYear/prop-desc.js new file mode 100644 index 000000000000..7d0b371f641c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/daysInYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.daysinyear +description: The "daysInYear" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "daysInYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-cast.js new file mode 100644 index 000000000000..9a85ff5e50a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-cast.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: equals() casts its argument +features: [Temporal] +---*/ + +const nov94 = Temporal.PlainYearMonth.from("1994-11"); + +assert.sameValue(nov94.equals({ year: 2013, month: 6 }), false, "object"); +assert.sameValue(nov94.equals({ year: 1994, month: 11 }), true, "object"); +assert.sameValue(nov94.equals("2013-06"), false, "string"); +assert.sameValue(nov94.equals("1994-11"), true, "string"); +assert.throws(TypeError, () => nov94.equals({ year: 2013 }), "missing property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..ceaec14c173e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: RangeError thrown if a string with UTC designator is used as a PlainYearMonth +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainYearMonth(2000, 5); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "String with UTC designator should not be valid as a PlainYearMonth" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-wrong-type.js new file mode 100644 index 000000000000..7697a73a8080 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/argument-wrong-type.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: Appropriate error thrown when argument cannot be converted to a valid string +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5, day: 2 }); + +assert.throws(RangeError, () => instance.equals(undefined), "undefined"); +assert.throws(RangeError, () => instance.equals(null), "null"); +assert.throws(RangeError, () => instance.equals(true), "true"); +assert.throws(RangeError, () => instance.equals(""), "empty string"); +assert.throws(TypeError, () => instance.equals(Symbol()), "symbol"); +assert.throws(RangeError, () => instance.equals(1), "1"); +assert.throws(TypeError, () => instance.equals({}), "plain object"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainYearMonth), "Temporal.PlainYearMonth"); +assert.throws(TypeError, () => instance.equals(Temporal.PlainYearMonth.prototype), "Temporal.PlainYearMonth.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/basic.js new file mode 100644 index 000000000000..8ace1936ff59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/basic.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: Basic tests for equals() +features: [Temporal] +---*/ + +const nov94 = Temporal.PlainYearMonth.from("1994-11"); +const nov94bis = Temporal.PlainYearMonth.from("1994-11"); +const jun13 = Temporal.PlainYearMonth.from("2013-06"); +assert.sameValue(nov94.equals(nov94), true, "same object"); +assert.sameValue(nov94.equals(nov94bis), true, "different object"); +assert.sameValue(nov94.equals(jun13), false, "different year-months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/builtin.js new file mode 100644 index 000000000000..663795e815ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: > + Tests that Temporal.PlainYearMonth.prototype.equals + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.equals), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.equals), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.equals), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.equals.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-fields-iterable.js new file mode 100644 index 000000000000..7a1e6776e3aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalYearMonth(_other_). + sec-temporal-totemporalyearmonth step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +yearmonth.equals({ year: 2005, month: 6, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-temporal-object.js new file mode 100644 index 000000000000..208d8d8d38ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainyearmonth.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalYearMonth(_other_). + sec-temporal-totemporalyearmonth step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const yearmonth = new Temporal.PlainYearMonth(2000, 5, temporalObject); + yearmonth.equals({ year: 2005, month: 6, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-yearmonthfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..88b389bef90c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +let instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.equals({ year: 2000, month: 6, calendar }); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to yearMonthFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +calendar = new Temporal.Calendar("iso8601"); +instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.equals("2000-06-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/compare-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/compare-calendar.js new file mode 100644 index 000000000000..1d7217cfc70b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/compare-calendar.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: equals() takes the calendar into account +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +class CustomCalendar extends Temporal.Calendar { + constructor(id) { + super("iso8601"); + this._id = id; + } + toString() { + actual.push(this._id); + return this._id; + } +} + +const sharedCalendar = new CustomCalendar("a"); +const ym1 = new Temporal.PlainYearMonth(2000, 1, sharedCalendar, 1); +const ym2 = new Temporal.PlainYearMonth(2000, 1, sharedCalendar, 1); +assert.sameValue(ym1.equals(ym2), true); +assert.compareArray(actual, [], "should not call toString if objects are equal"); + +const ym3 = new Temporal.PlainYearMonth(2000, 1, new CustomCalendar("b"), 1); +const ym4 = new Temporal.PlainYearMonth(2000, 1, new CustomCalendar("c"), 2); +assert.sameValue(ym3.equals(ym4), false); +assert.compareArray(actual, [], "should not call toString if ISO dates differ"); + +const ym5 = new Temporal.PlainYearMonth(2000, 1, new CustomCalendar("d"), 1); +const ym6 = new Temporal.PlainYearMonth(2000, 1, new CustomCalendar("e"), 1); +assert.sameValue(ym5.equals(ym6), false); +assert.compareArray(actual, ["d", "e"], "order of operations"); + +actual.splice(0, actual.length); // empty it for the next check +const ym7 = new Temporal.PlainYearMonth(2000, 1, new CustomCalendar("f"), 1); +const ym8 = new Temporal.PlainYearMonth(2000, 1, new CustomCalendar("f"), 1); +assert.sameValue(ym7.equals(ym8), true); +assert.compareArray(actual, ["f", "f"], "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/compare-reference-day.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/compare-reference-day.js new file mode 100644 index 000000000000..3e4fcbd67836 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/compare-reference-day.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: equals() takes the reference day into account +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const ym1 = new Temporal.PlainYearMonth(2000, 1, iso, 1); +const ym2 = new Temporal.PlainYearMonth(2000, 1, iso, 2); +assert.sameValue(ym1.equals(ym2), false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..609e3102952c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +const base = { year: 2000, month: 5 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month"].forEach((prop) => { + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/length.js new file mode 100644 index 000000000000..ba9ef6fa0eb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: Temporal.PlainYearMonth.prototype.equals.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.equals, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/name.js new file mode 100644 index 000000000000..1e3ef11f8352 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: Temporal.PlainYearMonth.prototype.equals.name is "equals". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.equals, "name", { + value: "equals", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/not-a-constructor.js new file mode 100644 index 000000000000..5c744c5b1326 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: > + Temporal.PlainYearMonth.prototype.equals does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.equals(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.equals), false, + "isConstructor(Temporal.PlainYearMonth.prototype.equals)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/prop-desc.js new file mode 100644 index 000000000000..40786d290f93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: The "equals" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.equals, + "function", + "`typeof PlainYearMonth.prototype.equals` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "equals", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/use-internal-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/use-internal-slots.js new file mode 100644 index 000000000000..0d0a6907d811 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/use-internal-slots.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: equals() ignores the observable properties and uses internal slots +features: [Temporal] +---*/ + +function CustomError() {} + +class AvoidGettersYearMonth extends Temporal.PlainYearMonth { + get year() { + throw new CustomError(); + } + get month() { + throw new CustomError(); + } +} + +const one = new AvoidGettersYearMonth(2000, 5); +const two = new AvoidGettersYearMonth(2006, 3); +assert.sameValue(one.equals(two), false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/year-zero.js new file mode 100644 index 000000000000..633cac19a960 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/equals/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: RangeError thrown if a string with UTC designator is used as a PlainYearMonth +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-06', + '-000000-06-24', + '-000000-06-24T15:43:27', + '-000000-06-24T15:43:27+01:00[UTC]' +]; +const instance = new Temporal.PlainYearMonth(2000, 5); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/builtin.js new file mode 100644 index 000000000000..09bb6e98f8e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.getisofields +description: > + Tests that Temporal.PlainYearMonth.prototype.getISOFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.getISOFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.getISOFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.getISOFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.getISOFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-names.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-names.js new file mode 100644 index 000000000000..14d65dbdf23f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-names.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.getisofields +description: Correct field names on the object returned from getISOFields +features: [Temporal] +---*/ + +const ym = new Temporal.PlainYearMonth(2000, 5); + +const result = ym.getISOFields(); +assert.sameValue(result.isoYear, 2000, "isoYear result"); +assert.sameValue(result.isoMonth, 5, "isoMonth result"); +assert.sameValue(result.isoDay, 1, "isoDay result"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-prop-desc.js new file mode 100644 index 000000000000..41eb0c2ec22d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-prop-desc.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.getisofields +description: Properties on the returned object have the correct descriptor +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoMonth", + "isoYear", +]; + +const ym = new Temporal.PlainYearMonth(2000, 5); +const result = ym.getISOFields(); + +for (const property of expected) { + verifyProperty(result, property, { + writable: true, + enumerable: true, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-traversal-order.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-traversal-order.js new file mode 100644 index 000000000000..050bd9d9f732 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/field-traversal-order.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.getisofields +description: Properties added in correct order to object returned from getISOFields +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoMonth", + "isoYear", +]; + +const ym = new Temporal.PlainYearMonth(2000, 5); +const result = ym.getISOFields(); + +assert.compareArray(Object.keys(result), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/length.js new file mode 100644 index 000000000000..469da9d57c34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.getisofields +description: Temporal.PlainYearMonth.prototype.getISOFields.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.getISOFields, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/name.js new file mode 100644 index 000000000000..45ebf4adfcab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.getisofields +description: Temporal.PlainYearMonth.prototype.getISOFields.name is "getISOFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.getISOFields, "name", { + value: "getISOFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/not-a-constructor.js new file mode 100644 index 000000000000..ffbf723387cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.getisofields +description: > + Temporal.PlainYearMonth.prototype.getISOFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.getISOFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.getISOFields), false, + "isConstructor(Temporal.PlainYearMonth.prototype.getISOFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/prop-desc.js new file mode 100644 index 000000000000..7e6c0d2b44cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.getisofields +description: The "getISOFields" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.getISOFields, + "function", + "`typeof PlainYearMonth.prototype.getISOFields` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "getISOFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/getISOFields/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/inLeapYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/inLeapYear/prop-desc.js new file mode 100644 index 000000000000..2726cdb66ece --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/inLeapYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.inleapyear +description: The "inLeapYear" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "inLeapYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/month/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/month/calendar-returns-infinity.js new file mode 100644 index 000000000000..7f2abd4f6696 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/month/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.month +description: Getter throws if the calendar returns ±∞ from its month method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + month() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainYearMonth(2000, 5, pos); +assert.throws(RangeError, () => instance1.month); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainYearMonth(2000, 5, neg); +assert.throws(RangeError, () => instance2.month); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/month/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/month/prop-desc.js new file mode 100644 index 000000000000..fc1aeb0f568f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/month/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.month +description: The "month" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "month"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthCode/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthCode/prop-desc.js new file mode 100644 index 000000000000..606fd63ba1a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthCode/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.monthcode +description: The "monthCode" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "monthCode"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthsInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthsInYear/basic.js new file mode 100644 index 000000000000..1e7df364f98a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthsInYear/basic.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.monthsinyear +description: monthsInYear works +features: [Temporal] +---*/ + +const ym = new Temporal.PlainYearMonth(1976, 11); +assert.sameValue(ym.monthsInYear, 12); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthsInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthsInYear/prop-desc.js new file mode 100644 index 000000000000..fe1da95c6baf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/monthsInYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.monthsinyear +description: The "monthsInYear" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "monthsInYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/prop-desc.js new file mode 100644 index 000000000000..ad89e59c5950 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-plainyearmonth-prototype +description: The "prototype" property of Temporal.PlainYearMonth +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.PlainYearMonth.prototype, "object"); +assert.notSameValue(Temporal.PlainYearMonth.prototype, null); + +verifyProperty(Temporal.PlainYearMonth, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/argument-casting.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/argument-casting.js new file mode 100644 index 000000000000..935041981f49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/argument-casting.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Calls to PYM.since cast arguments. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const nov94 = new Temporal.PlainYearMonth(1994, 11); +const jun13 = new Temporal.PlainYearMonth(2013, 6); +const diff = jun13.since(nov94); + +TemporalHelpers.assertDurationsEqual(jun13.since({ year: 1994, month: 11 }), diff, 'Casts object argument'); +TemporalHelpers.assertDurationsEqual(jun13.since('1994-11'), diff, 'Casts string argument'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..e4413f1797d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: RangeError thrown if a string with UTC designator is used as a PlainYearMonth +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainYearMonth(2000, 5); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + "String with UTC designator should not be valid as a PlainYearMonth" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/arguments-missing-throws.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/arguments-missing-throws.js new file mode 100644 index 000000000000..70992188b85f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/arguments-missing-throws.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Calls to PYM.since throw when missing required arguments. +features: [Temporal] +---*/ + +const jun13 = new Temporal.PlainYearMonth(2013, 6); + +assert.throws(TypeError, () => jun13.since({ year: 1994 }), 'Throws when missing required month'); +assert.throws(TypeError, () => jun13.since({ month: 11 }), 'Throws when missing required year'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/builtin.js new file mode 100644 index 000000000000..cec438872613 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: > + Tests that Temporal.PlainYearMonth.prototype.since + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.since), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.since), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.since), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.since.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..c5bc12c0f9e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.PlainYearMonth(1970, 1, calendar); +instance.since(new Temporal.PlainYearMonth(2000, 5, calendar), { smallestUnit: "year" }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..91395b637c27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.since({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..50be2be006a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.plainyearmonth.prototype.since steps 21–22: + 21. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _largestUnit_). + 22. Let _result_ be ? CalendarDateUntil(_calendar_, _thisDate_, _otherDate_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.PlainYearMonth(2000, 5, calendar); + const later = new Temporal.PlainYearMonth(2001, 6, calendar); + later.since(earlier, { largestUnit }); + }, + { + years: ["year"], + months: ["month"] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-fields-iterable.js new file mode 100644 index 000000000000..feec85e07bb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-fields-iterable.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.prototype.since step 3: + 3. Set _other_ to ? ToTemporalYearMonth(_other_). + sec-temporal.plainyearmonth.prototype.since step 14: + 14. Let fieldNames be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »). + sec-temporal-totemporalyearmonth step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "monthCode", + "year", +]; +const expected2 = [ + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +yearmonth.since({ year: 2005, month: 6, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 1, "fields() method not called"); +assert.compareArray(calendar1.fieldsCalledWith[0], expected1, "fields() method called with correct args"); +assert(calendar1.iteratorExhausted[0], "iterated through the whole iterable"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected2, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-temporal-object.js new file mode 100644 index 000000000000..8f42d51ecb06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainyearmonth.prototype.since step 3: + 3. Set _other_ to ? ToTemporalYearMonth(_other_). + sec-temporal-totemporalyearmonth step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const yearmonth = new Temporal.PlainYearMonth(2000, 5, temporalObject); + yearmonth.since({ year: 2005, month: 6, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-yearmonthfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..27168043ddca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +let instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.since({ year: 2000, month: 6, calendar }); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to yearMonthFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +calendar = new Temporal.Calendar("iso8601"); +instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.since("2000-06-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..0b734a33f972 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.prototype.since +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +const base = { year: 2000, month: 5 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month"].forEach((prop) => { + assert.throws(RangeError, () => instance.since({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.since({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-auto.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-auto.js new file mode 100644 index 000000000000..84cf48746cf4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-auto.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: auto value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.assertDuration(later.since(earlier, { largestUnit: "auto" }), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "auto largestUnit is year (pos)"); +TemporalHelpers.assertDuration(earlier.since(later, { largestUnit: "auto" }), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "auto largestUnit is year (neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-disallowed-units.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-disallowed-units.js new file mode 100644 index 000000000000..54266bd95167 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-disallowed-units.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Since throws on to0-small largestUnit +features: [Temporal, arrow-function] +---*/ + +const earlier = new Temporal.PlainYearMonth(2019, 1); +const later = new Temporal.PlainYearMonth(2021, 9); + +[ + 'weeks', + 'days', + 'hours', + 'minutes', + 'seconds', + 'milliseconds', + 'microseconds', + 'nanoseconds' +].forEach((largestUnit) => { + assert.throws(RangeError, () => later.since(earlier, { largestUnit }),`throws on disallowed or invalid largestUnit: ${largestUnit}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string.js new file mode 100644 index 000000000000..f98aa5e66e25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const values = ["era", "eraYear", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-months.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-months.js new file mode 100644 index 000000000000..38d47d02da16 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-months.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: months value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.assertDuration(later.since(earlier, { largestUnit: "months" }), + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, "largestUnit is months (pos)"); +TemporalHelpers.assertDuration(earlier.since(later, { largestUnit: "months" }), + 0, -13, 0, 0, 0, 0, 0, 0, 0, 0, "largestUnit is months (neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..a4e1001db20c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-plurals-accepted.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const validUnits = [ + "year", + "month", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => later.since(earlier, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..43da239747ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const units = ["years", "months"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => later.since(earlier, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-undefined.js new file mode 100644 index 000000000000..44bcdab59df6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.assertDuration(later.since(earlier, { largestUnit: undefined }), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (explicit, pos)"); +TemporalHelpers.assertDuration(earlier.since(later, { largestUnit: undefined }), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (explicit, neg)"); + +TemporalHelpers.assertDuration(later.since(earlier, {}), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (implicit, pos)"); +TemporalHelpers.assertDuration(earlier.since(later, {}), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (implicit, neg)"); + +TemporalHelpers.assertDuration(later.since(earlier, () => {}), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (arrow function, pos)"); +TemporalHelpers.assertDuration(earlier.since(later, () => {}), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (arrow function, neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-wrong-type.js new file mode 100644 index 000000000000..75f1dd1e2a1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "month", + (largestUnit) => later.since(earlier, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-years.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-years.js new file mode 100644 index 000000000000..b7649915c750 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-years.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: years value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.assertDuration(later.since(earlier, { largestUnit: "years" }), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "largestUnit is years (pos)"); +TemporalHelpers.assertDuration(earlier.since(later, { largestUnit: "years" }), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "largestUnit is years (neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/length.js new file mode 100644 index 000000000000..942d5a4c2ea0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Temporal.PlainYearMonth.prototype.since.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.since, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/mixed-calendar-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/mixed-calendar-invalid.js new file mode 100644 index 000000000000..250cefd27c94 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/mixed-calendar-invalid.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Mixed calendars throw as invalid +features: [Temporal] +---*/ + +class customCal extends Temporal.Calendar { + constructor () { + super('iso8601'); + } + + toString() { + return "I am a secret cal."; + } +} + +const ym1 = new Temporal.PlainYearMonth(2000, 1); +const ym2 = new Temporal.PlainYearMonth(2000, 1, new customCal()); + +assert.throws(RangeError, () => ym1.since(ym2), 'since throws with different calendars'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/name.js new file mode 100644 index 000000000000..298f93489f22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Temporal.PlainYearMonth.prototype.since.name is "since". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.since, "name", { + value: "since", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/not-a-constructor.js new file mode 100644 index 000000000000..e4e0d3fab929 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: > + Temporal.PlainYearMonth.prototype.since does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.since(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.since), false, + "isConstructor(Temporal.PlainYearMonth.prototype.since)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/options-invalid.js new file mode 100644 index 000000000000..8bb77ebc7618 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/options-invalid.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Verify that invalid options are handled correctly. +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainYearMonth(2020, 2); +const feb21 = new Temporal.PlainYearMonth(2021, 2); + +[ + null, + 1, + 'hello', + true, + Symbol('foo'), + 1n +].forEach((badOption) => + assert.throws(TypeError, () => feb21.since(feb20, badOption), `${String(badOption)} throws TypeError`) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/options-undefined.js new file mode 100644 index 000000000000..a7214222f687 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/options-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Verify that undefined options are handled correctly. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2002, 12); + +TemporalHelpers.assertDuration(later.since(earlier, undefined), + 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (explicit, pos)"); +TemporalHelpers.assertDuration(earlier.since(later, undefined), + -2, -7, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (explicit, neg)"); + +TemporalHelpers.assertDuration(later.since(earlier), + 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (implicit, pos)"); +TemporalHelpers.assertDuration(earlier.since(later), + -2, -7, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (implicit, neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/prop-desc.js new file mode 100644 index 000000000000..39aebf9be408 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: The "since" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.since, + "function", + "`typeof PlainYearMonth.prototype.since` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "since", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js new file mode 100644 index 000000000000..e74f894245d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Since rounding increments work as expected +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2019, 1); +const later = new Temporal.PlainYearMonth(2021, 9); + +const laterSinceYear = later.since(earlier, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" }); +TemporalHelpers.assertDuration(laterSinceYear, + /* years = */ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rounds to an increment of years"); + +const laterSinceMixed = later.since(earlier, { smallestUnit: "months", roundingIncrement: 5 }); +TemporalHelpers.assertDuration(laterSinceMixed, + /* years = */ 2, /* months = */ 5, 0, 0, 0, 0, 0, 0, 0, 0, "rounds to an increment of months mixed with years"); + +const laterSinceMonth = later.since(earlier, { largestUnit: "months", smallestUnit: "months", roundingIncrement: 10 }); +TemporalHelpers.assertDuration(laterSinceMonth, + 0, /* months = */ 30, 0, 0, 0, 0, 0, 0, 0, 0, "rounds to an increment of pure months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-nan.js new file mode 100644 index 000000000000..286ac1045eac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plainyearmonth.prototype.since step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-non-integer.js new file mode 100644 index 000000000000..7259c8a87584 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2000, 10); +const result = later.since(earlier, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..439802d8116d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2000, 10); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -1 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 0 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-undefined.js new file mode 100644 index 000000000000..fbb83036d3f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plainyearmonth.prototype.since step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +const explicit = later.since(earlier, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1"); + +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..00785a59a03b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plainyearmonth.prototype.since step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => later.since(earlier, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-ceil.js new file mode 100644 index 000000000000..e2646d018098 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-ceil.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainYearMonth.from("2019-01"); +const later = Temporal.PlainYearMonth.from("2021-09"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "ceil" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "years", roundingMode: "ceil" }), + /* years = */ -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "ceil" }), + /* years = */ 2, /* months = */ 8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "months", roundingMode: "ceil" }), + /* years = */ -2, /* months = */ -8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-floor.js new file mode 100644 index 000000000000..98a5c805a4b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-floor.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainYearMonth.from("2019-01"); +const later = Temporal.PlainYearMonth.from("2021-09"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "floor" }), + /* years = */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "years", roundingMode: "floor" }), + /* years = */ -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "floor" }), + /* years = */ 2, /* months = */ 8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "months", roundingMode: "floor" }), + /* years = */ -2, /* months = */ -8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfExpand.js new file mode 100644 index 000000000000..7ccdf33d7462 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-halfExpand.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainYearMonth.from("2019-01"); +const later = Temporal.PlainYearMonth.from("2021-09"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "halfExpand" }), + /* years = */ 2, /* months = */ 8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "months", roundingMode: "halfExpand" }), + /* years = */ -2, /* months = */ -8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string.js new file mode 100644 index 000000000000..7a3a406354cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-trunc.js new file mode 100644 index 000000000000..14ba76dde994 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-trunc.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainYearMonth.from("2019-01"); +const later = Temporal.PlainYearMonth.from("2021-09"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "years", roundingMode: "trunc" }), + /* years = */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "years", roundingMode: "trunc" }), + /* years = */ -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "months", roundingMode: "trunc" }), + /* years = */ 2, /* months = */ 8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "months", roundingMode: "trunc" }), + /* years = */ -2, /* months = */ -8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-undefined.js new file mode 100644 index 000000000000..1a9f675f5ef9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 1); + +const later1 = new Temporal.PlainYearMonth(2005, 2); +const explicit1 = later1.since(earlier, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit1 = later1.since(earlier, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +const later2 = new Temporal.PlainYearMonth(2005, 12); +const explicit2 = later2.since(earlier, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit2 = later2.since(earlier, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-wrong-type.js new file mode 100644 index 000000000000..afae24365289 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => later.since(earlier, { smallestUnit: "year", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string.js new file mode 100644 index 000000000000..c49cdb86546a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const values = ["era", "eraYear", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..d9291ee83f67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-plurals-accepted.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const validUnits = [ + "year", + "month", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => later.since(earlier, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-undefined.js new file mode 100644 index 000000000000..63a3e23bed86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +const explicit = later.since(earlier, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default smallestUnit is month"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default smallestUnit is month"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-wrong-type.js new file mode 100644 index 000000000000..a2f00046ed4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year", + (smallestUnit) => later.since(earlier, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/symmetry.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/symmetry.js new file mode 100644 index 000000000000..9684be692fde --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/symmetry.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: Since observes symmetry with until +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const nov94 = new Temporal.PlainYearMonth(1994, 11); +const jun13 = new Temporal.PlainYearMonth(2013, 6); +const diff = jun13.since(nov94); + +TemporalHelpers.assertDurationsEqual(diff, nov94.until(jun13), 'Since is inverse of until'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/year-zero.js new file mode 100644 index 000000000000..67ddd452c278 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/since/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: RangeError thrown if a string with UTC designator is used as a PlainYearMonth +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-06', + '-000000-06-24', + '-000000-06-24T15:43:27', + '-000000-06-24T15:43:27+01:00[UTC]' +]; +const instance = new Temporal.PlainYearMonth(2000, 5); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-duration-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-duration-object.js new file mode 100644 index 000000000000..7f7430d58e1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-duration-object.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: A Duration object is supported as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const jun13 = Temporal.PlainYearMonth.from("2013-06"); +const diff = Temporal.Duration.from("P18Y7M"); +TemporalHelpers.assertPlainYearMonth(jun13.subtract(diff), 1994, 11, "M11"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-lower-units.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-lower-units.js new file mode 100644 index 000000000000..867c76830a14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-lower-units.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Using lower units in subtract() works +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); + +const tests = [ + [{ days: 1 }, 2019, 11, "M11"], + [{ hours: 1 }, 2019, 11, "M11"], + [{ minutes: 1 }, 2019, 11, "M11"], + [{ seconds: 1 }, 2019, 11, "M11"], + [{ milliseconds: 1 }, 2019, 11, "M11"], + [{ microseconds: 1 }, 2019, 11, "M11"], + [{ nanoseconds: 1 }, 2019, 11, "M11"], + [{ days: 29 }, 2019, 11, "M11"], + [{ days: 30 }, 2019, 10, "M10"], + [{ days: 60 }, 2019, 10, "M10"], + [{ days: 61 }, 2019, 9, "M09"], + [{ hours: 720 }, 2019, 10, "M10"], + [{ minutes: 43200 }, 2019, 10, "M10"], + [{ seconds: 2592000 }, 2019, 10, "M10"], + [{ milliseconds: 2592000_000 }, 2019, 10, "M10"], + [{ microseconds: 2592000_000_000 }, 2019, 10, "M10"], + [{ nanoseconds: 2592000_000_000_000 }, 2019, 10, "M10"], +]; + +for (const [argument, ...expected] of tests) { + TemporalHelpers.assertPlainYearMonth(ym.subtract(argument), ...expected, "no options"); + TemporalHelpers.assertPlainYearMonth(ym.subtract(argument, { overflow: "constrain" }), ...expected, "constrain"); + TemporalHelpers.assertPlainYearMonth(ym.subtract(argument, { overflow: "reject" }), ...expected, "reject"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-not-object.js new file mode 100644 index 000000000000..c3ae06707425 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Passing a primitive other than string to subtract() throws +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5 }); +assert.throws(RangeError, () => instance.subtract(undefined), "undefined"); +assert.throws(RangeError, () => instance.subtract(null), "null"); +assert.throws(RangeError, () => instance.subtract(true), "boolean"); +assert.throws(RangeError, () => instance.subtract(""), "empty string"); +assert.throws(TypeError, () => instance.subtract(Symbol()), "Symbol"); +assert.throws(RangeError, () => instance.subtract(7), "number"); +assert.throws(RangeError, () => instance.subtract(7n), "bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object-invalid.js new file mode 100644 index 000000000000..cb335b310484 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object-invalid.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Mixed positive and negative values or missing properties always throw +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); +for (const overflow of ["constrain", "reject"]) { + assert.throws(RangeError, () => ym.subtract({ years: 1, months: -6 }, { overflow }), overflow) +} + +assert.throws(TypeError, () => ym.subtract({}), "no properties"); +assert.throws(TypeError, () => ym.subtract({ month: 12 }), "only singular 'month' property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object-plural.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object-plural.js new file mode 100644 index 000000000000..33c8d39f7875 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object-plural.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Singular properties are ignored +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); +TemporalHelpers.assertPlainYearMonth(ym.subtract({ month: 1, years: 1 }), 2018, 11, "M11"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object.js new file mode 100644 index 000000000000..b1a96419612a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-object.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Passing an object to subtract() works +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); + +const tests = [ + [{ months: 2 }, 2019, 9, "M09"], + [{ years: 1 }, 2018, 11, "M11"], + [{ months: -2 }, 2020, 1, "M01"], + [{ years: -1 }, 2020, 11, "M11"], +]; + +for (const [argument, ...expected] of tests) { + TemporalHelpers.assertPlainYearMonth(ym.subtract(argument), ...expected, "no options"); + TemporalHelpers.assertPlainYearMonth(ym.subtract(argument, { overflow: "constrain" }), ...expected, "constrain"); + TemporalHelpers.assertPlainYearMonth(ym.subtract(argument, { overflow: "reject" }), ...expected, "reject"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..542c9c66e8bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); + +const resultHours = instance.subtract("-PT24.567890123H"); +TemporalHelpers.assertPlainYearMonth(resultHours, 2000, 5, "M05", "negative fractional hours"); + +const resultMinutes = instance.subtract("-PT1440.567890123M"); +TemporalHelpers.assertPlainYearMonth(resultMinutes, 2000, 5, "M05", "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-string.js new file mode 100644 index 000000000000..c933d9c5deac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5 }); +const result = instance.subtract("P3M"); +TemporalHelpers.assertPlainYearMonth(result, 2000, 2, "M02"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/builtin.js new file mode 100644 index 000000000000..7d150bd267d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: > + Tests that Temporal.PlainYearMonth.prototype.subtract + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.subtract), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.subtract), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.subtract), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.subtract.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-arguments-extra-options.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-arguments-extra-options.js new file mode 100644 index 000000000000..ffad884d2802 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-arguments-extra-options.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: plainyearmonth.prototype.subtract should pass extra fields in copied options objects. +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 5. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "get extra", + "get overflow", +]; +const options = new Proxy({ extra: 5 }, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateAdd(date, duration, options) { + const result = super.dateAdd(date, duration, options); + options.overflow = 'meatloaf'; + return result; + } + yearMonthFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.notSameValue(args[1], options, "args[1]"); + return super.yearMonthFromFields(...args); + } +} +const plainYearMonth = new Temporal.PlainYearMonth(2000, 3, new CustomCalendar()); +const result = plainYearMonth.subtract({ months: 5 }, options); +TemporalHelpers.assertPlainYearMonth(result, 1999, 10, "M10"); +assert.compareArray(actual, expected, "extra field options object order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-arguments.js new file mode 100644 index 000000000000..034012fbbc7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-arguments.js @@ -0,0 +1,61 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: plainyearmonth.prototype.subtract should respect calendar arguments and pass copied options objects. +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 5. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "get overflow", + "get overflow", + "get overflow.toString", + "call overflow.toString", + "get overflow.toString", + "call overflow.toString", +]; +const options = new Proxy({ overflow: "constrain" }, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateAdd(date, duration, options) { + const result = super.dateAdd(date, duration, options); + options.overflow = 'meatloaf'; + return result; + } + yearMonthFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.notSameValue(args[1], options, "args[1]"); + return super.yearMonthFromFields(...args); + } +} +const plainYearMonth = new Temporal.PlainYearMonth(2000, 7, new CustomCalendar()); +const result = plainYearMonth.subtract({ months: 9 }, options); +TemporalHelpers.assertPlainYearMonth(result, 1999, 10, "M10"); +assert.compareArray(actual, expected, "copied options object order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-datefromfields-called.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-datefromfields-called.js new file mode 100644 index 000000000000..633a2c42e74a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-datefromfields-called.js @@ -0,0 +1,150 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: > + Calls calendar's dateFromFields method to obtain a start date for the + operation, based on the sign of the duration +info: | + 9. Let _fields_ be ? PrepareTemporalFields(_yearMonth_, _fieldNames_, «»). + 10. Let _sign_ be ! DurationSign(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _balanceResult_.[[Days]], 0, 0, 0, 0, 0, 0). + 11. If _sign_ < 0, then + a. Let _dayFromCalendar_ be ? CalendarDaysInMonth(_calendar_, _yearMonth_). + b. Let _day_ be ? ToPositiveInteger(_dayFromCalendar_). + 12. Else, + a. Let _day_ be 1. + 13. Perform ! CreateDataPropertyOrThrow(_fields_, *"day"*, _day_). + 14. Let _date_ be ? DateFromFields(_calendar_, _fields_, *undefined*). +includes: [deepEqual.js, temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCalls = []; + } + year(date) { + // years in this calendar start and end on the same day as ISO 8601 years + return date.getISOFields().isoYear; + } + month(date) { + // this calendar has 10 months of 36 days each, plus an 11th month of 5 or 6 + const { isoYear, isoMonth, isoDay } = date.getISOFields(); + const isoDate = new Temporal.PlainDate(isoYear, isoMonth, isoDay); + return Math.floor((isoDate.dayOfYear - 1) / 36) + 1; + } + monthCode(date) { + return "M" + this.month(date).toString().padStart(2, "0"); + } + day(date) { + return (date.dayOfYear - 1) % 36 + 1; + } + daysInMonth(date) { + if (this.month(date) < 11) return 36; + return this.daysInYear(date) - 360; + } + _dateFromFieldsImpl({ year, month, monthCode, day }) { + if (year === undefined) throw new TypeError("year required"); + if (month === undefined && monthCode === undefined) throw new TypeError("one of month or monthCode required"); + if (month !== undefined && month < 1) throw new RangeError("month < 1"); + if (day === undefined) throw new TypeError("day required"); + + if (monthCode !== undefined) { + const numberPart = +(monthCode.slice(1)); + if ("M" + `${numberPart}`.padStart(2, "0") !== monthCode) throw new RangeError("invalid monthCode"); + if (month === undefined) { + month = numberPart; + } else if (month !== numberPart) { + throw new RangeError("month and monthCode must match"); + } + } + + const isoDayOfYear = (month - 1) * 36 + day; + return new Temporal.PlainDate(year, 1, 1).add({ days: isoDayOfYear - 1 }).withCalendar(this); + } + dateFromFields(...args) { + this.dateFromFieldsCalls.push(args); + return this._dateFromFieldsImpl(...args); + } + yearMonthFromFields(fields, options) { + const { isoYear, isoMonth, isoDay } = this._dateFromFieldsImpl({ ...fields, day: 1 }, options).getISOFields(); + return new Temporal.PlainYearMonth(isoYear, isoMonth, this, isoDay); + } + monthDayFromFields(fields, options) { + const { isoYear, isoMonth, isoDay } = this._dateFromFieldsImpl({ ...fields, year: 2000 }, options).getISOFields(); + return new Temporal.PlainMonthDay(isoMonth, isoDay, this, isoYear); + } + dateAdd(date, duration, options) { + if (duration.months) throw new Error("adding months not implemented in this test"); + return super.dateAdd(date, duration, options); + } + toString() { + return "thirty-six"; + } +} + +const calendar = new CustomCalendar(); +const month2 = Temporal.PlainYearMonth.from({ year: 2022, month: 2, calendar }); +const lessThanOneMonth = new Temporal.Duration(0, 0, 0, 35); +const oneMonth = new Temporal.Duration(0, 0, 0, 36); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.subtract(lessThanOneMonth), + 2022, 2, "M02", + "subtracting positive less than one month's worth of days yields the same month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 36 }, + "last day of month 2 passed to dateFromFields when subtracting positive duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.subtract(oneMonth), + 2022, 1, "M01", + "subtracting positive one month's worth of days yields the previous month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 36 }, + "last day of month 2 passed to dateFromFields when subtracting positive duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.subtract(lessThanOneMonth.negated()), + 2022, 2, "M02", + "subtracting negative less than one month's worth of days yields the same month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 1 }, + "first day of month 2 passed to dateFromFields when subtracting negative duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.subtract(oneMonth.negated()), + 2022, 3, "M03", + "subtracting negative one month's worth of days yields the following month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 1 }, + "first day of month 2 passed to dateFromFields when subtracting negative duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-daysinmonth-wrong-value.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-daysinmonth-wrong-value.js new file mode 100644 index 000000000000..0774510da6f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-daysinmonth-wrong-value.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: > + The appropriate error is thrown if the calendar's daysInMonth method returns a + value that cannot be converted to a positive integer +includes: [compareArray.js] +features: [BigInt, Symbol, Temporal] +---*/ + +const actual = []; +class CalendarDaysInMonthWrongValue extends Temporal.Calendar { + constructor(badValue) { + super("iso8601"); + this._badValue = badValue; + } + dateFromFields(fields, options) { + actual.push("call dateFromFields"); + return super.dateFromFields(fields, options); + } + daysInMonth() { + return this._badValue; + } +} +// daysInMonth is only called if we are subtracting a positive duration +const duration = new Temporal.Duration(1, 1); + +[Infinity, -Infinity, -42].forEach((badValue) => { + const calendar = new CalendarDaysInMonthWrongValue(badValue); + const yearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + assert.throws(RangeError, () => yearMonth.subtract(duration), `daysInMonth ${badValue}`); + assert.compareArray(actual, [], "dateFromFields not called"); +}); + +[Symbol('foo'), 31n].forEach((badValue) => { + const calendar = new CalendarDaysInMonthWrongValue(badValue); + const yearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + assert.throws(TypeError, () => yearMonth.subtract(duration), `daysInMonth ${typeof badValue}`); + assert.compareArray(actual, [], "dateFromFields not called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-fields-iterable.js new file mode 100644 index 000000000000..f5d394272f98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-fields-iterable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.prototype.subtract step 8: + 8. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +yearmonth.subtract({ months: 1 }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..95e5b0f26ff9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/infinity-throws-rangeerror.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainYearMonth.prototype.subtract throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plainyearmonth.prototype.subtract +features: [Temporal] +---*/ +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/length.js new file mode 100644 index 000000000000..57601540ea69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Temporal.PlainYearMonth.prototype.subtract.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.subtract, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/limits.js new file mode 100644 index 000000000000..4c4d64b0cb21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/limits.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: RangeError thrown when going out of range +features: [Temporal] +---*/ + +const min = Temporal.PlainYearMonth.from("-271821-04"); +for (const overflow of ["reject", "constrain"]) { + assert.throws(RangeError, () => min.subtract({ months: 1 }, { overflow }), overflow); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/month-length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/month-length.js new file mode 100644 index 000000000000..84654d97e1de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/month-length.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: subtract() takes month length into account +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); + +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2019-02").subtract({ days: 27 }), + 2019, 2, "M02"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2019-02").subtract({ days: 28 }), + 2019, 1, "M01"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2020-02").subtract({ days: 28 }), + 2020, 2, "M02"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2020-02").subtract({ days: 29 }), + 2020, 1, "M01"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2019-11").subtract({ days: 29 }), + 2019, 11, "M11"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2019-11").subtract({ days: 30 }), + 2019, 10, "M10"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2020-01").subtract({ days: 30 }), + 2020, 1, "M01"); +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from("2020-01").subtract({ days: 31 }), + 2019, 12, "M12"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/name.js new file mode 100644 index 000000000000..9375aa397ba2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Temporal.PlainYearMonth.prototype.subtract.name is "subtract". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.subtract, "name", { + value: "subtract", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/negative-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..18e5e88f951f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainYearMonth.prototype.subtract throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plainyearmonth.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainYearMonth.from({ year: 2000, month: 5 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..2cfd93a60d20 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.subtract({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/not-a-constructor.js new file mode 100644 index 000000000000..3fe2371f32c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: > + Temporal.PlainYearMonth.prototype.subtract does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.subtract(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.subtract), false, + "isConstructor(Temporal.PlainYearMonth.prototype.subtract)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-invalid.js new file mode 100644 index 000000000000..e693885c5a69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-invalid.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Invalid options throw +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-11"); +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +for (const badOptions of values) { + assert.throws(TypeError, () => ym.subtract({ years: 1 }, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-undefined.js new file mode 100644 index 000000000000..c3bffb76f104 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-undefined.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +// overflow option has no effect on addition in the ISO calendar, so verify this +// with a custom calendar +class CheckedAdd extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateAdd(date, duration, options, constructor) { + this.called = true; + assert.notSameValue(options, undefined, "options not undefined"); + return super.dateAdd(date, duration, options, constructor); + } +} +const calendar = new CheckedAdd(); + +const yearmonth = new Temporal.PlainYearMonth(2000, 3, calendar); +const duration = { months: 1 }; + +yearmonth.subtract(duration, undefined); +yearmonth.subtract(duration); + +assert(calendar.called); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/order-of-operations.js new file mode 100644 index 000000000000..492029916163 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/order-of-operations.js @@ -0,0 +1,77 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Properties on an object passed to subtract() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +const expected = [ + "get days", + "get days.valueOf", + "call days.valueOf", + "get hours", + "get hours.valueOf", + "call hours.valueOf", + "get microseconds", + "get microseconds.valueOf", + "call microseconds.valueOf", + "get milliseconds", + "get milliseconds.valueOf", + "call milliseconds.valueOf", + "get minutes", + "get minutes.valueOf", + "call minutes.valueOf", + "get months", + "get months.valueOf", + "call months.valueOf", + "get nanoseconds", + "get nanoseconds.valueOf", + "call nanoseconds.valueOf", + "get seconds", + "get seconds.valueOf", + "call seconds.valueOf", + "get weeks", + "get weeks.valueOf", + "call weeks.valueOf", + "get years", + "get years.valueOf", + "call years.valueOf", +]; +const actual = []; +const fields = { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.subtract(argument); +TemporalHelpers.assertPlainYearMonth(result, 1999, 4, "M04"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js new file mode 100644 index 000000000000..a67589713299 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.subtract steps 13–15: + 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_). + 14. ... + 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_). +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +const duration = new Temporal.Duration(1, 1); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-undefined.js new file mode 100644 index 000000000000..cc022663adc7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-undefined.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.subtract steps 13–15: + 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_). + 14. ... + 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// In the ISO calendar, PlainYearMonth.prototype.subtract() actually ignores the +// overflow option. There is no subtraction in the ISO calendar that we could +// test which would actually show a difference between the 'constrain' and +// 'reject' values. +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +const duration = new Temporal.Duration(1, 1); +const explicit = yearmonth.subtract(duration, { overflow: undefined }); +TemporalHelpers.assertPlainYearMonth(explicit, 1999, 4, "M04", "default overflow is constrain"); +const implicit = yearmonth.subtract(duration, {}); +TemporalHelpers.assertPlainYearMonth(implicit, 1999, 4, "M04", "default overflow is constrain"); +const lambda = yearmonth.subtract(duration, () => {}); +TemporalHelpers.assertPlainYearMonth(lambda, 1999, 4, "M04", "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-wrong-type.js new file mode 100644 index 000000000000..337dd43c0680 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-wrong-type.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.subtract steps 13–15: + 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_). + 14. ... + 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +const duration = new Temporal.Duration(1, 1); + +// See TemporalHelpers.checkStringOptionWrongType(); this code path has +// different expectations for observable calls + +assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: null }), "null"); +assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: true }), "true"); +assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: false }), "false"); +assert.throws(TypeError, () => yearmonth.subtract(duration, { overflow: Symbol() }), "symbol"); +assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: 2 }), "bigint"); +assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: 2n }), "bigint"); +assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: {} }), "plain object"); + +// toString property is read once by Calendar.dateAdd() and then once again by +// calendar.yearMonthFromFields(). +const expected = [ + "get overflow.toString", + "call overflow.toString", + "get overflow.toString", + "call overflow.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); +const result = yearmonth.subtract(duration, { overflow: observer }); +TemporalHelpers.assertPlainYearMonth(result, 1999, 4, "M04", "object with toString"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/prop-desc.js new file mode 100644 index 000000000000..37ad0c808512 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: The "subtract" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.subtract, + "function", + "`typeof PlainYearMonth.prototype.subtract` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "subtract", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/shell.js index e69de29bb2d1..b36293881a43 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/shell.js @@ -0,0 +1,348 @@ +// GENERATED, DO NOT EDIT +// file: deepEqual.js +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Compare two values structurally +defines: [assert.deepEqual] +---*/ + +assert.deepEqual = function(actual, expected, message) { + var format = assert.deepEqual.format; + assert( + assert.deepEqual._compare(actual, expected), + `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}` + ); +}; + +assert.deepEqual.format = function(value, seen) { + switch (typeof value) { + case 'string': + return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`; + case 'number': + case 'boolean': + case 'symbol': + case 'bigint': + return value.toString(); + case 'undefined': + return 'undefined'; + case 'function': + return `[Function${value.name ? `: ${value.name}` : ''}]`; + case 'object': + if (value === null) return 'null'; + if (value instanceof Date) return `Date "${value.toISOString()}"`; + if (value instanceof RegExp) return value.toString(); + if (!seen) { + seen = { + counter: 0, + map: new Map() + }; + } + + let usage = seen.map.get(value); + if (usage) { + usage.used = true; + return `[Ref: #${usage.id}]`; + } + + usage = { id: ++seen.counter, used: false }; + seen.map.set(value, usage); + + if (typeof Set !== "undefined" && value instanceof Set) { + return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (typeof Map !== "undefined" && value instanceof Map) { + return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (Array.isArray ? Array.isArray(value) : value instanceof Array) { + return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`; + } + let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object'; + if (tag === 'Object' && Object.getPrototypeOf(value) === null) { + tag = '[Object: null prototype]'; + } + return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`; + default: + return typeof value; + } +}; + +assert.deepEqual._compare = (function () { + var EQUAL = 1; + var NOT_EQUAL = -1; + var UNKNOWN = 0; + + function deepEqual(a, b) { + return compareEquality(a, b) === EQUAL; + } + + function compareEquality(a, b, cache) { + return compareIf(a, b, isOptional, compareOptionality) + || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality) + || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache) + || NOT_EQUAL; + } + + function compareIf(a, b, test, compare, cache) { + return !test(a) + ? !test(b) ? UNKNOWN : NOT_EQUAL + : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache); + } + + function tryCompareStrictEquality(a, b) { + return a === b ? EQUAL : UNKNOWN; + } + + function tryCompareTypeOfEquality(a, b) { + return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN; + } + + function tryCompareToStringTagEquality(a, b) { + var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined; + var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined; + return aTag !== bTag ? NOT_EQUAL : UNKNOWN; + } + + function isOptional(value) { + return value === undefined + || value === null; + } + + function compareOptionality(a, b) { + return tryCompareStrictEquality(a, b) + || NOT_EQUAL; + } + + function isPrimitiveEquatable(value) { + switch (typeof value) { + case 'string': + case 'number': + case 'bigint': + case 'boolean': + case 'symbol': + return true; + default: + return isBoxed(value); + } + } + + function comparePrimitiveEquality(a, b) { + if (isBoxed(a)) a = a.valueOf(); + if (isBoxed(b)) b = b.valueOf(); + return tryCompareStrictEquality(a, b) + || tryCompareTypeOfEquality(a, b) + || compareIf(a, b, isNaNEquatable, compareNaNEquality) + || NOT_EQUAL; + } + + function isNaNEquatable(value) { + return typeof value === 'number'; + } + + function compareNaNEquality(a, b) { + return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL; + } + + function isObjectEquatable(value) { + return typeof value === 'object'; + } + + function compareObjectEquality(a, b, cache) { + if (!cache) cache = new Map(); + return getCache(cache, a, b) + || setCache(cache, a, b, EQUAL) // consider equal for now + || cacheComparison(a, b, tryCompareStrictEquality, cache) + || cacheComparison(a, b, tryCompareToStringTagEquality, cache) + || compareIf(a, b, isValueOfEquatable, compareValueOfEquality) + || compareIf(a, b, isToStringEquatable, compareToStringEquality) + || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache) + || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache) + || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || cacheComparison(a, b, fail, cache); + } + + function isBoxed(value) { + return value instanceof String + || value instanceof Number + || value instanceof Boolean + || typeof Symbol === 'function' && value instanceof Symbol + || typeof BigInt === 'function' && value instanceof BigInt; + } + + function isValueOfEquatable(value) { + return value instanceof Date; + } + + function compareValueOfEquality(a, b) { + return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isToStringEquatable(value) { + return value instanceof RegExp; + } + + function compareToStringEquality(a, b) { + return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isArrayLikeEquatable(value) { + return (Array.isArray ? Array.isArray(value) : value instanceof Array) + || (typeof Uint8Array === 'function' && value instanceof Uint8Array) + || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray) + || (typeof Uint16Array === 'function' && value instanceof Uint16Array) + || (typeof Uint32Array === 'function' && value instanceof Uint32Array) + || (typeof Int8Array === 'function' && value instanceof Int8Array) + || (typeof Int16Array === 'function' && value instanceof Int16Array) + || (typeof Int32Array === 'function' && value instanceof Int32Array) + || (typeof Float32Array === 'function' && value instanceof Float32Array) + || (typeof Float64Array === 'function' && value instanceof Float64Array) + || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array) + || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array); + } + + function compareArrayLikeEquality(a, b, cache) { + if (a.length !== b.length) return NOT_EQUAL; + for (var i = 0; i < a.length; i++) { + if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + return EQUAL; + } + + function isStructurallyEquatable(value) { + return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference + || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference + || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference + || typeof Map === 'function' && value instanceof Map // comparable via @@iterator + || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator + } + + function compareStructuralEquality(a, b, cache) { + var aKeys = []; + for (var key in a) aKeys.push(key); + + var bKeys = []; + for (var key in b) bKeys.push(key); + + if (aKeys.length !== bKeys.length) { + return NOT_EQUAL; + } + + aKeys.sort(); + bKeys.sort(); + + for (var i = 0; i < aKeys.length; i++) { + var aKey = aKeys[i]; + var bKey = bKeys[i]; + if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + + return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || EQUAL; + } + + function isIterableEquatable(value) { + return typeof Symbol === 'function' + && typeof value[Symbol.iterator] === 'function'; + } + + function compareIteratorEquality(a, b, cache) { + if (typeof Map === 'function' && a instanceof Map && b instanceof Map || + typeof Set === 'function' && a instanceof Set && b instanceof Set) { + if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size + } + + var ar, br; + while (true) { + ar = a.next(); + br = b.next(); + if (ar.done) { + if (br.done) return EQUAL; + if (b.return) b.return(); + return NOT_EQUAL; + } + if (br.done) { + if (a.return) a.return(); + return NOT_EQUAL; + } + if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) { + if (a.return) a.return(); + if (b.return) b.return(); + return NOT_EQUAL; + } + } + } + + function compareIterableEquality(a, b, cache) { + return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache); + } + + function cacheComparison(a, b, compare, cache) { + var result = compare(a, b, cache); + if (cache && (result === EQUAL || result === NOT_EQUAL)) { + setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result)); + } + return result; + } + + function fail() { + return NOT_EQUAL; + } + + function setCache(cache, left, right, result) { + var otherCache; + + otherCache = cache.get(left); + if (!otherCache) cache.set(left, otherCache = new Map()); + otherCache.set(right, result); + + otherCache = cache.get(right); + if (!otherCache) cache.set(right, otherCache = new Map()); + otherCache.set(left, result); + } + + function getCache(cache, left, right) { + var otherCache; + var result; + + otherCache = cache.get(left); + result = otherCache && otherCache.get(right); + if (result) return result; + + otherCache = cache.get(right); + result = otherCache && otherCache.get(left); + if (result) return result; + + return UNKNOWN; + } + + return deepEqual; +})(); + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/subclassing-ignored.js new file mode 100644 index 000000000000..ee2748962a01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/subtract/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: Objects of a subclass are never created as return values for subtract() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainYearMonth, + [2000, 5], + "subtract", + [{ months: 1 }], + (result) => TemporalHelpers.assertPlainYearMonth(result, 2000, 4, "M04"), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..e4d6483c3a26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tojson +description: > + Tests that Temporal.PlainYearMonth.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/length.js new file mode 100644 index 000000000000..df3572f6a567 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tojson +description: Temporal.PlainYearMonth.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/name.js new file mode 100644 index 000000000000..216809c81451 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tojson +description: Temporal.PlainYearMonth.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..bad94d9d811d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tojson +description: > + Temporal.PlainYearMonth.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.toJSON), false, + "isConstructor(Temporal.PlainYearMonth.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..eccc5a16f2ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tojson +description: The "toJSON" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.toJSON, + "function", + "`typeof PlainYearMonth.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/year-format.js new file mode 100644 index 000000000000..c1baf09eca81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toJSON/year-format.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainYearMonth(-100000, 12); +assert.sameValue(instance.toJSON(), "-100000-12", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-10000, 4); +assert.sameValue(instance.toJSON(), "-010000-04", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-9999, 6); +assert.sameValue(instance.toJSON(), "-009999-06", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-1000, 8); +assert.sameValue(instance.toJSON(), "-001000-08", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-999, 10); +assert.sameValue(instance.toJSON(), "-000999-10", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-1, 8); +assert.sameValue(instance.toJSON(), "-000001-08", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(0, 6); +assert.sameValue(instance.toJSON(), "0000-06", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(1, 4); +assert.sameValue(instance.toJSON(), "0001-04", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(999, 2); +assert.sameValue(instance.toJSON(), "0999-02", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(1000, 1); +assert.sameValue(instance.toJSON(), "1000-01", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(9999, 4); +assert.sameValue(instance.toJSON(), "9999-04", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(10000, 6); +assert.sameValue(instance.toJSON(), "+010000-06", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(100000, 8); +assert.sameValue(instance.toJSON(), "+100000-08", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/builtin.js new file mode 100644 index 000000000000..f1a10008e969 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: > + Tests that Temporal.PlainYearMonth.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/length.js new file mode 100644 index 000000000000..fcac0aebebbf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: Temporal.PlainYearMonth.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/name.js new file mode 100644 index 000000000000..cb468cba4adc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: Temporal.PlainYearMonth.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 000000000000..09430b6950a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: > + Temporal.PlainYearMonth.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.toLocaleString), false, + "isConstructor(Temporal.PlainYearMonth.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/prop-desc.js new file mode 100644 index 000000000000..26139c9a670c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.toLocaleString, + "function", + "`typeof PlainYearMonth.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/argument-not-object.js new file mode 100644 index 000000000000..1f9afc95f79c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/argument-not-object.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: Throws a TypeError if the argument is not an Object, before any other observable actions +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[null, undefined, true, 3.1416, "a string", Symbol("symbol"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarThrowEverything(); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + assert.throws(TypeError, () => plainYearMonth.toPlainDate(primitive)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/basic.js new file mode 100644 index 000000000000..236035a6eef5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/basic.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: Basic check for toPlainDate() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2002-01"); +TemporalHelpers.assertPlainDate(ym.toPlainDate({ day: 22 }), 2002, 1, "M01", 22); +assert.throws(TypeError, () => ym.toPlainDate({ something: "nothing" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/builtin.js new file mode 100644 index 000000000000..bb3504680e09 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: > + Tests that Temporal.PlainYearMonth.prototype.toPlainDate + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.toPlainDate), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.toPlainDate), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.toPlainDate), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.toPlainDate.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/calendar-fields-iterable.js new file mode 100644 index 000000000000..3017be7a15d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.prototype.toplaindate step 5: + 5. Let _receiverFieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »). + sec-temporal.plainyearmonth.prototype.toplaindate step 7: + 7. Let _inputFieldNames_ be ? CalendarFields(_calendar_, « *"day"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "monthCode", + "year", +]; +const expected2 = [ + "day", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +yearmonth.toPlainDate({ day: 15 }); + +assert.sameValue(calendar.fieldsCallCount, 2, "fields() method called twice"); +assert.compareArray(calendar.fieldsCalledWith[0], expected1, "fields() method called first time with correct args"); +assert.compareArray(calendar.fieldsCalledWith[1], expected2, "fields() method called second time with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole first iterable"); +assert(calendar.iteratorExhausted[1], "iterated through the whole second iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js new file mode 100644 index 000000000000..fc6e148e405b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: > + with() should throw a TypeError if mergeFields() returns a primitive, + without passing the value on to any other calendar methods +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive); + const instance = new Temporal.PlainYearMonth(2000, 5, calendar); + assert.throws(TypeError, () => instance.toPlainDate({ day: 2 }), "bad return from mergeFields() throws"); + assert.sameValue(calendar.dateFromFieldsCallCount, 0, "dateFromFields() never called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/copies-merge-fields-object.js new file mode 100644 index 000000000000..af39b2130bd0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/copies-merge-fields-object.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: The object returned from mergeFields() is copied before being passed to monthDayFromFields(). +info: | + sec-temporal.plainyearmonth.prototype.toplaindate steps 9 and 11: + 9. Let _mergedFields_ be ? CalendarMergeFields(_calendar_, _fields_, _inputFields_). + 11. Set _mergedFields_ to ? PrepareTemporalFields(_mergedFields_, _mergedFieldNames_, «»). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", + "get day", // first receiver fields, then input fields + "get day.valueOf", + "call day.valueOf", +]; + +const calendar = TemporalHelpers.calendarMergeFieldsGetters(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +yearmonth.toPlainDate({ day: 2 }); + +assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..df8ca935b322 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/infinity-throws-rangeerror.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.prototype.toplaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.toPlainDate({ day: inf }), `day property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "day"); + assert.throws(RangeError, () => instance.toPlainDate({ day: obj })); + assert.compareArray(calls, ["get day.valueOf", "call day.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/length.js new file mode 100644 index 000000000000..58601b7b1092 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: Temporal.PlainYearMonth.prototype.toPlainDate.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.toPlainDate, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/limits.js new file mode 100644 index 000000000000..c3e2ea88cf76 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/limits.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: Throws a RangeError if the resulting PlainDate is out of range +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const min = Temporal.PlainYearMonth.from("-271821-04"); +assert.throws(RangeError, () => min.toPlainDate({ day: 18 }), "min"); +TemporalHelpers.assertPlainDate(min.toPlainDate({ day: 19 }), + -271821, 4, "M04", 19, "min"); + +const max = Temporal.PlainYearMonth.from("+275760-09"); +assert.throws(RangeError, () => max.toPlainDate({ day: 14 }), "max"); +TemporalHelpers.assertPlainDate(max.toPlainDate({ day: 13 }), + 275760, 9, "M09", 13, "max"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/name.js new file mode 100644 index 000000000000..93200726d064 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: Temporal.PlainYearMonth.prototype.toPlainDate.name is "toPlainDate". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.toPlainDate, "name", { + value: "toPlainDate", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/not-a-constructor.js new file mode 100644 index 000000000000..258ece1e7056 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: > + Temporal.PlainYearMonth.prototype.toPlainDate does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.toPlainDate(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.toPlainDate), false, + "isConstructor(Temporal.PlainYearMonth.prototype.toPlainDate)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/prop-desc.js new file mode 100644 index 000000000000..6d168bf5a452 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.toplaindate +description: The "toPlainDate" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.toPlainDate, + "function", + "`typeof PlainYearMonth.prototype.toPlainDate` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "toPlainDate", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toPlainDate/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/builtin.js new file mode 100644 index 000000000000..dcee6f4013dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tostring +description: > + Tests that Temporal.PlainYearMonth.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js new file mode 100644 index 000000000000..af92456f31eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.protoype.tostring +description: always value for calendarName option +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const yearmonth1 = new Temporal.PlainYearMonth(2000, 5); +const yearmonth2 = new Temporal.PlainYearMonth(2000, 5, calendar); + +[ + [yearmonth1, "2000-05-01[u-ca=iso8601]"], // fallback day 1 used + [yearmonth2, "2000-05-01[u-ca=custom]"], +].forEach(([yearmonth, expected]) => { + const result = yearmonth.toString({ calendarName: "always" }); + assert.sameValue(result, expected, "calendarName is always"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-auto.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-auto.js new file mode 100644 index 000000000000..be054aee7d12 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-auto.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.protoype.tostring +description: auto value for calendarName option +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const yearmonth1 = new Temporal.PlainYearMonth(2000, 5); +const yearmonth2 = new Temporal.PlainYearMonth(2000, 5, calendar); + +[ + [yearmonth1, "2000-05"], + [yearmonth2, "2000-05-01[u-ca=custom]"], +].forEach(([yearmonth, expected]) => { + const result = yearmonth.toString({ calendarName: "auto" }); + assert.sameValue(result, expected, "calendarName is auto"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-invalid-string.js new file mode 100644 index 000000000000..2e888a350385 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-invalid-string.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.protoype.tostring +description: RangeError thrown when calendarName option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plainyearmonth.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +for (const calendarName of ["ALWAYS", "sometimes", "other string"]) { + assert.throws(RangeError, () => yearmonth.toString({ calendarName })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-never.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-never.js new file mode 100644 index 000000000000..aca7b21692a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-never.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.protoype.tostring +description: never value for calendarName option +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const yearmonth1 = new Temporal.PlainYearMonth(2000, 5); +const yearmonth2 = new Temporal.PlainYearMonth(2000, 5, calendar); + +[ + [yearmonth1, "2000-05"], + [yearmonth2, "2000-05-01"], +].forEach(([yearmonth, expected]) => { + const result = yearmonth.toString({ calendarName: "never" }); + assert.sameValue(result, expected, "calendarName is never"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-undefined.js new file mode 100644 index 000000000000..1232ad641710 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-undefined.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.protoype.tostring +description: Fallback value for calendarName option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plainyearmonth.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const yearmonth1 = new Temporal.PlainYearMonth(2000, 5); +const yearmonth2 = new Temporal.PlainYearMonth(2000, 5, calendar); + +[ + [yearmonth1, "2000-05"], + [yearmonth2, "2000-05-01[u-ca=custom]"], +].forEach(([yearmonth, expected]) => { + const explicit = yearmonth.toString({ calendarName: undefined }); + assert.sameValue(explicit, expected, "default calendarName option is auto"); + + const implicit = yearmonth.toString({}); + assert.sameValue(implicit, expected, "default calendarName option is auto"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-wrong-type.js new file mode 100644 index 000000000000..bf2644486f77 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.protoype.tostring +description: Type conversions for calendarName option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.plainyearmonth.protoype.tostring step 4: + 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); + +TemporalHelpers.checkStringOptionWrongType("calendarName", "auto", + (calendarName) => yearmonth.toString({ calendarName }), + (result, descr) => assert.sameValue(result, "2000-05-01[u-ca=custom]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/length.js new file mode 100644 index 000000000000..c30f9668afd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tostring +description: Temporal.PlainYearMonth.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/name.js new file mode 100644 index 000000000000..d8a2ede5dc0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tostring +description: Temporal.PlainYearMonth.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..3799e82dbce2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tostring +description: > + Temporal.PlainYearMonth.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.toString), false, + "isConstructor(Temporal.PlainYearMonth.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/options-undefined.js new file mode 100644 index 000000000000..d9c3d7f91853 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/options-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tostring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const yearmonth1 = new Temporal.PlainYearMonth(2000, 5); +const yearmonth2 = new Temporal.PlainYearMonth(2000, 5, calendar); + +[ + [yearmonth1, "2000-05"], + [yearmonth2, "2000-05-01[u-ca=custom]"], +].forEach(([yearmonth, expected]) => { + const explicit = yearmonth.toString(undefined); + assert.sameValue(explicit, expected, "default calendarName option is auto"); + + const implicit = yearmonth.toString(); + assert.sameValue(implicit, expected, "default calendarName option is auto"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..7a8d7e70a96e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tostring +description: The "toString" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.toString, + "function", + "`typeof PlainYearMonth.prototype.toString` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/year-format.js new file mode 100644 index 000000000000..154c05c4e9c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/toString/year-format.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainYearMonth(-100000, 12); +assert.sameValue(instance.toString(), "-100000-12", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-10000, 4); +assert.sameValue(instance.toString(), "-010000-04", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-9999, 6); +assert.sameValue(instance.toString(), "-009999-06", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-1000, 8); +assert.sameValue(instance.toString(), "-001000-08", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-999, 10); +assert.sameValue(instance.toString(), "-000999-10", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-1, 8); +assert.sameValue(instance.toString(), "-000001-08", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(0, 6); +assert.sameValue(instance.toString(), "0000-06", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(1, 4); +assert.sameValue(instance.toString(), "0001-04", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(999, 2); +assert.sameValue(instance.toString(), "0999-02", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(1000, 1); +assert.sameValue(instance.toString(), "1000-01", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(9999, 4); +assert.sameValue(instance.toString(), "9999-04", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(10000, 6); +assert.sameValue(instance.toString(), "+010000-06", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(100000, 8); +assert.sameValue(instance.toString(), "+100000-08", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/argument-casting.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/argument-casting.js new file mode 100644 index 000000000000..e49447aa9e32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/argument-casting.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Calls to PYM.until cast arguments. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const nov94 = new Temporal.PlainYearMonth(1994, 11); +const jun13 = new Temporal.PlainYearMonth(2013, 6); +const diff = nov94.until(jun13); + +TemporalHelpers.assertDurationsEqual(nov94.until({ year: 2013, month: 6 }), diff, "Casts object argument"); +TemporalHelpers.assertDurationsEqual(nov94.until("2013-06"), diff, "Casts string argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..7a89c05e8f82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: RangeError thrown if a string with UTC designator is used as a PlainYearMonth +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainYearMonth(2000, 5); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "String with UTC designator should not be valid as a PlainYearMonth" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/arguments-missing-throws.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/arguments-missing-throws.js new file mode 100644 index 000000000000..844b9c1c2e2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/arguments-missing-throws.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Calls to PYM.until throw when missing required arguments. +features: [Temporal] +---*/ + +const jun13 = new Temporal.PlainYearMonth(2013, 6); + +assert.throws(TypeError, () => jun13.until({ year: 1994 }), 'Throws when missing required month'); +assert.throws(TypeError, () => jun13.until({ month: 11 }), 'Throws when missing required year'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/builtin.js new file mode 100644 index 000000000000..0e54bb74e46b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: > + Tests that Temporal.PlainYearMonth.prototype.until + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.until), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.until), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.until), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.until.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 000000000000..3b9b5eaf6ffe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.PlainYearMonth(1970, 1, calendar); +instance.until(new Temporal.PlainYearMonth(2000, 5, calendar), { smallestUnit: "year" }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..a4b8498a3d6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.until({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..97e763f9b739 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.plainyearmonth.prototype.until steps 20–21: + 20. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _largestUnit_). + 21. Let _result_ be ? CalendarDateUntil(_calendar_, _thisDate_, _otherDate_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.PlainYearMonth(2000, 5, calendar); + const later = new Temporal.PlainYearMonth(2001, 6, calendar); + earlier.until(later, { largestUnit }); + }, + { + years: ["year"], + months: ["month"] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-fields-iterable.js new file mode 100644 index 000000000000..b013a9dc8682 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-fields-iterable.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.prototype.until step 3: + 3. Set _other_ to ? ToTemporalYearMonth(_other_). + sec-temporal.plainyearmonth.prototype.until step 13: + 13. Let fieldNames be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »). + sec-temporal-totemporalyearmonth step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "monthCode", + "year", +]; +const expected2 = [ + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +yearmonth.until({ year: 2005, month: 6, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 1, "fields() method not called"); +assert.compareArray(calendar1.fieldsCalledWith[0], expected1, "fields() method called with correct args"); +assert(calendar1.iteratorExhausted[0], "iterated through the whole iterable"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected2, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-temporal-object.js new file mode 100644 index 000000000000..38eac56b7067 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plainyearmonth.prototype.until step 3: + 3. Set _other_ to ? ToTemporalYearMonth(_other_). + sec-temporal-totemporalyearmonth step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const yearmonth = new Temporal.PlainYearMonth(2000, 5, temporalObject); + yearmonth.until({ year: 2005, month: 6, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-yearmonthfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..d9c5849b5703 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +let instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.until({ year: 2000, month: 6, calendar }); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to yearMonthFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +calendar = new Temporal.Calendar("iso8601"); +instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.until("2000-06-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..bfe51083c3b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +const base = { year: 2000, month: 5 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month"].forEach((prop) => { + assert.throws(RangeError, () => instance.until({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.until({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-auto.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-auto.js new file mode 100644 index 000000000000..7c9b74ae48d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-auto.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: auto value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.assertDuration(earlier.until(later, { largestUnit: "auto" }), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "auto largestUnit is year (pos)"); +TemporalHelpers.assertDuration(later.until(earlier, { largestUnit: "auto" }), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "auto largestUnit is year (neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-disallowed-units.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-disallowed-units.js new file mode 100644 index 000000000000..4f9fc96b6c7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-disallowed-units.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Until throws on to0-small largestUnit +features: [Temporal, arrow-function] +---*/ + +const earlier = new Temporal.PlainYearMonth(2019, 1); +const later = new Temporal.PlainYearMonth(2021, 9); + +[ + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds" +].forEach((largestUnit) => { + assert.throws(RangeError, () => earlier.until(later, { largestUnit }), + `throws on disallowed or invalid largestUnit: ${largestUnit}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string.js new file mode 100644 index 000000000000..52fe3210f81b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const values = ["era", "eraYear", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-months.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-months.js new file mode 100644 index 000000000000..7a08cce11707 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-months.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: months value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.assertDuration(earlier.until(later, { largestUnit: "months" }), + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, "largestUnit is months (pos)"); +TemporalHelpers.assertDuration(later.until(earlier, { largestUnit: "months" }), + 0, -13, 0, 0, 0, 0, 0, 0, 0, 0, "largestUnit is months (neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..9f18e886d45e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-plurals-accepted.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const validUnits = [ + "year", + "month", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => earlier.until(later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..ae7f99fe0189 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const units = ["years", "months"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => earlier.until(later, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-undefined.js new file mode 100644 index 000000000000..c2252e32a8a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.assertDuration(earlier.until(later, { largestUnit: undefined }), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (explicit, pos)"); +TemporalHelpers.assertDuration(later.until(earlier, { largestUnit: undefined }), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (explicit, neg)"); + +TemporalHelpers.assertDuration(earlier.until(later, {}), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (implicit, pos)"); +TemporalHelpers.assertDuration(later.until(earlier, {}), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (implicit, neg)"); + +TemporalHelpers.assertDuration(earlier.until(later, () => {}), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (arrow function, pos)"); +TemporalHelpers.assertDuration(later.until(earlier, () => {}), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (arrow function, neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-wrong-type.js new file mode 100644 index 000000000000..3eea93017376 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "month", + (largestUnit) => earlier.until(later, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-years.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-years.js new file mode 100644 index 000000000000..0cb7f0b6e439 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-years.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: years value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.assertDuration(earlier.until(later, { largestUnit: "years" }), + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "largestUnit is years (pos)"); +TemporalHelpers.assertDuration(later.until(earlier, { largestUnit: "years" }), + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, "largestUnit is years (neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/length.js new file mode 100644 index 000000000000..3862c4baf208 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Temporal.PlainYearMonth.prototype.until.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.until, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/mixed-calendar-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/mixed-calendar-invalid.js new file mode 100644 index 000000000000..50faa5687c92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/mixed-calendar-invalid.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Mixed calendars throw as invalid +features: [Temporal] +---*/ + +class customCal extends Temporal.Calendar { + constructor () { + super('iso8601'); + } + + toString() { + return "I am a secret cal."; + } +} + +const ym1 = new Temporal.PlainYearMonth(2000, 1); +const ym2 = new Temporal.PlainYearMonth(2000, 1, new customCal()); + +assert.throws(RangeError, () => ym1.until(ym2), 'until throws with different calendars'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/name.js new file mode 100644 index 000000000000..0057bf855b1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Temporal.PlainYearMonth.prototype.until.name is "until". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.until, "name", { + value: "until", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/not-a-constructor.js new file mode 100644 index 000000000000..2e7e90edae34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: > + Temporal.PlainYearMonth.prototype.until does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.until(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.until), false, + "isConstructor(Temporal.PlainYearMonth.prototype.until)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/options-invalid.js new file mode 100644 index 000000000000..3bdc86b0e676 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/options-invalid.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Verify that invalid options are handled correctly. +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainYearMonth(2020, 2); +const feb21 = new Temporal.PlainYearMonth(2021, 2); + +[ + null, + 1, + "hello", + true, + Symbol("foo"), + 1n +].forEach((badOption) => + assert.throws(TypeError, () => feb20.until(feb21, badOption), `${String(badOption)} throws TypeError`) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/options-undefined.js new file mode 100644 index 000000000000..7f254f72345c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/options-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Verify that undefined options are handled correctly. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2002, 12); + +TemporalHelpers.assertDuration(earlier.until(later, undefined), + 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (explicit, pos)"); +TemporalHelpers.assertDuration(later.until(earlier, undefined), + -2, -7, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (explicit, neg)"); + +TemporalHelpers.assertDuration(earlier.until(later), + 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (implicit, pos)"); +TemporalHelpers.assertDuration(later.until(earlier), + -2, -7, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year (implicit, neg)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/prop-desc.js new file mode 100644 index 000000000000..cd2cd4a41a2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: The "until" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.until, + "function", + "`typeof PlainYearMonth.prototype.until` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "until", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-as-expected.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-as-expected.js new file mode 100644 index 000000000000..900f289ddfe1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-as-expected.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Until rounding increments work as expected +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2019, 1); +const later = new Temporal.PlainYearMonth(2021, 9); + +const laterSinceYear = earlier.until(later, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" }); +TemporalHelpers.assertDuration(laterSinceYear, + /* years = */ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rounds to an increment of years"); + +const laterSinceMixed = earlier.until(later, { smallestUnit: "months", roundingIncrement: 5 }); +TemporalHelpers.assertDuration(laterSinceMixed, + /* years = */ 2, /* months = */ 5, 0, 0, 0, 0, 0, 0, 0, 0, "rounds to an increment of months mixed with years"); + +const laterSinceMonth = earlier.until(later, { largestUnit: "months", smallestUnit: "months", roundingIncrement: 10 }); +TemporalHelpers.assertDuration(laterSinceMonth, + 0, /* months = */ 30, 0, 0, 0, 0, 0, 0, 0, 0, "rounds to an increment of pure months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-nan.js new file mode 100644 index 000000000000..d92440b677f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plainyearmonth.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-non-integer.js new file mode 100644 index 000000000000..ef6df76c3509 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2000, 10); +const result = earlier.until(later, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..347c6eb39189 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2000, 10); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-undefined.js new file mode 100644 index 000000000000..d682be316f39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plainyearmonth.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +const explicit = earlier.until(later, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1"); + +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..e3d545e15845 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plainyearmonth.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => earlier.until(later, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-ceil.js new file mode 100644 index 000000000000..6dea59983a70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-ceil.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainYearMonth.from("2019-01"); +const later = Temporal.PlainYearMonth.from("2021-09"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "ceil" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "years", roundingMode: "ceil" }), + /* years = */ -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "ceil" }), + /* years = */ 2, /* months = */ 8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "months", roundingMode: "ceil" }), + /* years = */ -2, /* months = */ -8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-floor.js new file mode 100644 index 000000000000..708af0840797 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-floor.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainYearMonth.from("2019-01"); +const later = Temporal.PlainYearMonth.from("2021-09"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "floor" }), + /* years = */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "years", roundingMode: "floor" }), + /* years = */ -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "floor" }), + /* years = */ 2, /* months = */ 8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "months", roundingMode: "floor" }), + /* years = */ -2, /* months = */ -8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfExpand.js new file mode 100644 index 000000000000..28fc10c74861 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-halfExpand.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainYearMonth.from("2019-01"); +const later = Temporal.PlainYearMonth.from("2021-09"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "halfExpand" }), + /* years = */ 2, /* months = */ 8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "months", roundingMode: "halfExpand" }), + /* years = */ -2, /* months = */ -8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string.js new file mode 100644 index 000000000000..688dfb2e09c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-trunc.js new file mode 100644 index 000000000000..789fa97e023a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-trunc.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainYearMonth.from("2019-01"); +const later = Temporal.PlainYearMonth.from("2021-09"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "trunc" }), + /* years = */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "years", roundingMode: "trunc" }), + /* years = */ -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "trunc" }), + /* years = */ 2, /* months = */ 8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "months", roundingMode: "trunc" }), + /* years = */ -2, /* months = */ -8, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-undefined.js new file mode 100644 index 000000000000..24009ace61dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 1); + +const later1 = new Temporal.PlainYearMonth(2005, 2); +const explicit1 = earlier.until(later1, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit1 = earlier.until(later1, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +const later2 = new Temporal.PlainYearMonth(2005, 12); +const explicit2 = earlier.until(later2, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit2 = earlier.until(later2, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-wrong-type.js new file mode 100644 index 000000000000..cfa8295eeeec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => earlier.until(later, { smallestUnit: "year", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string.js new file mode 100644 index 000000000000..ac515fe2d8a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const values = ["era", "eraYear", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..ce199f6065d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-plurals-accepted.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +const validUnits = [ + "year", + "month", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => earlier.until(later, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-undefined.js new file mode 100644 index 000000000000..a7ba8b70103c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); + +const explicit = earlier.until(later, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default smallestUnit is month"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default smallestUnit is month"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-wrong-type.js new file mode 100644 index 000000000000..743651dc1683 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainYearMonth(2000, 5); +const later = new Temporal.PlainYearMonth(2001, 6); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year", + (smallestUnit) => earlier.until(later, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/year-zero.js new file mode 100644 index 000000000000..9f5efc266f6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/until/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: RangeError thrown if a string with UTC designator is used as a PlainYearMonth +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-06', + '-000000-06-24', + '-000000-06-24T15:43:27', + '-000000-06-24T15:43:27+01:00[UTC]' +]; +const instance = new Temporal.PlainYearMonth(2000, 5); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/basic.js new file mode 100644 index 000000000000..825513dc9d6b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/basic.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.valueof +description: Basic tests for valueOf(). +features: [Temporal] +---*/ + +const plainYearMonth = Temporal.PlainYearMonth.from("1963-02"); +const plainYearMonth2 = Temporal.PlainYearMonth.from("1963-02"); + +assert.throws(TypeError, () => plainYearMonth.valueOf(), "valueOf"); +assert.throws(TypeError, () => plainYearMonth < plainYearMonth, "<"); +assert.throws(TypeError, () => plainYearMonth <= plainYearMonth, "<="); +assert.throws(TypeError, () => plainYearMonth > plainYearMonth, ">"); +assert.throws(TypeError, () => plainYearMonth >= plainYearMonth, ">="); +assert.sameValue(plainYearMonth === plainYearMonth, true, "==="); +assert.sameValue(plainYearMonth === plainYearMonth2, false, "==="); +assert.sameValue(plainYearMonth !== plainYearMonth, false, "!=="); +assert.sameValue(plainYearMonth !== plainYearMonth2, true, "!=="); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/builtin.js new file mode 100644 index 000000000000..d29a5ce21838 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.valueof +description: > + Tests that Temporal.PlainYearMonth.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/length.js new file mode 100644 index 000000000000..f6bb27343751 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.valueof +description: Temporal.PlainYearMonth.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/name.js new file mode 100644 index 000000000000..8fff995807bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.valueof +description: Temporal.PlainYearMonth.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/not-a-constructor.js new file mode 100644 index 000000000000..706a1946170c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.valueof +description: > + Temporal.PlainYearMonth.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.valueOf), false, + "isConstructor(Temporal.PlainYearMonth.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/prop-desc.js new file mode 100644 index 000000000000..cb264ce206b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.valueof +description: The "valueOf" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.valueOf, + "function", + "`typeof PlainYearMonth.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/valueOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-calendar-field.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-calendar-field.js new file mode 100644 index 000000000000..86e813f7bd1b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-calendar-field.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Throw if the argument has a calendar field +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-10"); +assert.throws(TypeError, () => ym.with({ year: 2021, calendar: "iso8601" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-missing-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-missing-fields.js new file mode 100644 index 000000000000..8666155f5d49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-missing-fields.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: TypeError thrown when argument doesn't contain any of the supported properties +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-10"); +assert.throws(TypeError, () => ym.with({}), "No properties"); +assert.throws(TypeError, () => ym.with({ months: 12 }), "Only plural 'months' property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-timezone-field.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-timezone-field.js new file mode 100644 index 000000000000..f4f07f60cc9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/argument-timezone-field.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Throw if the argument has a timeZone field +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-10"); +assert.throws(TypeError, () => ym.with({ year: 2021, timeZone: "UTC" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/basic.js new file mode 100644 index 000000000000..ef2706572cc6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/basic.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Basic tests for with +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const ym = Temporal.PlainYearMonth.from("2019-10"); + +TemporalHelpers.assertPlainYearMonth(ym.with({ year: 2020 }), 2020, 10, "M10", "year"); +TemporalHelpers.assertPlainYearMonth(ym.with({ month: 9 }), 2019, 9, "M09", "month"); +TemporalHelpers.assertPlainYearMonth(ym.with({ monthCode: "M09" }), 2019, 9, "M09", "monthCode"); + +assert.throws(RangeError, () => ym.with({ month: 9, monthCode: "M10" }), "month/monthCode mismatch"); +TemporalHelpers.assertPlainYearMonth(ym.with({ month: 1, years: 2020 }), 2019, 1, "M01", "plural 'years'"); + +const withDay = ym.with({ year: 2019, get day() { throw new Test262Error("should not read the day property") } }); +TemporalHelpers.assertPlainYearMonth(withDay, 2019, 10, "M10", "day property"); +assert.sameValue(withDay.getISOFields().isoDay, 1); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/builtin.js new file mode 100644 index 000000000000..6c9d3647a037 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: > + Tests that Temporal.PlainYearMonth.prototype.with + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainYearMonth.prototype.with), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainYearMonth.prototype.with), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainYearMonth.prototype.with), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainYearMonth.prototype.with.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-arguments.js new file mode 100644 index 000000000000..3e040f783d12 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-arguments.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Correct options value is passed to calendar method +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 5. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const options = {}; +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + yearMonthFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.sameValue(args[1], options, "args[1]"); + return super.yearMonthFromFields(...args); + } +} +const plainYearMonth = new Temporal.PlainYearMonth(2000, 7, new CustomCalendar()); +const result = plainYearMonth.with({ month: 5 }, options); +TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-fields-iterable.js new file mode 100644 index 000000000000..480614e46bb4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-fields-iterable.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plainyearmonth.prototype.with step 9: + 9. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "month", + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +yearmonth.with({ year: 2005 }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-merge-fields-returns-primitive.js new file mode 100644 index 000000000000..2bf04d3fedec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/calendar-merge-fields-returns-primitive.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: > + with() should throw a TypeError if mergeFields() returns a primitive, + without passing the value on to any other calendar methods +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive); + const instance = new Temporal.PlainYearMonth(2000, 5, calendar); + assert.throws(TypeError, () => instance.with({ year: 2005 }), "bad return from mergeFields() throws"); + assert.sameValue(calendar.yearMonthFromFieldsCallCount, 0, "yearMonthFromFields() never called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/copies-merge-fields-object.js new file mode 100644 index 000000000000..7535cf0fea52 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/copies-merge-fields-object.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: The object returned from mergeFields() is copied before being passed to monthDayFromFields(). +info: | + sec-temporal.plainyearmonth.prototype.with steps 13–15: + 13. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialYearMonth_). + 14. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»). + 15. Return ? YearMonthFromFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; + +const calendar = TemporalHelpers.calendarMergeFieldsGetters(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +yearmonth.with({ year: 2004 }); + +assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/copy-properties-not-undefined.js new file mode 100644 index 000000000000..d4b4c25ba385 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/copy-properties-not-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: PreparePartialTemporalFields copies only defined properties of source object +info: | + 4. For each value _property_ of _fieldNames_, do + a. Let _value_ be ? Get(_fields_, _property_). + b. If _value_ is not *undefined*, then + ... + iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainYearMonth = new Temporal.PlainYearMonth(2001, 9); + +TemporalHelpers.assertPlainYearMonth(plainYearMonth.with({ month: 11, year: undefined }), + 2001, 11, "M11", + "only the properties that are present and defined in the plain object are copied" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..7d4ba2863f7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.prototype.with +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.with({ [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.with({ [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/length.js new file mode 100644 index 000000000000..9a89c6ae282a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Temporal.PlainYearMonth.prototype.with.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.with, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/name.js new file mode 100644 index 000000000000..e2ae229fb467 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Temporal.PlainYearMonth.prototype.with.name is "with". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainYearMonth.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/not-a-constructor.js new file mode 100644 index 000000000000..8f3a3b661afc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: > + Temporal.PlainYearMonth.prototype.with does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainYearMonth.prototype.with(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainYearMonth.prototype.with), false, + "isConstructor(Temporal.PlainYearMonth.prototype.with)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/options-undefined.js new file mode 100644 index 000000000000..d45c9effd5b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 2); +const fields = { month: 13 }; + +const explicit = yearmonth.with(fields, undefined); +assert.sameValue(explicit.month, 12, "default overflow is constrain"); + +const implicit = yearmonth.with(fields); +assert.sameValue(implicit.month, 12, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/options-wrong-type.js new file mode 100644 index 000000000000..99a9e500641e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/options-wrong-type.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const values = [ + null, + true, + "2021-01", + Symbol(), + 1, + 2n, +]; + +const ym = Temporal.PlainYearMonth.from("2019-10"); +values.forEach((value) => { + assert.throws(TypeError, () => ym.with({ year: 2020 }, value), `TypeError on wrong argument type ${typeof value}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/order-of-operations.js new file mode 100644 index 000000000000..ca35cd29783b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/order-of-operations.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Properties on an object passed to with() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +const expected = [ + "get calendar", + "get timeZone", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get year", + "get year.valueOf", + "call year.valueOf", +]; +const actual = []; +const fields = { + year: 1.7, + month: 1.7, + monthCode: "M01", +}; +const argument = new Proxy(fields, { + get(target, key) { + actual.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(actual, result, key); + }, + has(target, key) { + actual.push(`has ${key}`); + return key in target; + }, +}); +const result = instance.with(argument); +TemporalHelpers.assertPlainYearMonth(result, 1, 1, "M01"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js new file mode 100644 index 000000000000..f01c079c6173 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.with step 16: + 16. Return ? YearMonthFromFields(_calendar_, _fields_, _options_). +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 5); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.with({ month: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-undefined.js new file mode 100644 index 000000000000..61620a559161 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.with step 16: + 16. Return ? YearMonthFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +const explicit = yearmonth.with({ month: 15 }, { overflow: undefined }); +TemporalHelpers.assertPlainYearMonth(explicit, 2000, 12, "M12", "default overflow is constrain"); +const implicit = yearmonth.with({ month: 15 }, {}); +TemporalHelpers.assertPlainYearMonth(implicit, 2000, 12, "M12", "default overflow is constrain"); +const lambda = yearmonth.with({ month: 15 }, () => {}); +TemporalHelpers.assertPlainYearMonth(lambda, 2000, 12, "M12", "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-wrong-type.js new file mode 100644 index 000000000000..1f9dc56b3058 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.plainyearmonth.prototype.with step 16: + 16. Return ? YearMonthFromFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const yearmonth = new Temporal.PlainYearMonth(2000, 5); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => yearmonth.with({ month: 8 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainYearMonth(result, 2000, 8, "M08", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/prop-desc.js new file mode 100644 index 000000000000..e0eda7349da5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: The "with" property of Temporal.PlainYearMonth.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainYearMonth.prototype.with, + "function", + "`typeof PlainYearMonth.prototype.with` is `function`" +); + +verifyProperty(Temporal.PlainYearMonth.prototype, "with", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/subclassing-ignored.js new file mode 100644 index 000000000000..4da061889101 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/with/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.with +description: Objects of a subclass are never created as return values for with() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainYearMonth, + [2000, 5], + "with", + [{ month: 11 }], + (result) => TemporalHelpers.assertPlainYearMonth(result, 2000, 11, "M11"), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/year/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/year/calendar-returns-infinity.js new file mode 100644 index 000000000000..053916c08001 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/year/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.year +description: Getter throws if the calendar returns ±∞ from its year method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + year() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainYearMonth(2000, 5, pos); +assert.throws(RangeError, () => instance1.year); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainYearMonth(2000, 5, neg); +assert.throws(RangeError, () => instance2.year); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/year/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/year/prop-desc.js new file mode 100644 index 000000000000..160f60ba1d9b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/year/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.year +description: The "year" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "year"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/refisoday-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/refisoday-undefined.js new file mode 100644 index 000000000000..f1d61f617003 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/refisoday-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: referenceISODay argument defaults to 1 if not given +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const args = [2000, 5, calendar]; + +const dateExplicit = new Temporal.PlainYearMonth(...args, undefined); +assert.sameValue(dateExplicit.getISOFields().isoDay, 1, "default referenceISODay is 1"); + +const dateImplicit = new Temporal.PlainYearMonth(...args); +assert.sameValue(dateImplicit.getISOFields().isoDay, 1, "default referenceISODay is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/shell.js index e69de29bb2d1..1d70b7579ee9 100644 --- a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/basic.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/basic.js new file mode 100644 index 000000000000..c92d6c9c48fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/basic.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Basic tests for the Temporal.TimeZone constructor. +features: [Temporal] +---*/ + +const valid = [ + ["+01:00"], + ["-01:00"], + ["+0330", "+03:30"], + ["-0650", "-06:50"], + ["-08", "-08:00"], + ["\u221201:00", "-01:00"], + ["\u22120650", "-06:50"], + ["\u221208", "-08:00"], + ["+01:00:00", "+01:00"], + ["-010000", "-01:00"], + ["+03:30:00.000000001", "+03:30:00.000000001"], + ["-033000.1", "-03:30:00.1"], + ["UTC"], +]; +for (const [zone, id = zone] of valid) { + const result = new Temporal.TimeZone(zone); + assert.sameValue(typeof result, "object", `object should be created for ${zone}`); + assert.sameValue(result.id, id, `id for ${zone} should be ${id}`); +} + +const invalid = ["+00:01.1", "-01.1"]; +for (const zone of invalid) { + assert.throws(RangeError, () => new Temporal.TimeZone(zone), `should throw for ${zone}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/builtin.js new file mode 100644 index 000000000000..dac509ac72ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Tests that Temporal.TimeZone meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.TimeZone.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/constructor.js new file mode 100644 index 000000000000..bc143b316f8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Temporal.TimeZone constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.TimeZone()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-object-invalid.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-object-invalid.js new file mode 100644 index 000000000000..c9cf7db86c98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-object-invalid.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: TimeZone.from() with invalid objects. +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.TimeZone.from({ timeZone: "local" })); +assert.throws(RangeError, () => Temporal.TimeZone.from({ timeZone: { timeZone: "UTC" } })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-object.js new file mode 100644 index 000000000000..f32b0b68edc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-object.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: An object is returned unchanged +features: [Temporal] +---*/ + +class CustomTimeZone extends Temporal.TimeZone {} + +const objects = [ + new Temporal.TimeZone("UTC"), + new CustomTimeZone("UTC"), + {}, + { getPlainDateTimeFor: null }, + { id: "Etc/Custom" }, +]; + +const thisValues = [ + Temporal.TimeZone, + CustomTimeZone, + {}, + null, + undefined, + 7, +]; + +for (const thisValue of thisValues) { + for (const object of objects) { + const result = Temporal.TimeZone.from.call(thisValue, object); + assert.sameValue(result, object); + } + + const zdt = new Temporal.ZonedDateTime(0n, "UTC"); + const fromZdt = Temporal.TimeZone.from.call(thisValue, zdt); + assert.sameValue(fromZdt, zdt.timeZone); + assert.sameValue(fromZdt.id, "UTC"); + + const tz = new Temporal.TimeZone("UTC"); + const fromPropertyBagObject = Temporal.TimeZone.from.call(thisValue, { timeZone: tz }); + assert.sameValue(fromPropertyBagObject, tz); + assert.sameValue(fromPropertyBagObject.id, "UTC"); + + const fromPropertyBagString = Temporal.TimeZone.from.call(thisValue, { timeZone: "UTC" }); + assert(fromPropertyBagString instanceof Temporal.TimeZone); + assert.sameValue(fromPropertyBagString.id, "UTC"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-primitive.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-primitive.js new file mode 100644 index 000000000000..814a94be16a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-primitive.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: RangeError thrown if a value is passed that converts to an invalid string +features: [Temporal] +---*/ + +class CustomTimeZone extends Temporal.TimeZone {} + +const primitives = [ + undefined, + null, + true, + "string", + "local", + "Z", + "-00:00[UTC]", + "+00:01.1", + "-01.1", + "1994-11-05T08:15:30+25:00", + "1994-11-05T13:15:30-25:00", + 7, + 4.2, + 12n, +]; + +const thisValues = [ + Temporal.TimeZone, + CustomTimeZone, + {}, + null, + undefined, + 7, +]; + +for (const thisValue of thisValues) { + for (const primitive of primitives) { + assert.throws(RangeError, () => Temporal.TimeZone.from.call(thisValue, primitive)); + } + + const symbol = Symbol(); + assert.throws(TypeError, () => Temporal.TimeZone.from.call(thisValue, symbol)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-valid.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-valid.js new file mode 100644 index 000000000000..d5d4a9b094fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/argument-valid.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Built-in time zones are parsed correctly out of valid strings +features: [Temporal] +---*/ + +const valids = [ + ["+01:00"], + ["-01:00"], + ["+0330", "+03:30"], + ["-0650", "-06:50"], + ["-08", "-08:00"], + ["\u221201:00", "-01:00"], + ["\u22120650", "-06:50"], + ["\u221208", "-08:00"], + ["+01:00:00", "+01:00"], + ["-010000", "-01:00"], + ["+03:30:00.000000001", "+03:30:00.000000001"], + ["-033000.1", "-03:30:00.1"], + ["UTC"], + ["1994-11-05T08:15:30-05:00", "-05:00"], + ["1994-11-05T08:15:30\u221205:00", "-05:00"], + ["1994-11-05T13:15:30Z", "UTC"], +]; + +for (const [valid, canonical = valid] of valids) { + const result = Temporal.TimeZone.from(valid); + assert.sameValue(Object.getPrototypeOf(result), Temporal.TimeZone.prototype); + assert.sameValue(result.id, canonical); + assert.sameValue(result.toString(), canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/builtin.js new file mode 100644 index 000000000000..4c961e488c3f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Tests that Temporal.TimeZone.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/length.js new file mode 100644 index 000000000000..eea90f16d958 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Temporal.TimeZone.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/name.js new file mode 100644 index 000000000000..10d0a45f427a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Temporal.TimeZone.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/not-a-constructor.js new file mode 100644 index 000000000000..5e15f2d0c915 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Temporal.TimeZone.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.from), false, + "isConstructor(Temporal.TimeZone.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/prop-desc.js new file mode 100644 index 000000000000..2e9e56cb2afe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: The "from" property of Temporal.TimeZone +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.from, + "function", + "`typeof TimeZone.from` is `function`" +); + +verifyProperty(Temporal.TimeZone, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/subclassing-ignored.js new file mode 100644 index 000000000000..159bc5d1de97 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/subclassing-ignored.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.TimeZone, + "from", + ["UTC"], + (result) => { + assert.sameValue(result.id, "UTC", "id property of result"); + assert.sameValue(result.toString(), "UTC", "toString() of result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/timezone-string-datetime.js new file mode 100644 index 000000000000..f5dff22629f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/timezone-string-datetime.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.TimeZone.from(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.TimeZone.from({ timeZone }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result1.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result2.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result3.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result4.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result5.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result6.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result7.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result8.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result9.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result10.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/from/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..8b4c6693bd9c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/from/timezone-string-multiple-offsets.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result1.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result2.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/length.js new file mode 100644 index 000000000000..104589025d3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Temporal.TimeZone.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/missing-arguments.js new file mode 100644 index 000000000000..cb0e8d07e363 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/missing-arguments.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: RangeError thrown when constructor invoked with no argument +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.TimeZone()); +assert.throws(RangeError, () => new Temporal.TimeZone(undefined)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/name.js new file mode 100644 index 000000000000..ab2fd8820365 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Temporal.TimeZone.name is "TimeZone" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone, "name", { + value: "TimeZone", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prop-desc.js new file mode 100644 index 000000000000..afe5731f3a04 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: The "TimeZone" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone, + "function", + "`typeof TimeZone` is `function`" +); + +verifyProperty(Temporal, "TimeZone", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-not-datetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-not-datetime.js new file mode 100644 index 000000000000..0f6f7205f18e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-not-datetime.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Appropriate error thrown when argument cannot be converted to Temporal.PlainDateTime +features: [Temporal] +---*/ + +const timeZone = Temporal.TimeZone.from("UTC"); +assert.throws(RangeError, () => timeZone.getInstantFor(undefined), "undefined"); +assert.throws(RangeError, () => timeZone.getInstantFor(null), "null"); +assert.throws(RangeError, () => timeZone.getInstantFor(true), "boolean"); +assert.throws(RangeError, () => timeZone.getInstantFor(""), "empty string"); +assert.throws(TypeError, () => timeZone.getInstantFor(Symbol()), "Symbol"); +assert.throws(RangeError, () => timeZone.getInstantFor(5), "number"); +assert.throws(RangeError, () => timeZone.getInstantFor(5n), "bigint"); +assert.throws(TypeError, () => timeZone.getInstantFor({ year: 2020 }), "plain object"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-plaindate.js new file mode 100644 index 000000000000..8fd29130dc07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-plaindate.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots +info: | + sec-temporal.timezone.prototype.getinstantfor step 3: + 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_). + sec-temporal-totemporaldatetime step 2.b: + b. If _item_ has an [[InitializedTemporalDate]] internal slot, then + i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date) => { + const timezone = new Temporal.TimeZone("UTC"); + const result = timezone.getInstantFor(date); + assert.sameValue(result.epochNanoseconds, 957_225_600_000_000_000n, "epochNanoseconds result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..d1d8bf36b2a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: RangeError thrown if a string with UTC designator is used as a PlainDateTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.TimeZone("UTC"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.getInstantFor(arg), + "String with UTC designator should not be valid as a PlainDateTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..a675238fcde0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaldatetime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.timezone.prototype.getinstantfor step 3: + 3. Set _dateTime_ ? ToTemporalDateTime(_dateTime_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const conversionTimeZone = new Temporal.TimeZone("UTC"); // should not be used to interpret the argument +const instant = conversionTimeZone.getInstantFor(datetime); + +assert.sameValue(instant.epochNanoseconds, 3661_001_000_999n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..28519c78f415 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.TimeZone("UTC"); +const result = instance.getInstantFor(datetime); +assert.sameValue(result.epochNanoseconds, -13849764_999_999_999n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..692df372bd14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const builtinTimeZone = new Temporal.TimeZone("UTC"); + assert.throws(RangeError, () => builtinTimeZone.getInstantFor(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..dc7e23df25a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const builtinTimeZone = new Temporal.TimeZone("UTC"); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => builtinTimeZone.getInstantFor(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..c3da8aec0b8a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const builtinTimeZone = new Temporal.TimeZone("UTC"); + assert.throws(RangeError, () => builtinTimeZone.getInstantFor(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..889712d4e31d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const builtinTimeZone = new Temporal.TimeZone("UTC"); + assert.throws(TypeError, () => builtinTimeZone.getInstantFor(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/balance-negative-time-units.js new file mode 100644 index 000000000000..122b502b3d92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/balance-negative-time-units.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-adddatetime step 1: + 1. Let _timeResult_ be ? AddTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-builtintimezonegetinstantfor step 13.a: + a. Let _earlier_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], 0, 0, 0, 0, 0, 0, 0, 0, 0, −_nanoseconds_, *"constrain"*). + sec-temporal.timezone.prototype.getinstantfor step 6: + 6. Return ? BuiltinTimeZoneGetInstantFor(_timeZone_, _dateTime_, _disambiguation_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const shiftInstant = new Temporal.Instant(3661_001_001_001n); +const tz = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2); +const datetime = new Temporal.PlainDateTime(1970, 1, 1, 1, 1, 1, 1, 1, 1); + +// This code path is encountered if disambiguation is `earlier` and the shift is +// a spring-forward change +tz.getInstantFor(datetime, { disambiguation: "earlier" }); + +const expected = [ + "1970-01-01T01:01:01.001001001", + "1970-01-01T01:01:01.001000999", +]; +assert.compareArray(tz.getPossibleInstantsForCalledWith, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/builtin.js new file mode 100644 index 000000000000..04fa262fdde1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: > + Tests that Temporal.TimeZone.prototype.getInstantFor + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.getInstantFor), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getInstantFor), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getInstantFor), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.getInstantFor.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..534d4f3606b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const pdt = new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, calendar); + +["earlier", "compatible", "later"].forEach((disambiguation) => { + calendar.dateAddCallCount = 0; + + timeZone.getInstantFor(pdt, { disambiguation }); + assert.sameValue(calendar.dateAddCallCount, 1, `calling with disambiguation ${disambiguation}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-fields-iterable.js new file mode 100644 index 000000000000..7df5f51aec84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-fields-iterable.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.timezone.prototype.getinstantfor step 3: + 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const timeZone = new Temporal.TimeZone("UTC"); +timeZone.getInstantFor({ year: 2000, month: 5, day: 2, calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-temporal-object.js new file mode 100644 index 000000000000..1a99d7eebf73 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.timezone.prototype.getinstantfor step 3: + 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const timeZone = new Temporal.TimeZone("UTC"); + timeZone.getInstantFor({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js new file mode 100644 index 000000000000..486928a675fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: RangeError thrown when disambiguation option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.timezone.prototype.getinstantfor step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321); +const timeZone = new Temporal.TimeZone("UTC"); +assert.throws(RangeError, () => timeZone.getInstantFor(datetime, { disambiguation: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-undefined.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-undefined.js new file mode 100644 index 000000000000..5d5562d208c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-undefined.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Fallback value for disambiguation option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.timezone.prototype.getinstantfor step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); +const springForwardDateTime = new Temporal.PlainDateTime(2000, 4, 2, 2, 30); +const fallBackDateTime = new Temporal.PlainDateTime(2000, 10, 29, 1, 30); + +[ + [springForwardDateTime, 954671400_000_000_000n], + [fallBackDateTime, 972808200_000_000_000n], +].forEach(([datetime, expected]) => { + const explicit = timeZone.getInstantFor(datetime, { disambiguation: undefined }); + assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible"); + const implicit = timeZone.getInstantFor(datetime, {}); + assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible"); + const lambda = timeZone.getInstantFor(datetime, () => {}); + assert.sameValue(lambda.epochNanoseconds, expected, "default disambiguation is compatible"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js new file mode 100644 index 000000000000..de79fec20b8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Type conversions for disambiguation option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.timezone.prototype.getinstantfor step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321); +const timeZone = new Temporal.TimeZone("UTC"); +TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible", + (disambiguation) => timeZone.getInstantFor(datetime, { disambiguation }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..3b92774dc05f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.timezone.prototype.getinstantfor +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.getInstantFor({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.getInstantFor({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/length.js new file mode 100644 index 000000000000..cac2c6708f03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Temporal.TimeZone.prototype.getInstantFor.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getInstantFor, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/name.js new file mode 100644 index 000000000000..54a73180a9be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Temporal.TimeZone.prototype.getInstantFor.name is "getInstantFor". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getInstantFor, "name", { + value: "getInstantFor", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/not-a-constructor.js new file mode 100644 index 000000000000..db08812ba2bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: > + Temporal.TimeZone.prototype.getInstantFor does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.getInstantFor(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getInstantFor), false, + "isConstructor(Temporal.TimeZone.prototype.getInstantFor)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-undefined.js new file mode 100644 index 000000000000..dfb10527cb37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +includes: [temporalHelpers.js] +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const datetimeEarlier = new Temporal.PlainDateTime(2000, 10, 29, 1, 34, 56, 987, 654, 321); +const datetimeLater = new Temporal.PlainDateTime(2000, 4, 2, 2, 34, 56, 987, 654, 321); +const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); + +[ + [datetimeEarlier, 972808496987654321n], + [datetimeLater, 954671696987654321n], +].forEach(([datetime, expected]) => { + const explicit = timeZone.getInstantFor(datetime, undefined); + assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible"); + + const implicit = timeZone.getInstantFor(datetime); + assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/prop-desc.js new file mode 100644 index 000000000000..d55828c9c77e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: The "getInstantFor" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.getInstantFor, + "function", + "`typeof TimeZone.prototype.getInstantFor` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "getInstantFor", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..fb655ff31a84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/read-time-fields-before-datefromfields.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.timezone.prototype.getinstantfor step 3: + 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_). + sec-temporal-totemporaldatetime step 2.e: + e. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timezone = new Temporal.TimeZone("UTC"); +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const result = timezone.getInstantFor({ year: 1970, month: 1, day: 1, calendar }); + +assert.sameValue(result.epochNanoseconds, 0n, "epochNanoseconds result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/year-zero.js new file mode 100644 index 000000000000..67ff13902477 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getinstantfor +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00[UTC]" +]; +const instance = new Temporal.TimeZone("UTC"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { instance.getInstantFor(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-zoneddatetime.js new file mode 100644 index 000000000000..7530526ada14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-zoneddatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getnexttransition +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.timezone.prototype.getnexttransition step 3: + 3. Set _startingPoint_ to ? ToTemporalInstant(_startingPoint_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const timeZone = Temporal.TimeZone.from("UTC"); + const result = timeZone.getNextTransition(datetime); + assert.sameValue(result, null, "transition result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/builtin.js new file mode 100644 index 000000000000..cd8968e63db4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getnexttransition +description: > + Tests that Temporal.TimeZone.prototype.getNextTransition + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.getNextTransition), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getNextTransition), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getNextTransition), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.getNextTransition.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string.js new file mode 100644 index 000000000000..a98a59bbf299 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getnexttransition +description: Conversion of ISO date-time strings to Temporal.Instant instances +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.getNextTransition(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => instance.getNextTransition(str), "date-time + IANA annotation is not an instant"); + +// The following are all valid strings so should not throw: + +const valids = [ + "1970-01-01T00:00Z", + "1970-01-01T00:00+01:00", + "1970-01-01T00:00Z[UTC]", + "1970-01-01T00:00+01:00[UTC]", +]; +for (const str of valids) { + const result = instance.getNextTransition(str); + assert.sameValue(result, null); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/length.js new file mode 100644 index 000000000000..f0d93b0f0963 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getnexttransition +description: Temporal.TimeZone.prototype.getNextTransition.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getNextTransition, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/name.js new file mode 100644 index 000000000000..ec444a82f727 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getnexttransition +description: Temporal.TimeZone.prototype.getNextTransition.name is "getNextTransition". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getNextTransition, "name", { + value: "getNextTransition", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/not-a-constructor.js new file mode 100644 index 000000000000..4de7b386db3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getnexttransition +description: > + Temporal.TimeZone.prototype.getNextTransition does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.getNextTransition(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getNextTransition), false, + "isConstructor(Temporal.TimeZone.prototype.getNextTransition)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/prop-desc.js new file mode 100644 index 000000000000..cabccb702f05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getnexttransition +description: The "getNextTransition" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.getNextTransition, + "function", + "`typeof TimeZone.prototype.getNextTransition` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "getNextTransition", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/year-zero.js new file mode 100644 index 000000000000..3aac1ad19bf5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/year-zero.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getnexttransition +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "-000000-01-01T00:00"; +assert.throws(RangeError, () => instance.getNextTransition(str), "reject minus zero as extended year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-not-absolute.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-not-absolute.js new file mode 100644 index 000000000000..30a60ed1c8ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-not-absolute.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: Appropriate error thrown when argument cannot be converted to Temporal.Instant +features: [Temporal] +---*/ + +const timeZone = Temporal.TimeZone.from("UTC"); +assert.throws(RangeError, () => timeZone.getOffsetNanosecondsFor(undefined), "undefined"); +assert.throws(RangeError, () => timeZone.getOffsetNanosecondsFor(null), "null"); +assert.throws(RangeError, () => timeZone.getOffsetNanosecondsFor(true), "boolean"); +assert.throws(RangeError, () => timeZone.getOffsetNanosecondsFor(""), "empty string"); +assert.throws(TypeError, () => timeZone.getOffsetNanosecondsFor(Symbol()), "Symbol"); +assert.throws(RangeError, () => timeZone.getOffsetNanosecondsFor(5), "number"); +assert.throws(RangeError, () => timeZone.getOffsetNanosecondsFor(5n), "bigint"); +assert.throws(RangeError, () => timeZone.getOffsetNanosecondsFor({}), "plain object"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-zoneddatetime.js new file mode 100644 index 000000000000..fe220ed296ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-zoneddatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.timezone.prototype.getoffsetnanosecondsfor step 3: + 3. Set _instant_ to ? ToTemporalInstant(_instant_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const timeZone = Temporal.TimeZone.from("UTC"); + const result = timeZone.getOffsetNanosecondsFor(datetime); + assert.sameValue(result, 0, "offset result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/builtin.js new file mode 100644 index 000000000000..359d05bb82a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: > + Tests that Temporal.TimeZone.prototype.getOffsetNanosecondsFor + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.getOffsetNanosecondsFor), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getOffsetNanosecondsFor), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getOffsetNanosecondsFor), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.getOffsetNanosecondsFor.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js new file mode 100644 index 000000000000..39dbea2938b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: Conversion of ISO date-time strings to Temporal.Instant instances +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.getOffsetNanosecondsFor(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => instance.getOffsetNanosecondsFor(str), "date-time + IANA annotation is not an instant"); + +// The following are all valid strings so should not throw: + +const valids = [ + "1970-01-01T00:00Z", + "1970-01-01T00:00+01:00", + "1970-01-01T00:00Z[UTC]", + "1970-01-01T00:00+01:00[UTC]", +]; +for (const str of valids) { + const result = instance.getOffsetNanosecondsFor(str); + assert.sameValue(result, 0); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/length.js new file mode 100644 index 000000000000..b79d63502693 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: Temporal.TimeZone.prototype.getOffsetNanosecondsFor.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getOffsetNanosecondsFor, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/name.js new file mode 100644 index 000000000000..bd828e7f1e4d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: Temporal.TimeZone.prototype.getOffsetNanosecondsFor.name is "getOffsetNanosecondsFor". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getOffsetNanosecondsFor, "name", { + value: "getOffsetNanosecondsFor", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/not-a-constructor.js new file mode 100644 index 000000000000..0f4ee59b393b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: > + Temporal.TimeZone.prototype.getOffsetNanosecondsFor does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.getOffsetNanosecondsFor(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getOffsetNanosecondsFor), false, + "isConstructor(Temporal.TimeZone.prototype.getOffsetNanosecondsFor)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/prop-desc.js new file mode 100644 index 000000000000..b1925f757f18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: The "getOffsetNanosecondsFor" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.getOffsetNanosecondsFor, + "function", + "`typeof TimeZone.prototype.getOffsetNanosecondsFor` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/year-zero.js new file mode 100644 index 000000000000..6dcba03de879 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/year-zero.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "-000000-01-01T00:00"; +assert.throws(RangeError, () => instance.getOffsetNanosecondsFor(str), "reject minus zero as extended year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute-getOffsetNanosecondsFor-override.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute-getOffsetNanosecondsFor-override.js new file mode 100644 index 000000000000..8e924f16b2eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute-getOffsetNanosecondsFor-override.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: timeZone.getOffsetNanosecondsFor not called when argument cannot be converted to Temporal.Instant +features: [Temporal] +---*/ + +const timeZone = Temporal.TimeZone.from("UTC"); +let called = false; +timeZone.getOffsetNanosecondsFor = () => called = true; +assert.throws(RangeError, () => timeZone.getOffsetStringFor(undefined), "undefined"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(null), "null"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(true), "boolean"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(""), "empty string"); +assert.throws(TypeError, () => timeZone.getOffsetStringFor(Symbol()), "Symbol"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(5), "number"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(5n), "bigint"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor({}), "plain object"); +assert.sameValue(called, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute.js new file mode 100644 index 000000000000..52c3e0f2d4ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: Appropriate error thrown when argument cannot be converted to Temporal.Instant +features: [Temporal] +---*/ + +const timeZone = Temporal.TimeZone.from("UTC"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(undefined), "undefined"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(null), "null"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(true), "boolean"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(""), "string"); +assert.throws(TypeError, () => timeZone.getOffsetStringFor(Symbol()), "Symbol"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(5), "number"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor(5n), "bigint"); +assert.throws(RangeError, () => timeZone.getOffsetStringFor({}), "plain object"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-zoneddatetime.js new file mode 100644 index 000000000000..9d6e927ebb6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-zoneddatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.timezone.prototype.getoffsetstringfor step 3: + 3. Set _instant_ to ? ToTemporalInstant(_instant_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const timeZone = Temporal.TimeZone.from("UTC"); + const result = timeZone.getOffsetStringFor(datetime); + assert.sameValue(result, "+00:00", "offset result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/basic.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/basic.js new file mode 100644 index 000000000000..4197d97c8dcc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/basic.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: Basic tests for Temporal.TimeZone.prototype.getOffsetStringFor +features: [BigInt, Temporal] +---*/ + +const instant = new Temporal.Instant(0n); + +function test(timeZoneIdentifier, expectedOffsetString, description) { + const timeZone = new Temporal.TimeZone(timeZoneIdentifier); + assert.sameValue(timeZone.getOffsetStringFor(instant), expectedOffsetString, description); +} + +test("UTC", "+00:00", "offset of UTC is +00:00"); +test("+01:00", "+01:00", "positive offset"); +test("-05:00", "-05:00", "negative offset"); +test("+00:44:59.123456789", "+00:44:59.123456789", "sub-minute offset is not rounded"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/builtin.js new file mode 100644 index 000000000000..97df7d3f6284 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: > + Tests that Temporal.TimeZone.prototype.getOffsetStringFor + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.getOffsetStringFor), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getOffsetStringFor), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getOffsetStringFor), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.getOffsetStringFor.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js new file mode 100644 index 000000000000..f67c0a7309f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: Conversion of ISO date-time strings to Temporal.Instant instances +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.getOffsetStringFor(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => instance.getOffsetStringFor(str), "date-time + IANA annotation is not an instant"); + +// The following are all valid strings so should not throw: + +const valids = [ + "1970-01-01T00:00Z", + "1970-01-01T00:00+01:00", + "1970-01-01T00:00Z[UTC]", + "1970-01-01T00:00+01:00[UTC]", +]; +for (const str of valids) { + const result = instance.getOffsetStringFor(str); + assert.sameValue(result, "+00:00"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/length.js new file mode 100644 index 000000000000..55dbee108e53 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: Temporal.TimeZone.prototype.getOffsetStringFor.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getOffsetStringFor, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/name.js new file mode 100644 index 000000000000..2fe5a8f4467b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: Temporal.TimeZone.prototype.getOffsetStringFor.name is "getOffsetStringFor". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getOffsetStringFor, "name", { + value: "getOffsetStringFor", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/not-a-constructor.js new file mode 100644 index 000000000000..cac868796a05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: > + Temporal.TimeZone.prototype.getOffsetStringFor does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.getOffsetStringFor(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getOffsetStringFor), false, + "isConstructor(Temporal.TimeZone.prototype.getOffsetStringFor)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/prop-desc.js new file mode 100644 index 000000000000..4e2508ea040f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: The "getOffsetStringFor" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.getOffsetStringFor, + "function", + "`typeof TimeZone.prototype.getOffsetStringFor` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "getOffsetStringFor", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..dfd196a6ae88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(RangeError, () => timeZone.getOffsetStringFor(instant)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..68cfdb2053ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => timeZone.getOffsetStringFor(instant), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..3c3fadf4e4a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(RangeError, () => timeZone.getOffsetStringFor(instant)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..85e92e530f0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(TypeError, () => timeZone.getOffsetStringFor(instant)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/year-zero.js new file mode 100644 index 000000000000..74378bdbe44b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/year-zero.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "-000000-01-01T00:00"; +assert.throws(RangeError, () => instance.getOffsetStringFor(str), "reject minus zero as extended year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-negative-epochnanoseconds.js new file mode 100644 index 000000000000..4c3ab883a51e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instant = new Temporal.Instant(-13849764_999_999_999n); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.TimeZone("UTC"); +const result = instance.getPlainDateTimeFor(instant); +TemporalHelpers.assertPlainDateTime(result, 1969, 7, "M07", 24, 16, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute-getOffsetNanosecondsFor-override.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute-getOffsetNanosecondsFor-override.js new file mode 100644 index 000000000000..961f33be1a80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute-getOffsetNanosecondsFor-override.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: timeZone.getOffsetNanosecondsFor not called when argument cannot be converted to Temporal.Instant +features: [Temporal] +---*/ + +const timeZone = Temporal.TimeZone.from("UTC"); +let called = false; +timeZone.getOffsetNanosecondsFor = () => called = true; +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(undefined), "undefined"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(null), "null"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(true), "boolean"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(""), "empty string"); +assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(Symbol()), "Symbol"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(5), "number"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(5n), "bigint"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor({}), "plain object"); +assert.sameValue(called, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute.js new file mode 100644 index 000000000000..67ae4f84e936 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Appropriate error thrown when argument cannot be converted to Temporal.Instant +features: [Temporal] +---*/ + +const timeZone = Temporal.TimeZone.from("UTC"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(undefined), "undefined"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(null), "null"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(true), "boolean"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(""), "empty string"); +assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(Symbol()), "Symbol"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(5), "number"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(5n), "bigint"); +assert.throws(RangeError, () => timeZone.getPlainDateTimeFor({}), "plain object"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-zoneddatetime.js new file mode 100644 index 000000000000..983a8edf2be8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-zoneddatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.timezone.prototype.getplaindatetimefor step 2: + 2. Set _instant_ to ? ToTemporalInstant(_instant_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const timeZone = Temporal.TimeZone.from("UTC"); + const result = timeZone.getPlainDateTimeFor(datetime); + TemporalHelpers.assertPlainDateTime(result, 2001, 9, "M09", 9, 1, 46, 40, 987, 654, 321); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/balance-negative-time-units.js new file mode 100644 index 000000000000..f623639af004 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/balance-negative-time-units.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.timezone.prototype.getplaindatetimefor step 4: + 4. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const instant = new Temporal.Instant(1001n); + +const pdt = tz.getPlainDateTimeFor(instant); + +TemporalHelpers.assertPlainDateTime(pdt, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/branding.js new file mode 100644 index 000000000000..f6fd80a63491 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const getPlainDateTimeFor = Temporal.TimeZone.prototype.getPlainDateTimeFor; + + const args = [new Temporal.Instant(0n)]; + +assert.throws(TypeError, () => getPlainDateTimeFor.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => getPlainDateTimeFor.apply(null, args), "null"); +assert.throws(TypeError, () => getPlainDateTimeFor.apply(true, args), "true"); +assert.throws(TypeError, () => getPlainDateTimeFor.apply("", args), "empty string"); +assert.throws(TypeError, () => getPlainDateTimeFor.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => getPlainDateTimeFor.apply(1, args), "1"); +assert.throws(TypeError, () => getPlainDateTimeFor.apply({}, args), "plain object"); +assert.throws(TypeError, () => getPlainDateTimeFor.apply(Temporal.TimeZone, args), "Temporal.TimeZone"); +assert.throws(TypeError, () => getPlainDateTimeFor.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/builtin.js new file mode 100644 index 000000000000..6a474266aaa7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: > + Tests that Temporal.TimeZone.prototype.getPlainDateTimeFor + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.getPlainDateTimeFor), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getPlainDateTimeFor), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getPlainDateTimeFor), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.getPlainDateTimeFor.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-temporal-object.js new file mode 100644 index 000000000000..6bccdb4b2f46 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-temporal-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.instant.prototype.tozoneddatetime step 6: + 6. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + const timezone = new Temporal.TimeZone("UTC"); + const result = timezone.getPlainDateTimeFor(instant, temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-undefined.js new file mode 100644 index 000000000000..38eae262e901 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Calendar argument defaults to the built-in ISO 8601 calendar +features: [Temporal] +---*/ + +const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456789Z"); +const timeZone = Temporal.TimeZone.from("UTC"); + +Object.defineProperty(Temporal.Calendar, "from", { + get() { + throw new Test262Error("Should not call Calendar.from"); + }, +}); + +const result1 = timeZone.getPlainDateTimeFor(instant); +assert.sameValue(result1.calendar.toString(), "iso8601"); + +const result2 = timeZone.getPlainDateTimeFor(instant, undefined); +assert.sameValue(result2.calendar.toString(), "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/custom-timezone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/custom-timezone.js new file mode 100644 index 000000000000..e53343cc6f51 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/custom-timezone.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: getOffsetNanosecondsFor is called by getPlainDateTimeFor +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "get getOffsetNanosecondsFor", + "call timeZone.getOffsetNanosecondsFor", +]; + +const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456789Z"); +const timeZone = new Temporal.TimeZone("UTC"); +TemporalHelpers.observeProperty(actual, timeZone, "getOffsetNanosecondsFor", function (instantArg) { + actual.push("call timeZone.getOffsetNanosecondsFor"); + assert.sameValue(instantArg, instant); + return 9876543210123; +}); + +const result = timeZone.getPlainDateTimeFor(instant); +TemporalHelpers.assertPlainDateTime(result, 1975, 2, "M02", 2, 17, 10, 12, 666, 666, 912); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-multiple-offsets.js new file mode 100644 index 000000000000..2e6d22b4348a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-multiple-offsets.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Instant strings with UTC offset fractional part are not confused with time fractional part +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "UTC offset determined from offset part of string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js new file mode 100644 index 000000000000..b6ace7229606 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Conversion of ISO date-time strings to Temporal.Instant instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.getPlainDateTimeFor(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => instance.getPlainDateTimeFor(str), "date-time + IANA annotation is not an instant"); + +str = "1970-01-01T00:00Z"; +const result1 = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result1, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "date-time + Z preserves exact time"); + +str = "1970-01-01T00:00+01:00"; +const result2 = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result2, 1969, 12, "M12", 31, 23, 0, 0, 0, 0, 0, "date-time + offset preserves exact time with offset"); + +str = "1970-01-01T00:00Z[Etc/Ignored]"; +const result3 = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result3, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation ignores the IANA annotation"); + +str = "1970-01-01T00:00+01:00[Etc/Ignored]"; +const result4 = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result4, 1969, 12, "M12", 31, 23, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation ignores the IANA annotation"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/length.js new file mode 100644 index 000000000000..7f2a83d61d6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Temporal.TimeZone.prototype.getPlainDateTimeFor.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getPlainDateTimeFor, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/name.js new file mode 100644 index 000000000000..517769b7b798 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Temporal.TimeZone.prototype.getPlainDateTimeFor.name is "getPlainDateTimeFor". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getPlainDateTimeFor, "name", { + value: "getPlainDateTimeFor", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/not-a-constructor.js new file mode 100644 index 000000000000..2cd257512080 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: > + Temporal.TimeZone.prototype.getPlainDateTimeFor does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.getPlainDateTimeFor(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getPlainDateTimeFor), false, + "isConstructor(Temporal.TimeZone.prototype.getPlainDateTimeFor)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/pre-epoch.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/pre-epoch.js new file mode 100644 index 000000000000..082d6c872862 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/pre-epoch.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Test of basic functionality for an exact time earlier than the Unix epoch +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instant = Temporal.Instant.from("1969-07-16T13:32:01.234567891Z"); +assert.sameValue(instant.toString(), "1969-07-16T13:32:01.234567891Z"); +const timeZone = Temporal.TimeZone.from("-04:00"); +const dateTime = timeZone.getPlainDateTimeFor(instant); +TemporalHelpers.assertPlainDateTime(dateTime, 1969, 7, "M07", 16, 9, 32, 1, 234, 567, 891); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/prop-desc.js new file mode 100644 index 000000000000..c45fdc797435 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: The "getPlainDateTimeFor" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.getPlainDateTimeFor, + "function", + "`typeof TimeZone.prototype.getPlainDateTimeFor` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "getPlainDateTimeFor", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..e5855c737b6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(instant)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..da4a7aaefa65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => timeZone.getPlainDateTimeFor(instant), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..7a77349e60c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(instant)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..59a3ddca1c07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const instant = new Temporal.Instant(1_000_000_000_987_654_321n); + assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(instant)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/year-zero.js new file mode 100644 index 000000000000..1057f2868e14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "-000000-03-30T00:45Z", + "-000000-03-30T01:45+01:00", + "-000000-03-30T01:45:00+01:00[UTC]" +]; +const instance = new Temporal.TimeZone("UTC"); +invalidStrings.forEach((str) => { + assert.throws( + RangeError, + () => instance.getPlainDateTimeFor(str), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-not-datetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-not-datetime.js new file mode 100644 index 000000000000..d96f7dbb689d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-not-datetime.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: Appropriate error thrown when argument cannot be converted to Temporal.PlainDateTime +features: [Temporal] +---*/ + +const timeZone = Temporal.TimeZone.from("UTC"); +assert.throws(RangeError, () => timeZone.getPossibleInstantsFor(undefined), "undefined"); +assert.throws(RangeError, () => timeZone.getPossibleInstantsFor(null), "null"); +assert.throws(RangeError, () => timeZone.getPossibleInstantsFor(true), "boolean"); +assert.throws(RangeError, () => timeZone.getPossibleInstantsFor(""), "empty string"); +assert.throws(TypeError, () => timeZone.getPossibleInstantsFor(Symbol()), "Symbol"); +assert.throws(RangeError, () => timeZone.getPossibleInstantsFor(5), "number"); +assert.throws(RangeError, () => timeZone.getPossibleInstantsFor(5n), "bigint"); +assert.throws(TypeError, () => timeZone.getPossibleInstantsFor({}), "plain object"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-plaindate.js new file mode 100644 index 000000000000..3f88e8377311 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-plaindate.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots +info: | + sec-temporal.timezone.prototype.getpossibleinstantsfor step 3: + 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_). + sec-temporal-totemporaldatetime step 2.b: + b. If _item_ has an [[InitializedTemporalDate]] internal slot, then + i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date) => { + const timezone = new Temporal.TimeZone("UTC"); + const result = timezone.getPossibleInstantsFor(date); + assert.sameValue(result.length, 1, "one possible instant"); + assert.sameValue(result[0].epochNanoseconds, 957_225_600_000_000_000n, "epochNanoseconds result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..653e64f9d0bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: RangeError thrown if a string with UTC designator is used as a PlainDateTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.TimeZone("UTC"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.getPossibleInstantsFor(arg), + "String with UTC designator should not be valid as a PlainDateTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..b66e0db9d781 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaldatetime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.timezone.prototype.getpossibleinstantsfor step 3: + 3. Set _dateTime_ ? ToTemporalDateTime(_dateTime_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const conversionTimeZone = new Temporal.TimeZone("UTC"); // should not be used to interpret the argument +const instants = conversionTimeZone.getPossibleInstantsFor(datetime); + +assert.sameValue(instants.length, 1); +assert.sameValue(instants[0].epochNanoseconds, 3661_001_000_999n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..e9c3c669e3e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [compareArray.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.TimeZone("UTC"); +const result = instance.getPossibleInstantsFor(datetime); +assert.compareArray(result.map((i) => i.epochNanoseconds), [-13849764_999_999_999n]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..ad8c07520ba3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const builtinTimeZone = new Temporal.TimeZone("UTC"); + assert.throws(RangeError, () => builtinTimeZone.getPossibleInstantsFor(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..117c847d3ff8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const builtinTimeZone = new Temporal.TimeZone("UTC"); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => builtinTimeZone.getPossibleInstantsFor(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..66024ead2c7d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const builtinTimeZone = new Temporal.TimeZone("UTC"); + assert.throws(RangeError, () => builtinTimeZone.getPossibleInstantsFor(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..de875bf46400 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const builtinTimeZone = new Temporal.TimeZone("UTC"); + assert.throws(TypeError, () => builtinTimeZone.getPossibleInstantsFor(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/builtin.js new file mode 100644 index 000000000000..7a73b6014988 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: > + Tests that Temporal.TimeZone.prototype.getPossibleInstantsFor + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.getPossibleInstantsFor), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getPossibleInstantsFor), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getPossibleInstantsFor), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.getPossibleInstantsFor.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-fields-iterable.js new file mode 100644 index 000000000000..161d017d97c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-fields-iterable.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.timezone.prototype.getpossibleinstantsfor step 3: + 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const timeZone = new Temporal.TimeZone("UTC"); +timeZone.getPossibleInstantsFor({ year: 2000, month: 5, day: 2, calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-temporal-object.js new file mode 100644 index 000000000000..c7a1be4174c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.timezone.prototype.getpossibleinstantsfor step 3: + 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_). + sec-temporal-totemporaldatetime step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const timeZone = new Temporal.TimeZone("UTC"); + timeZone.getPossibleInstantsFor({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..8af5905d3e33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.getPossibleInstantsFor({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.getPossibleInstantsFor({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/length.js new file mode 100644 index 000000000000..a207968dc5af --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: Temporal.TimeZone.prototype.getPossibleInstantsFor.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getPossibleInstantsFor, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/name.js new file mode 100644 index 000000000000..0e46a244629e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: Temporal.TimeZone.prototype.getPossibleInstantsFor.name is "getPossibleInstantsFor". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getPossibleInstantsFor, "name", { + value: "getPossibleInstantsFor", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/not-a-constructor.js new file mode 100644 index 000000000000..13eb622abbb8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: > + Temporal.TimeZone.prototype.getPossibleInstantsFor does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.getPossibleInstantsFor(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getPossibleInstantsFor), false, + "isConstructor(Temporal.TimeZone.prototype.getPossibleInstantsFor)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/prop-desc.js new file mode 100644 index 000000000000..7807b3d11ea7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: The "getPossibleInstantsFor" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.getPossibleInstantsFor, + "function", + "`typeof TimeZone.prototype.getPossibleInstantsFor` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "getPossibleInstantsFor", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..d594463cfe14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/read-time-fields-before-datefromfields.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.timezone.prototype.getpossibleinstantsfor step 3: + 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_). + sec-temporal-totemporaldatetime step 2.e: + e. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timezone = new Temporal.TimeZone("UTC"); +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const result = timezone.getPossibleInstantsFor({ year: 1970, month: 1, day: 1, calendar }); + +assert.sameValue(result.length, 1, "result array length"); +assert.sameValue(result[0].epochNanoseconds, 0n, "epochNanoseconds result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/year-zero.js new file mode 100644 index 000000000000..656e43ed58de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00[UTC]" +]; +const instance = new Temporal.TimeZone("UTC"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => { instance.getPossibleInstantsFor(arg); }, + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-zoneddatetime.js new file mode 100644 index 000000000000..0be016a1a90d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-zoneddatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getprevioustransition +description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant +info: | + sec-temporal.timezone.prototype.getprevioustransition step 3: + 3. Set _startingPoint_ to ? ToTemporalInstant(_startingPoint_). + sec-temporal-totemporalinstant step 1.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalInstantFastPath((datetime) => { + const timeZone = Temporal.TimeZone.from("UTC"); + const result = timeZone.getPreviousTransition(datetime); + assert.sameValue(result, null, "transition result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/builtin.js new file mode 100644 index 000000000000..28dd0fbfc181 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getprevioustransition +description: > + Tests that Temporal.TimeZone.prototype.getPreviousTransition + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.getPreviousTransition), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getPreviousTransition), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getPreviousTransition), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.getPreviousTransition.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string.js new file mode 100644 index 000000000000..b8e52d6f9fd2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getprevioustransition +description: Conversion of ISO date-time strings to Temporal.Instant instances +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.getPreviousTransition(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[UTC]"; +assert.throws(RangeError, () => instance.getPreviousTransition(str), "date-time + IANA annotation is not an instant"); + +// The following are all valid strings so should not throw: + +const valids = [ + "1970-01-01T00:00Z", + "1970-01-01T00:00+01:00", + "1970-01-01T00:00Z[UTC]", + "1970-01-01T00:00+01:00[UTC]", +]; +for (const str of valids) { + const result = instance.getPreviousTransition(str); + assert.sameValue(result, null); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/length.js new file mode 100644 index 000000000000..37a5b93e7370 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getprevioustransition +description: Temporal.TimeZone.prototype.getPreviousTransition.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getPreviousTransition, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/name.js new file mode 100644 index 000000000000..637ae204844a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getprevioustransition +description: Temporal.TimeZone.prototype.getPreviousTransition.name is "getPreviousTransition". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.getPreviousTransition, "name", { + value: "getPreviousTransition", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/not-a-constructor.js new file mode 100644 index 000000000000..ec424e01efd0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getprevioustransition +description: > + Temporal.TimeZone.prototype.getPreviousTransition does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.getPreviousTransition(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getPreviousTransition), false, + "isConstructor(Temporal.TimeZone.prototype.getPreviousTransition)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/prop-desc.js new file mode 100644 index 000000000000..01d4f38f8dc9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getprevioustransition +description: The "getPreviousTransition" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.getPreviousTransition, + "function", + "`typeof TimeZone.prototype.getPreviousTransition` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "getPreviousTransition", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/shell.js index e69de29bb2d1..5228295abfe7 100644 --- a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/year-zero.js new file mode 100644 index 000000000000..90d020696037 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/year-zero.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getprevioustransition +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); + +let str = "-000000-01-01T00:00"; +assert.throws(RangeError, () => instance.getPreviousTransition(str), "reject minus zero as extended year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/prop-desc.js new file mode 100644 index 000000000000..5caf215a07e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-timezone-prototype +description: The "prototype" property of Temporal.TimeZone +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.TimeZone.prototype, "object"); +assert.notSameValue(Temporal.TimeZone.prototype, null); + +verifyProperty(Temporal.TimeZone, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/branding.js new file mode 100644 index 000000000000..55f3468d1a9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toJSON = Temporal.TimeZone.prototype.toJSON; + +assert.sameValue(typeof toJSON, "function"); + +assert.throws(TypeError, () => toJSON.call(undefined), "undefined"); +assert.throws(TypeError, () => toJSON.call(null), "null"); +assert.throws(TypeError, () => toJSON.call(true), "true"); +assert.throws(TypeError, () => toJSON.call(""), "empty string"); +assert.throws(TypeError, () => toJSON.call(Symbol()), "symbol"); +assert.throws(TypeError, () => toJSON.call(1), "1"); +assert.throws(TypeError, () => toJSON.call({}), "plain object"); +assert.throws(TypeError, () => toJSON.call(Temporal.TimeZone), "Temporal.TimeZone"); +assert.throws(TypeError, () => toJSON.call(Temporal.TimeZone.prototype), "Temporal.TimeZone.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..c16a991198e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: > + Tests that Temporal.TimeZone.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/length.js new file mode 100644 index 000000000000..7d4793a80725 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: Temporal.TimeZone.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/name.js new file mode 100644 index 000000000000..8149ad217950 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: Temporal.TimeZone.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..be0d115a199d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: > + Temporal.TimeZone.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.toJSON), false, + "isConstructor(Temporal.TimeZone.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..13ef61b29600 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: The "toJSON" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.toJSON, + "function", + "`typeof TimeZone.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-call.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-call.js new file mode 100644 index 000000000000..b55e07670915 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-call.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: toJSON() calls toString() and returns its value +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + 'get [Symbol.toPrimitive]', + 'get toString', + 'call timeZone.toString', +]; + +const timeZone = new Temporal.TimeZone("UTC"); +TemporalHelpers.observeProperty(actual, timeZone, Symbol.toPrimitive, undefined); +TemporalHelpers.observeProperty(actual, timeZone, "toString", function () { + actual.push("call timeZone.toString"); + return "Etc/TAI"; +}); + +const result = timeZone.toJSON(); +assert.sameValue(result, 'Etc/TAI', 'toString'); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-undefined-custom.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-undefined-custom.js new file mode 100644 index 000000000000..d8a47e601844 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-undefined-custom.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: TypeError thrown when toString property not present +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + 'get [Symbol.toPrimitive]', + 'get toString', + 'get valueOf', +]; + +const timeZone = new Temporal.TimeZone("UTC"); +TemporalHelpers.observeProperty(actual, timeZone, Symbol.toPrimitive, undefined); +TemporalHelpers.observeProperty(actual, timeZone, "toString", undefined); +TemporalHelpers.observeProperty(actual, timeZone, "valueOf", Object.prototype.valueOf); + +assert.throws(TypeError, () => timeZone.toJSON()); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-undefined.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-undefined.js new file mode 100644 index 000000000000..1a8f80be9858 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/tostring-undefined.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tojson +description: TypeError thrown when toString property not present +features: [Temporal] +---*/ + +const tz = Temporal.TimeZone.from('UTC'); +tz.toString = undefined; + +assert.throws(TypeError, () => tz.toJSON()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/builtin.js new file mode 100644 index 000000000000..272decf5f29a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tostring +description: > + Tests that Temporal.TimeZone.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.TimeZone.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/length.js new file mode 100644 index 000000000000..367b49732e75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tostring +description: Temporal.TimeZone.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/name.js new file mode 100644 index 000000000000..35e4154ae18e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tostring +description: Temporal.TimeZone.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.TimeZone.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..0eba8d4a5737 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tostring +description: > + Temporal.TimeZone.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.TimeZone.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.TimeZone.prototype.toString), false, + "isConstructor(Temporal.TimeZone.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..388c4688fc88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.tostring +description: The "toString" property of Temporal.TimeZone.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.TimeZone.prototype.toString, + "function", + "`typeof TimeZone.prototype.toString` is `function`" +); + +verifyProperty(Temporal.TimeZone.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/builtin.js new file mode 100644 index 000000000000..be60cdf06a26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: Tests that Temporal.ZonedDateTime meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.ZonedDateTime.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/calendar-temporal-object.js new file mode 100644 index 000000000000..d51dc8a49cb7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/calendar-temporal-object.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime step 5: + 5. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/calendar-undefined.js new file mode 100644 index 000000000000..0aa9b9ff8aa5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/calendar-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: Calendar argument defaults to the built-in ISO 8601 calendar +features: [BigInt, Temporal] +---*/ + +const args = [957270896987654321n, new Temporal.TimeZone("UTC")]; + +Object.defineProperty(Temporal.Calendar, "from", { + get() { + throw new Test262Error("Should not get Calendar.from"); + }, +}); + +const explicit = new Temporal.ZonedDateTime(...args, undefined); +assert.sameValue(explicit.calendar.toString(), "iso8601"); + +const implicit = new Temporal.ZonedDateTime(...args); +assert.sameValue(implicit.calendar.toString(), "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-offset-not-agreeing-with-timezone.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-offset-not-agreeing-with-timezone.js new file mode 100644 index 000000000000..46764e59a0f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-offset-not-agreeing-with-timezone.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Property bag with offset property is rejected if offset does not agree with time zone +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+01:00"); +const datetime = new Temporal.ZonedDateTime(0n, timeZone); + +const properties = { year: 2021, month: 10, day: 28, offset: "-07:00", timeZone }; +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(properties, datetime), "offset property not matching time zone is rejected (first argument)"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(datetime, properties), "offset property not matching time zone is rejected (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..6e7962f6849f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, Infinity, -Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare({ year: 2000, month: 5, day: 2, hour: 12, timeZone }, datetime)); + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(datetime, { year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..969d8bcf0683 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.ZonedDateTime.compare({ year: 2000, month: 5, day: 2, hour: 12, timeZone }, datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); + assert.throws( + TypeError, + () => Temporal.ZonedDateTime.compare(datetime, { year: 2000, month: 5, day: 2, hour: 12, timeZone }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..b20eaafa9ef9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare({ year: 2000, month: 5, day: 2, hour: 12, timeZone }, datetime)); + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(datetime, { year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..0678009aaa42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(TypeError, () => Temporal.ZonedDateTime.compare({ year: 2000, month: 5, day: 2, hour: 12, timeZone }, datetime)); + assert.throws(TypeError, () => Temporal.ZonedDateTime.compare(datetime, { year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/browser.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/builtin.js new file mode 100644 index 000000000000..ce6f855d7f5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Tests that Temporal.ZonedDateTime.compare meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.compare), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.compare), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.compare), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.compare.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/calendar-fields-iterable.js new file mode 100644 index 000000000000..4be73132004c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/calendar-fields-iterable.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalZonedDateTime(_one_). + 2. Set _two_ to ? ToTemporalZonedDateTime(_two_). + sec-temporal-totemporalzoneddatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +Temporal.ZonedDateTime.compare( + { year: 2000, month: 5, day: 2, timeZone: "UTC", calendar: calendar1 }, + { year: 2001, month: 6, day: 3, timeZone: "UTC", calendar: calendar2 }, +); + +assert.sameValue(calendar1.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar1.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar1.iteratorExhausted[0], "iterated through the whole iterable"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/calendar-temporal-object.js new file mode 100644 index 000000000000..e7db462ed55a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/calendar-temporal-object.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalZonedDateTime(_one_). + 2. Set _two_ to ? ToTemporalZonedDateTime(_two_). + sec-temporal-totemporalzoneddatetime step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + Temporal.ZonedDateTime.compare( + { year: 2000, month: 5, day: 2, timeZone: "UTC", calendar: temporalObject }, + { year: 2001, month: 6, day: 3, timeZone: "UTC", calendar: temporalObject }, + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..085de6d7b7a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/infinity-throws-rangeerror.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const other = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321, timeZone: "UTC" }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare({ ...base, [prop]: inf }, other), `${prop} property cannot be ${inf}`); + + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(other, { ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, prop); + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare({ ...base, [prop]: obj1 }, other)); + assert.compareArray(calls1, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, prop); + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(other, { ...base, [prop]: obj2 })); + assert.compareArray(calls2, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/length.js new file mode 100644 index 000000000000..c857f94a165d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Temporal.ZonedDateTime.compare.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.compare, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/name.js new file mode 100644 index 000000000000..87eb03562df3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Temporal.ZonedDateTime.compare.name is "compare" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.compare, "name", { + value: "compare", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/not-a-constructor.js new file mode 100644 index 000000000000..d6c5925328bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Temporal.ZonedDateTime.compare does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.compare(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.compare), false, + "isConstructor(Temporal.ZonedDateTime.compare)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/prop-desc.js new file mode 100644 index 000000000000..342c1da72860 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: The "compare" property of Temporal.ZonedDateTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.compare, + "function", + "`typeof ZonedDateTime.compare` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime, "compare", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..1213bbd21747 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/read-time-fields-before-datefromfields.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.zoneddatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalZonedDateTime(_one_). + 2. Set _two_ to ? ToTemporalZonedDateTime(_two_). + sec-temporal-totemporalzoneddatetime step 2.j: + j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const result = Temporal.ZonedDateTime.compare( + { year: 2000, month: 5, day: 2, hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321, timeZone: "UTC", calendar }, + { year: 2000, month: 5, day: 2, hour: 6, minute: 54, second: 32, millisecond: 123, microsecond: 456, nanosecond: 789, timeZone: "UTC", calendar }, +); + +// will be 0 if the time fields are coerced to their max values due to Infinity +assert.sameValue(result, 1, "comparison result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..94fb26499782 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.zoneddatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalZonedDateTime(_one_). + 2. Set _two_ to ? ToTemporalZonedDateTime(_two_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "2000-05-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + Temporal.ZonedDateTime.compare( + { year: 2000, month: 5, day: 2, timeZone }, + { year: 2001, month: 6, day: 3, timeZone: "UTC" }, + ); +}, expected1); + +// Same, but on the other operand + +const expected2 = [ + "2001-06-03T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + Temporal.ZonedDateTime.compare( + { year: 2000, month: 5, day: 2, timeZone: "UTC" }, + { year: 2001, month: 6, day: 3, timeZone }, + ); +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/timezone-string-datetime.js new file mode 100644 index 000000000000..9da47e501814 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/timezone-string-datetime.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(0n, "UTC"); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare({ year: 2000, month: 5, day: 2, timeZone }, instance), "bare date-time string is not a time zone (arg 1)"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(instance, { year: 2000, month: 5, day: 2, timeZone }), "bare date-time string is not a time zone (arg 2)"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }, instance), "bare date-time string is not a time zone (arg 1)"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(instance, { year: 2000, month: 5, day: 2, timeZone: { timeZone } }), "bare date-time string is not a time zone (arg 2)"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T17:30-07:00", + "2021-08-19T17:30[UTC]", + "2021-08-19T17:30Z[UTC]", + "2021-08-19T17:30-07:00[UTC]", +].forEach((timeZone) => { + Temporal.ZonedDateTime.compare({ year: 2000, month: 5, day: 2, timeZone }, instance); + Temporal.ZonedDateTime.compare(instance, { year: 2000, month: 5, day: 2, timeZone }); + Temporal.ZonedDateTime.compare({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }, instance); + Temporal.ZonedDateTime.compare(instance, { year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/year-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/year-zero.js new file mode 100644 index 000000000000..756f6d02dcbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/year-zero.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Negative zero, as an extended year, fails +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(0n, "UTC"); +const bad = "-000000-08-19T17:30Z"; + +assert.throws(RangeError, + () => Temporal.ZonedDateTime.compare(bad, instance), + "cannot use negative zero as extended year (first argument)" +); +assert.throws(RangeError, + () => Temporal.ZonedDateTime.compare(instance, bad), + "cannot use negative zero as extended year (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/zoneddatetime-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/zoneddatetime-string-multiple-offsets.js new file mode 100644 index 000000000000..77559c27edf2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/zoneddatetime-string-multiple-offsets.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: ZonedDateTime strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(29_012_345_679n, "+00:01:30.987654321"); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +assert.sameValue(Temporal.ZonedDateTime.compare(str, datetime), 0, "Time zone determined from bracket name (first argument)"); +assert.sameValue(Temporal.ZonedDateTime.compare(datetime, str), 0, "Time zone determined from bracket name (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/zoneddatetime-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/zoneddatetime-string.js new file mode 100644 index 000000000000..0273a4f3ddfb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/compare/zoneddatetime-string.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +description: Conversion of ISO date-time strings to Temporal.ZonedDateTime instances +features: [Temporal] +---*/ + +const epoch = new Temporal.ZonedDateTime(0n, "UTC"); +const hourBefore = new Temporal.ZonedDateTime(-3600_000_000_000n, "UTC"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(str, epoch), "bare date-time string is not a ZonedDateTime (first argument)"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(epoch, str), "bare date-time string is not a ZonedDateTime (second argument)"); +str = "1970-01-01T00:00Z"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(str, epoch), "date-time + Z is not a ZonedDateTime (first argument)"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(epoch, str), "date-time + Z is not a ZonedDateTime (second argument)"); +str = "1970-01-01T00:00+01:00"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(str, epoch), "date-time + offset is not a ZonedDateTime (first argument)"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(epoch, str), "date-time + offset is not a ZonedDateTime (second argument)"); + +str = "1970-01-01T00:00[+01:00]"; +const result1 = Temporal.ZonedDateTime.compare(str, hourBefore); +assert.sameValue(result1, 0, "date-time + IANA annotation preserves wall time in the time zone (first argument)"); +const result2 = Temporal.ZonedDateTime.compare(hourBefore, str); +assert.sameValue(result2, 0, "date-time + IANA annotation preserves wall time in the time zone (second argument)"); + +str = "1970-01-01T00:00Z[+01:00]"; +const result3 = Temporal.ZonedDateTime.compare(str, epoch); +assert.sameValue(result3, 0, "date-time + Z + IANA annotation preserves exact time in the time zone (first argument)"); +const result4 = Temporal.ZonedDateTime.compare(epoch, str); +assert.sameValue(result4, 0, "date-time + Z + IANA annotation preserves exact time in the time zone (second argument)"); + +str = "1970-01-01T00:00+01:00[+01:00]"; +const result5 = Temporal.ZonedDateTime.compare(str, hourBefore); +assert.sameValue(result5, 0, "date-time + offset + IANA annotation ensures both exact and wall time match (first argument)"); +const result6 = Temporal.ZonedDateTime.compare(hourBefore, str); +assert.sameValue(result6, 0, "date-time + offset + IANA annotation ensures both exact and wall time match (second argument)"); + +str = "1970-01-01T00:00-04:15[+01:00]"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(str, epoch), "date-time + offset + IANA annotation throws if wall time and exact time mismatch (first argument)"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(epoch, str), "date-time + offset + IANA annotation throws if wall time and exact time mismatch (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/constructor.js new file mode 100644 index 000000000000..d3cb999c72e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: Temporal.ZonedDateTime constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.ZonedDateTime()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-offset-not-agreeing-with-timezone.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-offset-not-agreeing-with-timezone.js new file mode 100644 index 000000000000..62c4f3ab06fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-offset-not-agreeing-with-timezone.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Property bag with offset property is rejected if offset does not agree with time zone +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+01:00"); + +const properties = { year: 2021, month: 10, day: 28, offset: "-07:00", timeZone }; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(properties), "offset property not matching time zone is rejected"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..7a4b901d7422 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(RangeError, () => Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..8f0c882334b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.zoneddatetime.from +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, hour: 12, offset: "+00:00", timeZone }, { offset: "prefer" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=prefer and no disambiguation case)` + ); + + const badTimeZone = { + getPossibleInstantsFor() { return []; }, + getOffsetNanosecondsFor: notCallable, + }; + assert.throws( + TypeError, + () => Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, hour: 12, offset: "+00:00", timeZone: badTimeZone }, { offset: "ignore" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=ignore and no possible instants case)` + ); + assert.throws( + TypeError, + () => Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, hour: 12, offset: "+00:00", timeZone: badTimeZone }, { offset: "prefer" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=prefer and no possible instants case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..a02f1f6a18af --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(RangeError, () => Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..f2d16273e4b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + + assert.throws(TypeError, () => Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/balance-negative-time-units.js new file mode 100644 index 000000000000..9e6f192bd6dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/balance-negative-time-units.js @@ -0,0 +1,91 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-adddatetime step 1: + 1. Let _timeResult_ be ? AddTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-builtintimezonegetinstantfor step 13.a: + a. Let _earlier_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], 0, 0, 0, 0, 0, 0, 0, 0, 0, −_nanoseconds_, *"constrain"*). + sec-temporal-interpretisodatetimeoffset steps 4–10: + 4. If _offsetNanoseconds_ is *null*, or _offset_ is *"ignore"*, then + a. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _dateTime_, _disambiguation_). + ... + ... + 6. Assert: _offset_ is *"prefer"* or *"reject"*. + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + ... + 9. If _offset_ is *"reject"*, throw a *RangeError* exception. + 10. Let _instant_ be ? DisambiguatePossibleInstants(_possibleInstants_, _timeZone_, _dateTime_, _disambiguation_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal.zoneddatetime.from step 3: + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const shiftInstant = new Temporal.Instant(3661_001_001_001n); +const tz1 = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2); + +// This code path is encountered if offset is `ignore` or `prefer`, +// disambiguation is `earlier` and the shift is a spring-forward change +Temporal.ZonedDateTime.from({ + year: 1970, + month: 1, + day: 1, + hour: 1, + minute: 1, + second: 1, + millisecond: 1, + microsecond: 1, + nanosecond: 1, + timeZone: tz1, +}, { offset: "ignore", disambiguation: "earlier" }); + +const expected1 = [ + "1970-01-01T01:01:01.001001001", + "1970-01-01T01:01:01.001000999", +]; +assert.compareArray(tz1.getPossibleInstantsForCalledWith, expected1); + +const tz2 = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2); + +Temporal.ZonedDateTime.from({ + year: 1970, + month: 1, + day: 1, + hour: 1, + minute: 1, + second: 1, + millisecond: 1, + microsecond: 1, + nanosecond: 1, + timeZone: tz2, +}, { offset: "prefer", disambiguation: "earlier" }); + +const expected2 = [ + "1970-01-01T01:01:01.001001001", + "1970-01-01T01:01:01.001000999", +]; +assert.compareArray(tz2.getPossibleInstantsForCalledWith, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/browser.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/builtin.js new file mode 100644 index 000000000000..f60909aae590 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Tests that Temporal.ZonedDateTime.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/calendar-fields-iterable.js new file mode 100644 index 000000000000..45f5b5c228a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/calendar-fields-iterable.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.from step 3: + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). + sec-temporal-totemporalzoneddatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: "UTC", calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/calendar-temporal-object.js new file mode 100644 index 000000000000..761535f32edb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime.from step 3: + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). + sec-temporal-totemporalzoneddatetime step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const result = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: "UTC", calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-invalid-string.js new file mode 100644 index 000000000000..64640f24967a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-invalid-string.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: RangeError thrown when disambiguation option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal-totemporalzoneddatetime step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). + sec-temporal.zoneddatetime.from step 2: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + a. ... + b. Perform ? ToTemporalDisambiguation(_options_). + c. ... + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(datetime, { disambiguation: "other string" })); + +const timeZone = new Temporal.TimeZone("UTC"); +const propertyBag = { timeZone, year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321 }; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { disambiguation: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-undefined.js new file mode 100644 index 000000000000..2f1fe964ae5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-undefined.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Fallback value for disambiguation option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal-totemporalzoneddatetime step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). + sec-temporal.zoneddatetime.from step 2: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); +const springForwardFields = { timeZone, year: 2000, month: 4, day: 2, hour: 2, minute: 30 }; +const fallBackFields = { timeZone, year: 2000, month: 10, day: 29, hour: 1, minute: 30 }; + +[ + [springForwardFields, 954671400_000_000_000n], + [fallBackFields, 972808200_000_000_000n], +].forEach(([fields, expected]) => { + const explicit = Temporal.ZonedDateTime.from(fields, { disambiguation: undefined }); + assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible (later)"); + + // See options-undefined.js for {} +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-wrong-type.js new file mode 100644 index 000000000000..3de9c58a0994 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/disambiguation-wrong-type.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Type conversions for disambiguation option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal-totemporalzoneddatetime step 5: + 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). + sec-temporal.zoneddatetime.from step 2: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + a. ... + b. Perform ? ToTemporalDisambiguation(_options_). + c. ... + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible", + (disambiguation) => Temporal.ZonedDateTime.from(datetime, { disambiguation }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr), +); + +const timeZone = new Temporal.TimeZone("UTC"); +const propertyBag = { timeZone, year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321 }; +TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible", + (disambiguation) => Temporal.ZonedDateTime.from(propertyBag, { disambiguation }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..c7479d3768ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321, timeZone: "UTC" }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.ZonedDateTime.from({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => Temporal.ZonedDateTime.from({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/length.js new file mode 100644 index 000000000000..022fd9ad6b09 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Temporal.ZonedDateTime.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/name.js new file mode 100644 index 000000000000..6b3e376156e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Temporal.ZonedDateTime.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/not-a-constructor.js new file mode 100644 index 000000000000..cd81e6dc6bb0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Temporal.ZonedDateTime.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.from), false, + "isConstructor(Temporal.ZonedDateTime.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-invalid-string.js new file mode 100644 index 000000000000..ebf52f1bc142 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-invalid-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: RangeError thrown when offset option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloffset step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_). + sec-temporal-totemporalzoneddatetime step 6: + 6. Let _offset_ be ? ToTemporalOffset(_options_, *"reject"*). + sec-temporal.zoneddatetime.from step 2: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + c. Perform ? ToTemporalOffset(_options_, *"reject"*). + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(datetime, { offset: "other string" })); + +const timeZone = new Temporal.TimeZone("UTC"); +const propertyBag = { timeZone, year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321 }; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { offset: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-undefined.js new file mode 100644 index 000000000000..ba6145b62924 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Fallback value for offset option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloffset step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_). + sec-temporal-totemporalzoneddatetime step 6: + 6. Let _offset_ be ? ToTemporalOffset(_options_, *"reject"*). + sec-temporal.zoneddatetime.from step 2: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + c. Perform ? ToTemporalOffset(_options_, *"reject"*). + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("-04:00"); +const propertyBag = { timeZone, offset: "+01:00", year: 2020, month: 2, day: 16, hour: 23, minute: 45 }; + +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { offset: undefined }), "default offset is reject"); +// See options-undefined.js for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-wrong-type.js new file mode 100644 index 000000000000..0dc0e00711c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/offset-wrong-type.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Type conversions for offset option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloffset step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_). + sec-temporal-totemporalzoneddatetime step 6: + 6. Let _offset_ be ? ToTemporalOffset(_options_, *"reject"*). + sec-temporal.zoneddatetime.from step 2: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + c. Perform ? ToTemporalOffset(_options_, *"reject"*). + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("offset", "reject", + (disambiguation) => Temporal.ZonedDateTime.from(datetime, { disambiguation }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr), +); + +const timeZone = new Temporal.TimeZone("UTC"); +const propertyBag = { timeZone, offset: "+00:00", year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321 }; +TemporalHelpers.checkStringOptionWrongType("offset", "reject", + (disambiguation) => Temporal.ZonedDateTime.from(propertyBag, { disambiguation }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/options-undefined.js new file mode 100644 index 000000000000..496345332fe2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/options-undefined.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +includes: [temporalHelpers.js] +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const overflowFields = { year: 2000, month: 13, day: 2, timeZone: "UTC" }; + +const overflowExplicit = Temporal.ZonedDateTime.from(overflowFields, undefined); +assert.sameValue(overflowExplicit.month, 12, "default overflow is constrain"); + +const overflowPropertyImplicit = Temporal.ZonedDateTime.from(overflowFields, {}); +assert.sameValue(overflowPropertyImplicit.month, 12, "default overflow is constrain"); + +const overflowImplicit = Temporal.ZonedDateTime.from(overflowFields); +assert.sameValue(overflowImplicit.month, 12, "default overflow is constrain"); + +const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); +const disambiguationEarlierFields = { timeZone, year: 2000, month: 10, day: 29, hour: 1, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }; +const disambiguationLaterFields = { timeZone, year: 2000, month: 4, day: 2, hour: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[ + [disambiguationEarlierFields, 972808496987654321n], + [disambiguationLaterFields, 954671696987654321n], +].forEach(([fields, expected]) => { + const explicit = Temporal.ZonedDateTime.from(fields, undefined); + assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible"); + + const propertyImplicit = Temporal.ZonedDateTime.from(fields, {}); + assert.sameValue(propertyImplicit.epochNanoseconds, expected, "default disambiguation is compatible"); + + const implicit = Temporal.ZonedDateTime.from(fields); + assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible"); +}); + +const offsetFields = { year: 2000, month: 5, day: 2, offset: "+23:59", timeZone: "UTC" }; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(offsetFields, undefined), "default offset is reject"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(offsetFields, {}), "default offset is reject"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(offsetFields), "default offset is reject"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js new file mode 100644 index 000000000000..aeb527b5fcbe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-totemporalzoneddatetime steps 2–3: + 2. If Type(_item_) is Object, then + ... + j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + 3. Else, + a. Perform ? ToTemporalOverflow(_options_). + sec-temporal.zoneddatetime.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + ... + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"), + { year: 2000, month: 5, day: 2, hour: 12, timeZone: "UTC" }, + "2001-09-09T01:46:40.987654321+00:00[UTC]", +]; + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.ZonedDateTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-undefined.js new file mode 100644 index 000000000000..98e2d256b39a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-undefined.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-totemporalzoneddatetime steps 2–3: + 2. If Type(_item_) is Object, then + ... + j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + 3. Else, + a. Perform ? ToTemporalOverflow(_options_). + sec-temporal.zoneddatetime.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + ... + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"), + "2001-09-09T01:46:40.987654321+00:00[UTC]", +]; +validValues.forEach((value) => { + const explicit = Temporal.ZonedDateTime.from(value, { overflow: undefined }); + assert.sameValue(explicit.epochNanoseconds, 1_000_000_000_987_654_321n, "overflow is ignored"); + const implicit = Temporal.ZonedDateTime.from(value, {}); + assert.sameValue(implicit.epochNanoseconds, 1_000_000_000_987_654_321n, "overflow is ignored"); +}); + +const propertyBag = { year: 2000, month: 15, day: 34, hour: 12, timeZone: "UTC" }; +const explicit = Temporal.ZonedDateTime.from(propertyBag, { overflow: undefined }); +assert.sameValue(explicit.epochNanoseconds, 978_264_000_000_000_000n, "default overflow is constrain"); + +// See options-undefined for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-wrong-type.js new file mode 100644 index 000000000000..1d677bdd060c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/overflow-wrong-type.js @@ -0,0 +1,67 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-totemporalzoneddatetime steps 2–3: + 2. If Type(_item_) is Object, then + ... + j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + 3. Else, + a. Perform ? ToTemporalOverflow(_options_). + sec-temporal.zoneddatetime.from steps 2–3: + 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Perform ? ToTemporalOverflow(_options_). + ... + d. Return ... + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"), + "2001-09-09T01:46:40.987654321+00:00[UTC]", +]; +validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => Temporal.ZonedDateTime.from(value, { overflow }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr), +)); + +// See TemporalHelpers.checkStringOptionWrongType(); this code path has +// different expectations for observable calls +const propertyBag = { year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, timeZone: "UTC" }; + +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: null }), "null"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: true }), "true"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: false }), "false"); +assert.throws(TypeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: Symbol() }), "symbol"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: 2n }), "bigint"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: {} }), "plain object"); + +// toString property is read once by Calendar.dateFromFields() in the builtin +// calendars, to get the option value for the date part, and then once again +// internally to get the option value for the time part. +const expected = [ + "get overflow.toString", + "call overflow.toString", + "get overflow.toString", + "call overflow.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); +const result = Temporal.ZonedDateTime.from(propertyBag, { overflow: observer }); +assert.sameValue(result.epochNanoseconds, 1_000_000_000_000_000_000n, "object with toString"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/prop-desc.js new file mode 100644 index 000000000000..a8924ed03057 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: The "from" property of Temporal.ZonedDateTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.from, + "function", + "`typeof ZonedDateTime.from` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..9f424c10d6e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/read-time-fields-before-datefromfields.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.zoneddatetime.from step 3: + 3. Return ? ToTemporalDateTime(_item_, _options_). + sec-temporal-totemporalzoneddatetime step 2.j: + j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321, timeZone: "UTC", calendar }); + +assert.sameValue(datetime.hour, 12, "hour value"); +assert.sameValue(datetime.minute, 34, "minute value"); +assert.sameValue(datetime.second, 56, "second value"); +assert.sameValue(datetime.millisecond, 987, "millisecond value"); +assert.sameValue(datetime.microsecond, 654, "microsecond value"); +assert.sameValue(datetime.nanosecond, 321, "nanosecond value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/subclassing-ignored.js new file mode 100644 index 000000000000..dc97a85850f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/subclassing-ignored.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.ZonedDateTime, + "from", + ["2000-01-01T00:00:00.00000001+00:00[UTC]"], + (result) => { + assert.sameValue(result.epochNanoseconds, 946684800_000_000_010n, "epochNanoseconds result"); + assert.sameValue(result.year, 2000, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 1, "day result"); + assert.sameValue(result.hour, 0, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 0, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 10, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..460b464bf204 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.zoneddatetime.from step 3: + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "2000-05-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +}, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-string-datetime.js new file mode 100644 index 000000000000..42dcec002b67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-string-datetime.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..7ef6fb7d3a0b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/timezone-string-multiple-offsets.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/year-zero.js new file mode 100644 index 000000000000..f58cc1c20cf4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/year-zero.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const str = "-0000000-01-01T00:02:00.000000000+00:00[UTC]"; + +assert.throws(RangeError, () => { Temporal.ZonedDateTime.from(str); }, "reject minus zero as extended year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-string-multiple-offsets.js new file mode 100644 index 000000000000..021fee71f81d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-string-multiple-offsets.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: ZonedDateTime strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = Temporal.ZonedDateTime.from(str); +assert.sameValue(result.timeZone.toString(), "+00:01:30.987654321", "Time zone determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-string.js new file mode 100644 index 000000000000..b3807e5a8e4d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-string.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Conversion of ISO date-time strings to Temporal.ZonedDateTime instances +features: [Temporal] +---*/ + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str), "bare date-time string is not a ZonedDateTime"); +str = "1970-01-01T00:00Z"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str), "date-time + Z is not a ZonedDateTime"); +str = "1970-01-01T00:00+01:00"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str), "date-time + offset is not a ZonedDateTime"); + +str = "1970-01-01T00:00[+01:00]"; +const result1 = Temporal.ZonedDateTime.from(str); +assert.sameValue(result1.epochNanoseconds, -3600_000_000_000n, "date-time + IANA annotation preserves wall time in the time zone"); +assert.sameValue(result1.timeZone.toString(), "+01:00", "IANA annotation is not ignored"); + +str = "1970-01-01T00:00Z[+01:00]"; +const result2 = Temporal.ZonedDateTime.from(str); +assert.sameValue(result2.epochNanoseconds, 0n, "date-time + Z + IANA annotation preserves exact time in the time zone"); +assert.sameValue(result2.timeZone.toString(), "+01:00", "IANA annotation is not ignored"); + +str = "1970-01-01T00:00+01:00[+01:00]"; +const result3 = Temporal.ZonedDateTime.from(str); +assert.sameValue(result3.epochNanoseconds, -3600_000_000_000n, "date-time + offset + IANA annotation ensures both exact and wall time match"); +assert.sameValue(result3.timeZone.toString(), "+01:00", "IANA annotation is not ignored"); + +str = "1970-01-01T00:00-04:15[+01:00]"; +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str, { offset: "reject" }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch (explicit reject option)"); +const result4 = Temporal.ZonedDateTime.from(str, { offset: "ignore" }); +assert.sameValue(result4.epochNanoseconds, -3600_000_000_000n, "date-time + wrong offset + IANA annotation preserves wall time in the time zone (offset: ignore option)"); +assert.sameValue(result4.timeZone.toString(), "+01:00", "IANA annotation is not ignored"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-sub-minute-offset.js new file mode 100644 index 000000000000..5f0f3591f7c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/from/zoneddatetime-sub-minute-offset.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Fuzzy matching behaviour with UTC offsets in ISO 8601 strings and offset option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +["use", "ignore", "prefer", "reject"].forEach((offset) => { + const result = Temporal.ZonedDateTime.from("1970-01-01T12:00-00:44:30.123456789[-00:44:30.123456789]", { offset }); + assert.sameValue(result.epochNanoseconds, 45870_123_456_789n, `accepts the exact offset string (offset=${offset})`); + assert.sameValue(result.offset, "-00:44:30.123456789", "offset property is correct"); +}); + +assert.throws(RangeError, () => Temporal.ZonedDateTime.from("1970-01-01T00:00-00:44:30[-00:44:30.123456789]", { offset: "reject" }), "offset=reject does not accept any other rounding than minutes"); + +const str = "1970-01-01T12:00-00:45[-00:44:30.123456789]"; + +["ignore", "prefer", "reject"].forEach((offset) => { + const result = Temporal.ZonedDateTime.from(str, { offset }); + assert.sameValue(result.epochNanoseconds, 45870_123_456_789n, `accepts the offset string rounded to minutes (offset=${offset})`); + assert.sameValue(result.offset, "-00:44:30.123456789", "offset property is still the full precision"); + TemporalHelpers.assertPlainDateTime(result.toPlainDateTime(), 1970, 1, "M01", 1, 12, 0, 0, 0, 0, 0, "wall time is preserved"); +}); + +const result = Temporal.ZonedDateTime.from(str, { offset: "use" }); +assert.sameValue(result.epochNanoseconds, 45900_000_000_000n, "prioritizes the offset string with HH:MM precision when offset=use"); +assert.sameValue(result.offset, "-00:44:30.123456789", "offset property is still the full precision"); +TemporalHelpers.assertPlainDateTime(result.toPlainDateTime(), 1970, 1, "M01", 1, 12, 0, 29, 876, 543, 211, "wall time is shifted by the difference between exact and rounded offset"); + +const properties = { year: 1970, month: 1, day: 1, hour: 12, offset: "-00:45", timeZone: "-00:44:30.123456789" }; + +["ignore", "prefer"].forEach((offset) => { + const result = Temporal.ZonedDateTime.from(properties, { offset }); + assert.sameValue(result.epochNanoseconds, 45870_123_456_789n, `no fuzzy matching is done on offset in property bag (offset=${offset})`); +}); + +const result2 = Temporal.ZonedDateTime.from(properties, { offset: "use" }); +assert.sameValue(result2.epochNanoseconds, 45900_000_000_000n, "no fuzzy matching is done on offset in property bag (offset=use)"); + +assert.throws(RangeError, () => Temporal.ZonedDateTime.from(properties, { offset: "reject" }), "no fuzzy matching is done on offset in property bag (offset=reject)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/length.js new file mode 100644 index 000000000000..0448b05da581 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: Temporal.ZonedDateTime.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/missing-arguments.js new file mode 100644 index 000000000000..2af086ba9cdf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/missing-arguments.js @@ -0,0 +1,13 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: TypeError thrown when constructor invoked with no argument +features: [Temporal] +---*/ + +assert.throws(TypeError, () => new Temporal.ZonedDateTime()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/name.js new file mode 100644 index 000000000000..ebace2d4bf10 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: Temporal.ZonedDateTime.name is "ZonedDateTime" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime, "name", { + value: "ZonedDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prop-desc.js new file mode 100644 index 000000000000..45193fefe027 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: The "ZonedDateTime" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime, + "function", + "`typeof ZonedDateTime` is `function`" +); + +verifyProperty(Temporal, "ZonedDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..742fdff898d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: Strings with fractional duration units are rounded with the correct rounding mode +features: [Temporal] +---*/ + +const epoch = new Temporal.ZonedDateTime(0n, "UTC"); + +assert.sameValue(epoch.add("PT1.03125H").epochNanoseconds, 3712_500_000_000n, + "positive fractional units rounded with correct rounding mode"); +assert.sameValue(epoch.add("-PT1.03125H").epochNanoseconds, -3712_500_000_000n, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..afe6adbd512c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/argument-string-negative-fractional-units.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: Strings with fractional duration units are treated with the correct sign +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + +const resultHours = instance.add("-PT24.567890123H"); +assert.sameValue(resultHours.epochNanoseconds, 999_911_555_595_557_201n, "negative fractional hours"); + +const resultMinutes = instance.add("-PT1440.567890123M"); +assert.sameValue(resultMinutes.epochNanoseconds, 999_913_565_926_592_621n, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/builtin.js new file mode 100644 index 000000000000..d792ba587da9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: > + Tests that Temporal.ZonedDateTime.prototype.add + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.add), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.add), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.add), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.add.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/length.js new file mode 100644 index 000000000000..1b0cc1422abf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: Temporal.ZonedDateTime.prototype.add.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.add, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/name.js new file mode 100644 index 000000000000..82bcdee831d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: Temporal.ZonedDateTime.prototype.add.name is "add". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.add, "name", { + value: "add", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/negative-epochnanoseconds.js new file mode 100644 index 000000000000..0e3fcffea635 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/negative-epochnanoseconds.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.add(new Temporal.Duration(0, 0, 0, 1)); +assert.sameValue(result.epochNanoseconds, -13763364_999_999_999n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..fe5906acd3f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.add({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/not-a-constructor.js new file mode 100644 index 000000000000..0f336277d701 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: > + Temporal.ZonedDateTime.prototype.add does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.add(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.add), false, + "isConstructor(Temporal.ZonedDateTime.prototype.add)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/options-undefined.js new file mode 100644 index 000000000000..88a737b6cd79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(949322096_987_654_321n, "UTC"); +const duration = { months: 1 }; + +const explicit = datetime.add(duration, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = datetime.add(duration); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js new file mode 100644 index 000000000000..3d7e0f5215d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-addzoneddatetime step 6: + 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.zoneddatetime.prototype.add step 7: + 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-undefined.js new file mode 100644 index 000000000000..ad68e0494bcf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-addzoneddatetime step 6: + 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.zoneddatetime.prototype.add step 7: + 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-1n, "UTC"); +const duration = new Temporal.Duration(0, 2); + +const explicit = datetime.add(duration, { overflow: undefined }); +assert.sameValue(explicit.epochNanoseconds, 5097599_999_999_999n, "default overflow is constrain"); +const implicit = datetime.add(duration, {}); +assert.sameValue(implicit.epochNanoseconds, 5097599_999_999_999n, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-wrong-type.js new file mode 100644 index 000000000000..16098a068cf3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-addzoneddatetime step 6: + 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.zoneddatetime.prototype.add step 7: + 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => datetime.add(duration, { overflow }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_086_400_987_654_321n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/prop-desc.js new file mode 100644 index 000000000000..bee44a3da10a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: The "add" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.add, + "function", + "`typeof ZonedDateTime.prototype.add` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "add", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/subclassing-ignored.js new file mode 100644 index 000000000000..5c465f840559 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/subclassing-ignored.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [10n, "UTC"], + "add", + [{ nanoseconds: 5 }], + (result) => { + assert.sameValue(result.epochNanoseconds, 15n, "epochNanoseconds result"); + assert.sameValue(result.year, 1970, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 1, "day result"); + assert.sameValue(result.hour, 0, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 0, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 15, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..a7cd5838127f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.add(duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..ec7bfb139e13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.add(duration), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..9bb0d9204e20 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.add(duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..1d9371cbf3d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/add/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.add +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.add(duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/calendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/calendar/prop-desc.js new file mode 100644 index 000000000000..7f5c0ebe59fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/calendar/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.calendar +description: The "calendar" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "calendar"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/balance-negative-time-units.js new file mode 100644 index 000000000000..6dffc3a68198 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/balance-negative-time-units.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.day +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.day step 6: + 6. Let _temporalDateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(86400_000_000_001n, tz); + +assert.sameValue(datetime.day, 1); +assert.sameValue(datetime.hour, 23); +assert.sameValue(datetime.minute, 59); +assert.sameValue(datetime.second, 59); +assert.sameValue(datetime.millisecond, 999); +assert.sameValue(datetime.microsecond, 999); +assert.sameValue(datetime.nanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/calendar-returns-infinity.js new file mode 100644 index 000000000000..27e55b8f7feb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.day +description: Getter throws if the calendar returns ±∞ from its day method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + day() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.ZonedDateTime(0n, "UTC", pos); +assert.throws(RangeError, () => instance1.day); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.ZonedDateTime(0n, "UTC", neg); +assert.throws(RangeError, () => instance2.day); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/prop-desc.js new file mode 100644 index 000000000000..25e0c619b853 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.day +description: The "day" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "day"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..75678d0bff90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.day +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.day); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..ff7f86da0478 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.day +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.day, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..ebece5aa4a89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.day +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.day); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..2defbea46993 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/day/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.day +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.day); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/prop-desc.js new file mode 100644 index 000000000000..92e867e1a2b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofweek +description: The "dayOfWeek" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "dayOfWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..4cdd3bf4de4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofweek +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.dayOfWeek); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..97ec820f92ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofweek +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.dayOfWeek, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..87d8afcdebbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofweek +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.dayOfWeek); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..976fca6ad2c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfWeek/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofweek +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.dayOfWeek); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/prop-desc.js new file mode 100644 index 000000000000..201b450be26a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofyear +description: The "dayOfYear" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "dayOfYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..237a4c999558 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.dayOfYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..06f08603a10e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.dayOfYear, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..87abd00b5064 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.dayOfYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..0f7c1f9cd216 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/dayOfYear/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.dayofyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.dayOfYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/prop-desc.js new file mode 100644 index 000000000000..e27f8fb13771 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinmonth +description: The "daysInMonth" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "daysInMonth"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..35b356c5c96f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinmonth +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.daysInMonth); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..dd4929295f38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinmonth +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.daysInMonth, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..6fee83ec38c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinmonth +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.daysInMonth); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..7de986707a38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInMonth/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinmonth +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.daysInMonth); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/prop-desc.js new file mode 100644 index 000000000000..7be2704108e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinweek +description: The "daysInWeek" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "daysInWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..d5ccd40fe5d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinweek +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.daysInWeek); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..e4ad8ba2eb73 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinweek +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.daysInWeek, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..65630e45a335 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinweek +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.daysInWeek); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..5a682f36868c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInWeek/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinweek +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.daysInWeek); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/prop-desc.js new file mode 100644 index 000000000000..ceb3bfebba97 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinyear +description: The "daysInYear" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "daysInYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..1f5b533e8e04 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.daysInYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..4ab86e8d98cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.daysInYear, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..2c5b8ca0caba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.daysInYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..05169acd9c6a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/daysInYear/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.daysinyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.daysInYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMicroseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMicroseconds/basic.js new file mode 100644 index 000000000000..99f218bdfc49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMicroseconds/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.epochmicroseconds +description: Basic tests for epochMicroseconds. +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.ZonedDateTime(217175010_123_456_789n, "UTC"); +assert.sameValue(afterEpoch.epochMicroseconds, 217175010_123_456n, "epochMicroseconds post epoch"); +assert.sameValue(typeof afterEpoch.epochMicroseconds, "bigint", "epochMicroseconds value is a bigint"); + +const beforeEpoch = new Temporal.ZonedDateTime(-217175010_876_543_211n, "UTC"); +assert.sameValue(beforeEpoch.epochMicroseconds, -217175010_876_543n, "epochMicroseconds pre epoch"); +assert.sameValue(typeof beforeEpoch.epochMicroseconds, "bigint", "epochMicroseconds value is a bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMicroseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMicroseconds/prop-desc.js new file mode 100644 index 000000000000..8d0f7fe5f0aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMicroseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.epochmicroseconds +description: The "epochMicroseconds" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "epochMicroseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMilliseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMilliseconds/basic.js new file mode 100644 index 000000000000..2340c6d65aff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMilliseconds/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.epochmilliseconds +description: Basic tests for epochMilliseconds. +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.ZonedDateTime(217175010_123_456_789n, "UTC"); +assert.sameValue(afterEpoch.epochMilliseconds, 217175010_123, "epochMilliseconds post epoch"); +assert.sameValue(typeof afterEpoch.epochMilliseconds, "number", "epochMilliseconds value is a number"); + +const beforeEpoch = new Temporal.ZonedDateTime(-217175010_876_543_211n, "UTC"); +assert.sameValue(beforeEpoch.epochMilliseconds, -217175010_876, "epochMilliseconds pre epoch"); +assert.sameValue(typeof beforeEpoch.epochMilliseconds, "number", "epochMilliseconds value is a number"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMilliseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMilliseconds/prop-desc.js new file mode 100644 index 000000000000..e6403cfc6627 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochMilliseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.epochmilliseconds +description: The "epochMilliseconds" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "epochMilliseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochNanoseconds/basic.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochNanoseconds/basic.js new file mode 100644 index 000000000000..f9ff2bd75c83 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochNanoseconds/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.epochnanoseconds +description: Basic tests for epochNanoseconds. +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.ZonedDateTime(217175010_123_456_789n, "UTC"); +assert.sameValue(afterEpoch.epochNanoseconds, 217175010_123_456_789n, "epochNanoseconds post epoch"); +assert.sameValue(typeof afterEpoch.epochNanoseconds, "bigint", "epochNanoseconds value is a bigint"); + +const beforeEpoch = new Temporal.ZonedDateTime(-217175010_876_543_211n, "UTC"); +assert.sameValue(beforeEpoch.epochNanoseconds, -217175010_876_543_211n, "epochNanoseconds pre epoch"); +assert.sameValue(typeof beforeEpoch.epochNanoseconds, "bigint", "epochNanoseconds value is a bigint"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochNanoseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochNanoseconds/prop-desc.js new file mode 100644 index 000000000000..f4ee614a3204 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochNanoseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.epochnanoseconds +description: The "epochNanoseconds" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "epochNanoseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochSeconds/basic.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochSeconds/basic.js new file mode 100644 index 000000000000..c08374d4d7e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochSeconds/basic.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.epochseconds +description: Basic tests for epochSeconds. +features: [BigInt, Temporal] +---*/ + +const afterEpoch = new Temporal.ZonedDateTime(217175010_123_456_789n, "UTC"); +assert.sameValue(afterEpoch.epochSeconds, 217175010, "epochSeconds post epoch"); +assert.sameValue(typeof afterEpoch.epochSeconds, "number", "epochSeconds value is a number"); + +const beforeEpoch = new Temporal.ZonedDateTime(-217175010_876_543_211n, "UTC"); +assert.sameValue(beforeEpoch.epochSeconds, -217175010, "epochSeconds pre epoch"); +assert.sameValue(typeof beforeEpoch.epochSeconds, "number", "epochSeconds value is a number"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochSeconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochSeconds/prop-desc.js new file mode 100644 index 000000000000..0f0199ec6084 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/epochSeconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.epochseconds +description: The "epochSeconds" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "epochSeconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-offset-not-agreeing-with-timezone.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-offset-not-agreeing-with-timezone.js new file mode 100644 index 000000000000..0d9711a22774 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-offset-not-agreeing-with-timezone.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Property bag with offset property is rejected if offset does not agree with time zone +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+01:00"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +const properties = { year: 2021, month: 10, day: 28, offset: "-07:00", timeZone }; +assert.throws(RangeError, () => instance.equals(properties), "offset property not matching time zone is rejected"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..6fea9902e843 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + assert.throws(RangeError, () => datetime.equals({ year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..606c33ae5ecd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + timeZone.getPossibleInstantsFor = function () { + return []; + }; + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.equals({ year: 2000, month: 5, day: 2, hour: 12, timeZone }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..ae2b3145ca3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + assert.throws(RangeError, () => datetime.equals({ year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..887b4265889e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/argument-propertybag-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + assert.throws(TypeError, () => datetime.equals({ year: 2000, month: 5, day: 2, hour: 12, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/builtin.js new file mode 100644 index 000000000000..c2dd73d26717 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: > + Tests that Temporal.ZonedDateTime.prototype.equals + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.equals), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.equals), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.equals), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.equals.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/calendar-fields-iterable.js new file mode 100644 index 000000000000..117014edda14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/calendar-fields-iterable.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +datetime.equals({ year: 2005, month: 6, day: 2, timeZone: "UTC", calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/calendar-temporal-object.js new file mode 100644 index 000000000000..8133b89bf0ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + datetime.equals({ year: 2005, month: 6, day: 2, timeZone: "UTC", calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..c49149c968b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321, timeZone: "UTC" }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.equals({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/length.js new file mode 100644 index 000000000000..08d69f536e9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Temporal.ZonedDateTime.prototype.equals.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.equals, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/name.js new file mode 100644 index 000000000000..b3a508cef60b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Temporal.ZonedDateTime.prototype.equals.name is "equals". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.equals, "name", { + value: "equals", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/not-a-constructor.js new file mode 100644 index 000000000000..07b660efc6c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: > + Temporal.ZonedDateTime.prototype.equals does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.equals(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.equals), false, + "isConstructor(Temporal.ZonedDateTime.prototype.equals)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/prop-desc.js new file mode 100644 index 000000000000..9d3b1b4c16e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: The "equals" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.equals, + "function", + "`typeof ZonedDateTime.prototype.equals` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "equals", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..602d5eb47fd6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/read-time-fields-before-datefromfields.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.zoneddatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.j: + j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); +const result = datetime.equals({ year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321, timeZone: "UTC", calendar }); + +assert(result, "time fields are not modified"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/sub-minute-offset.js new file mode 100644 index 000000000000..9d3549f4963c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/sub-minute-offset.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Fuzzy matching behaviour for UTC offset in ISO 8601 string +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+00:44:30.123456789"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +const result = instance.equals("1970-01-01T00:44:30.123456789+00:45[+00:44:30.123456789]"); +assert.sameValue(result, true, "UTC offset rounded to minutes is accepted"); + +assert.throws(RangeError, () => instance.equals("1970-01-01T00:44:30.123456789+00:44:30[+00:44:30.123456789]"), "no other rounding than minutes is accepted"); + +const properties = { offset: "+00:45", year: 1970, month: 1, day: 1, minute: 44, second: 30, millisecond: 123, microsecond: 456, nanosecond: 123, timeZone }; +assert.throws(RangeError, () => instance.equals(properties), "no fuzzy matching is done on offset in property bag"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..21a2e31c7f22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.zoneddatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// Not called on the instance's time zone + +const expected1 = []; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.equals({ year: 2005, month: 6, day: 2, timeZone: "UTC" }); +}, expected1); + +// Called on the argument's time zone + +const expected2 = [ + "2005-06-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + datetime.equals({ year: 2005, month: 6, day: 2, timeZone }); +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-string-datetime.js new file mode 100644 index 000000000000..ffece078a5a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-string-datetime.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let expectedTimeZone = "UTC"; +const instance1 = new Temporal.ZonedDateTime(0n, expectedTimeZone); + +let timeZone = "2021-02-19T17:30"; +assert.throws(RangeError, () => instance1.equals({ year: 1970, month: 1, day: 1, timeZone }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance1.equals({ year: 1970, month: 1, day: 1, timeZone: { timeZone } }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw. They should produce +// expectedTimeZone, so additionally the operation should return true, because +// the property bag will produce an instance that's equal to the receiver. + +timeZone = "2021-02-19T17:30Z"; +assert(instance1.equals({ year: 1970, month: 1, day: 1, timeZone }), "date-time + Z is UTC time zone"); +assert(instance1.equals({ year: 1970, month: 1, day: 1, timeZone: { timeZone } }), "date-time + Z is UTC time zone (string in property bag)"); + +expectedTimeZone = "-08:00"; +const instance2 = new Temporal.ZonedDateTime(0n, expectedTimeZone); +timeZone = "2021-02-19T17:30-08:00"; +assert(instance2.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone }), "date-time + offset is the offset time zone"); +assert(instance2.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone: { timeZone } }), "date-time + offset is the offset time zone (string in property bag)"); + +const instance3 = new Temporal.ZonedDateTime(0n, expectedTimeZone); +timeZone = "2021-02-19T17:30[-08:00]"; +assert(instance3.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone }), "date-time + IANA annotation is the IANA time zone"); +assert(instance3.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone: { timeZone } }), "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-02-19T17:30Z[-08:00]"; +assert(instance3.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone }), "date-time + Z + IANA annotation is the IANA time zone"); +assert(instance3.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone: { timeZone } }), "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-02-19T17:30-08:00[-08:00]"; +assert(instance3.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone }), "date-time + offset + IANA annotation is the IANA time zone"); +assert(instance3.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone: { timeZone } }), "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..19ddcc7f642d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/timezone-string-multiple-offsets.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const expectedTimeZone = "+01:45:30.987654321"; +const instance = new Temporal.ZonedDateTime(0n, expectedTimeZone); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +// These operations should produce expectedTimeZone, so the following should +// be equal due to the time zones being different on the receiver and +// the argument. + +const properties = { year: 1970, month: 1, day: 1, hour: 1, minute: 45, second: 30, millisecond: 987, microsecond: 654, nanosecond: 321 }; +assert(instance.equals({ ...properties, timeZone }), "time zone string should produce expected time zone"); +assert(instance.equals({ ...properties, timeZone: { timeZone } }), "time zone string should produce expected time zone"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/year-zero.js new file mode 100644 index 000000000000..ce266576a9ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/year-zero.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); +const str = "-0000000-01-01T00:02:00.000000000+00:00[UTC]"; + +assert.throws(RangeError, () => { instance.equals(str); }, "reject minus zero as extended year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/zoneddatetime-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/zoneddatetime-string-multiple-offsets.js new file mode 100644 index 000000000000..36781932fd45 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/zoneddatetime-string-multiple-offsets.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: ZonedDateTime strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+00:01:30.987654321"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = instance.equals(str); +assert.sameValue(result, false, "Time zone determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/zoneddatetime-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/zoneddatetime-string.js new file mode 100644 index 000000000000..f6f14b1d70ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/equals/zoneddatetime-string.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Conversion of ISO date-time strings to Temporal.ZonedDateTime instances +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+01:00"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.equals(str), "bare date-time string is not a ZonedDateTime"); +str = "1970-01-01T00:00Z"; +assert.throws(RangeError, () => instance.equals(str), "date-time + Z is not a ZonedDateTime"); +str = "1970-01-01T00:00+01:00"; +assert.throws(RangeError, () => instance.equals(str), "date-time + offset is not a ZonedDateTime"); + +str = "1970-01-01T00:00[+01:00]"; +const result1 = instance.equals(str); +assert.sameValue(result1, false, "date-time + IANA annotation preserves wall time in the time zone"); + +str = "1970-01-01T00:00Z[+01:00]"; +const result2 = instance.equals(str); +assert.sameValue(result2, true, "date-time + Z + IANA annotation preserves exact time in the time zone"); + +str = "1970-01-01T00:00+01:00[+01:00]"; +const result3 = instance.equals(str); +assert.sameValue(result3, false, "date-time + offset + IANA annotation ensures both exact and wall time match"); + +str = "1970-01-01T00:00-04:15[+01:00]"; +assert.throws(RangeError, () => instance.equals(str), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/balance-negative-time-units.js new file mode 100644 index 000000000000..4c71873b2586 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/balance-negative-time-units.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.getisofields step 7: + 7. Let _dateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// ZonedDateTime +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(1001n, tz); + +const fields = datetime.getISOFields(); + +assert.sameValue(fields.isoMicrosecond, 0); +assert.sameValue(fields.isoNanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/builtin.js new file mode 100644 index 000000000000..767937de9a27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: > + Tests that Temporal.ZonedDateTime.prototype.getISOFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.getISOFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.getISOFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.getISOFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.getISOFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-names.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-names.js new file mode 100644 index 000000000000..c2f0c81ef318 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-names.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: Correct field names on the object returned from getISOFields +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_086_400_987_654_321n, "UTC"); + +const result = datetime.getISOFields(); +assert.sameValue(result.isoYear, 2001, "isoYear result"); +assert.sameValue(result.isoMonth, 9, "isoMonth result"); +assert.sameValue(result.isoDay, 10, "isoDay result"); +assert.sameValue(result.isoHour, 1, "isoHour result"); +assert.sameValue(result.isoMinute, 46, "isoMinute result"); +assert.sameValue(result.isoSecond, 40, "isoSecond result"); +assert.sameValue(result.isoMillisecond, 987, "isoMillisecond result"); +assert.sameValue(result.isoMicrosecond, 654, "isoMicrosecond result"); +assert.sameValue(result.isoNanosecond, 321, "isoNanosecond result"); +assert.sameValue(result.offset, "+00:00", "offset result"); +assert.sameValue(result.calendar.id, "iso8601", "calendar result"); +assert.sameValue(result.timeZone.id, "UTC", "timeZone result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-prop-desc.js new file mode 100644 index 000000000000..8d31ba7c2a88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-prop-desc.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: Properties on the returned object have the correct descriptor +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoHour", + "isoMicrosecond", + "isoMillisecond", + "isoMinute", + "isoMonth", + "isoNanosecond", + "isoSecond", + "isoYear", + "offset", + "timeZone", +]; + +const datetime = new Temporal.ZonedDateTime(1_000_086_400_987_654_321n, "UTC"); +const result = datetime.getISOFields(); + +for (const property of expected) { + verifyProperty(result, property, { + writable: true, + enumerable: true, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-traversal-order.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-traversal-order.js new file mode 100644 index 000000000000..a760ebb6aea9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/field-traversal-order.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: Properties added in correct order to object returned from getISOFields +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "calendar", + "isoDay", + "isoHour", + "isoMicrosecond", + "isoMillisecond", + "isoMinute", + "isoMonth", + "isoNanosecond", + "isoSecond", + "isoYear", + "offset", + "timeZone", +]; + +const datetime = new Temporal.ZonedDateTime(1_000_086_400_987_654_321n, "UTC"); +const result = datetime.getISOFields(); + +assert.compareArray(Object.keys(result), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/length.js new file mode 100644 index 000000000000..3cdb4f5b415b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: Temporal.ZonedDateTime.prototype.getISOFields.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.getISOFields, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/name.js new file mode 100644 index 000000000000..854aedb80e0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: Temporal.ZonedDateTime.prototype.getISOFields.name is "getISOFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.getISOFields, "name", { + value: "getISOFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/negative-epochnanoseconds.js new file mode 100644 index 000000000000..9e2bca08f3f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/negative-epochnanoseconds.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [deepEqual.js] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const calendar = new Temporal.Calendar("iso8601"); +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, timeZone, calendar); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.getISOFields(); +assert.deepEqual(result, { + calendar, + isoDay: 24, + isoHour: 16, + isoMicrosecond: 0, + isoMillisecond: 0, + isoMinute: 50, + isoMonth: 7, + isoNanosecond: 1, + isoSecond: 35, + isoYear: 1969, + offset: "+00:00", + timeZone, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/not-a-constructor.js new file mode 100644 index 000000000000..a8420f48b337 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: > + Temporal.ZonedDateTime.prototype.getISOFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.getISOFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.getISOFields), false, + "isConstructor(Temporal.ZonedDateTime.prototype.getISOFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/offset.js new file mode 100644 index 000000000000..3e4b8fb791f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/offset.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: The offset property of returned object +features: [BigInt, Temporal] +---*/ + +function test(timeZoneIdentifier, expectedOffsetString, description) { + const timeZone = new Temporal.TimeZone(timeZoneIdentifier); + const datetime = new Temporal.ZonedDateTime(0n, timeZone); + const fields = datetime.getISOFields(); + assert.sameValue(fields.offset, expectedOffsetString, description); +} + +test("UTC", "+00:00", "offset of UTC is +00:00"); +test("+01:00", "+01:00", "positive offset"); +test("-05:00", "-05:00", "negative offset"); +test("+00:44:59.123456789", "+00:44:59.123456789", "sub-minute offset is not rounded"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/prop-desc.js new file mode 100644 index 000000000000..0799e88aa1a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: The "getISOFields" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.getISOFields, + "function", + "`typeof ZonedDateTime.prototype.getISOFields` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "getISOFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/shell.js index e69de29bb2d1..b36293881a43 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/shell.js @@ -0,0 +1,348 @@ +// GENERATED, DO NOT EDIT +// file: deepEqual.js +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Compare two values structurally +defines: [assert.deepEqual] +---*/ + +assert.deepEqual = function(actual, expected, message) { + var format = assert.deepEqual.format; + assert( + assert.deepEqual._compare(actual, expected), + `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}` + ); +}; + +assert.deepEqual.format = function(value, seen) { + switch (typeof value) { + case 'string': + return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`; + case 'number': + case 'boolean': + case 'symbol': + case 'bigint': + return value.toString(); + case 'undefined': + return 'undefined'; + case 'function': + return `[Function${value.name ? `: ${value.name}` : ''}]`; + case 'object': + if (value === null) return 'null'; + if (value instanceof Date) return `Date "${value.toISOString()}"`; + if (value instanceof RegExp) return value.toString(); + if (!seen) { + seen = { + counter: 0, + map: new Map() + }; + } + + let usage = seen.map.get(value); + if (usage) { + usage.used = true; + return `[Ref: #${usage.id}]`; + } + + usage = { id: ++seen.counter, used: false }; + seen.map.set(value, usage); + + if (typeof Set !== "undefined" && value instanceof Set) { + return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (typeof Map !== "undefined" && value instanceof Map) { + return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (Array.isArray ? Array.isArray(value) : value instanceof Array) { + return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`; + } + let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object'; + if (tag === 'Object' && Object.getPrototypeOf(value) === null) { + tag = '[Object: null prototype]'; + } + return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`; + default: + return typeof value; + } +}; + +assert.deepEqual._compare = (function () { + var EQUAL = 1; + var NOT_EQUAL = -1; + var UNKNOWN = 0; + + function deepEqual(a, b) { + return compareEquality(a, b) === EQUAL; + } + + function compareEquality(a, b, cache) { + return compareIf(a, b, isOptional, compareOptionality) + || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality) + || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache) + || NOT_EQUAL; + } + + function compareIf(a, b, test, compare, cache) { + return !test(a) + ? !test(b) ? UNKNOWN : NOT_EQUAL + : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache); + } + + function tryCompareStrictEquality(a, b) { + return a === b ? EQUAL : UNKNOWN; + } + + function tryCompareTypeOfEquality(a, b) { + return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN; + } + + function tryCompareToStringTagEquality(a, b) { + var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined; + var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined; + return aTag !== bTag ? NOT_EQUAL : UNKNOWN; + } + + function isOptional(value) { + return value === undefined + || value === null; + } + + function compareOptionality(a, b) { + return tryCompareStrictEquality(a, b) + || NOT_EQUAL; + } + + function isPrimitiveEquatable(value) { + switch (typeof value) { + case 'string': + case 'number': + case 'bigint': + case 'boolean': + case 'symbol': + return true; + default: + return isBoxed(value); + } + } + + function comparePrimitiveEquality(a, b) { + if (isBoxed(a)) a = a.valueOf(); + if (isBoxed(b)) b = b.valueOf(); + return tryCompareStrictEquality(a, b) + || tryCompareTypeOfEquality(a, b) + || compareIf(a, b, isNaNEquatable, compareNaNEquality) + || NOT_EQUAL; + } + + function isNaNEquatable(value) { + return typeof value === 'number'; + } + + function compareNaNEquality(a, b) { + return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL; + } + + function isObjectEquatable(value) { + return typeof value === 'object'; + } + + function compareObjectEquality(a, b, cache) { + if (!cache) cache = new Map(); + return getCache(cache, a, b) + || setCache(cache, a, b, EQUAL) // consider equal for now + || cacheComparison(a, b, tryCompareStrictEquality, cache) + || cacheComparison(a, b, tryCompareToStringTagEquality, cache) + || compareIf(a, b, isValueOfEquatable, compareValueOfEquality) + || compareIf(a, b, isToStringEquatable, compareToStringEquality) + || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache) + || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache) + || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || cacheComparison(a, b, fail, cache); + } + + function isBoxed(value) { + return value instanceof String + || value instanceof Number + || value instanceof Boolean + || typeof Symbol === 'function' && value instanceof Symbol + || typeof BigInt === 'function' && value instanceof BigInt; + } + + function isValueOfEquatable(value) { + return value instanceof Date; + } + + function compareValueOfEquality(a, b) { + return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isToStringEquatable(value) { + return value instanceof RegExp; + } + + function compareToStringEquality(a, b) { + return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isArrayLikeEquatable(value) { + return (Array.isArray ? Array.isArray(value) : value instanceof Array) + || (typeof Uint8Array === 'function' && value instanceof Uint8Array) + || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray) + || (typeof Uint16Array === 'function' && value instanceof Uint16Array) + || (typeof Uint32Array === 'function' && value instanceof Uint32Array) + || (typeof Int8Array === 'function' && value instanceof Int8Array) + || (typeof Int16Array === 'function' && value instanceof Int16Array) + || (typeof Int32Array === 'function' && value instanceof Int32Array) + || (typeof Float32Array === 'function' && value instanceof Float32Array) + || (typeof Float64Array === 'function' && value instanceof Float64Array) + || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array) + || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array); + } + + function compareArrayLikeEquality(a, b, cache) { + if (a.length !== b.length) return NOT_EQUAL; + for (var i = 0; i < a.length; i++) { + if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + return EQUAL; + } + + function isStructurallyEquatable(value) { + return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference + || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference + || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference + || typeof Map === 'function' && value instanceof Map // comparable via @@iterator + || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator + } + + function compareStructuralEquality(a, b, cache) { + var aKeys = []; + for (var key in a) aKeys.push(key); + + var bKeys = []; + for (var key in b) bKeys.push(key); + + if (aKeys.length !== bKeys.length) { + return NOT_EQUAL; + } + + aKeys.sort(); + bKeys.sort(); + + for (var i = 0; i < aKeys.length; i++) { + var aKey = aKeys[i]; + var bKey = bKeys[i]; + if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + + return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || EQUAL; + } + + function isIterableEquatable(value) { + return typeof Symbol === 'function' + && typeof value[Symbol.iterator] === 'function'; + } + + function compareIteratorEquality(a, b, cache) { + if (typeof Map === 'function' && a instanceof Map && b instanceof Map || + typeof Set === 'function' && a instanceof Set && b instanceof Set) { + if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size + } + + var ar, br; + while (true) { + ar = a.next(); + br = b.next(); + if (ar.done) { + if (br.done) return EQUAL; + if (b.return) b.return(); + return NOT_EQUAL; + } + if (br.done) { + if (a.return) a.return(); + return NOT_EQUAL; + } + if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) { + if (a.return) a.return(); + if (b.return) b.return(); + return NOT_EQUAL; + } + } + } + + function compareIterableEquality(a, b, cache) { + return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache); + } + + function cacheComparison(a, b, compare, cache) { + var result = compare(a, b, cache); + if (cache && (result === EQUAL || result === NOT_EQUAL)) { + setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result)); + } + return result; + } + + function fail() { + return NOT_EQUAL; + } + + function setCache(cache, left, right, result) { + var otherCache; + + otherCache = cache.get(left); + if (!otherCache) cache.set(left, otherCache = new Map()); + otherCache.set(right, result); + + otherCache = cache.get(right); + if (!otherCache) cache.set(right, otherCache = new Map()); + otherCache.set(left, result); + } + + function getCache(cache, left, right) { + var otherCache; + var result; + + otherCache = cache.get(left); + result = otherCache && otherCache.get(right); + if (result) return result; + + otherCache = cache.get(right); + result = otherCache && otherCache.get(left); + if (result) return result; + + return UNKNOWN; + } + + return deepEqual; +})(); + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..461e02a1f950 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.getISOFields()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..92bb2a2cc9d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.getISOFields(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..f98abf8cf62f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.getISOFields()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..1ed7f8abf050 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/getISOFields/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.getisofields +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.getISOFields()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/balance-negative-time-units.js new file mode 100644 index 000000000000..7a6f8956d9c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/balance-negative-time-units.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.hour +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–12: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.hour step 6: + 6. Let _temporalDateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3600_000_000_001n, tz); + +assert.sameValue(datetime.hour, 0); +assert.sameValue(datetime.minute, 59); +assert.sameValue(datetime.second, 59); +assert.sameValue(datetime.millisecond, 999); +assert.sameValue(datetime.microsecond, 999); +assert.sameValue(datetime.nanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/prop-desc.js new file mode 100644 index 000000000000..54c93a8024a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hour +description: The "hour" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "hour"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..590adf6e0d55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hour +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.hour); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..3f833a260be1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hour +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.hour, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..a7da68f84f06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hour +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.hour); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..e9c51c294fba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hour/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hour +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.hour); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/prop-desc.js new file mode 100644 index 000000000000..54527fd26446 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hoursinday +description: The "hoursInDay" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "hoursInDay"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..6ca2b97437fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hoursinday +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.hoursInDay); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..fc29166bb6a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hoursinday +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.hoursInDay, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..21166e4ad136 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hoursinday +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.hoursInDay); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..22334d2d2129 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hoursinday +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.hoursInDay); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..156a2285da6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hoursinday +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-get-temporal.zoneddatetime.prototype.hoursinday steps 13–14: + 13. Let _todayInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _today_, *"compatible"*). + 14. Let _tomorrowInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _tomorrow_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "2001-09-09T00:00:00", + "2001-09-10T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.hoursInDay; +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:00:00", + "2030-01-01T01:00:00", + "2030-01-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_893_457_800_000_000_000n, timeZone); + datetime.hoursInDay; +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/prop-desc.js new file mode 100644 index 000000000000..2753796c9e4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.inleapyear +description: The "inLeapYear" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "inLeapYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..08efca35e01f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.inleapyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.inLeapYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..9b74f4075ff8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.inleapyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.inLeapYear, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..0666a9cd335d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.inleapyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.inLeapYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..9d08b877e602 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/inLeapYear/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.inleapyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.inLeapYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/balance-negative-time-units.js new file mode 100644 index 000000000000..88917a99bef7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/balance-negative-time-units.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.microsecond +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–4: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.microsecond step 6: + 6. Let _temporalDateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(1001n, tz); + +assert.sameValue(datetime.microsecond, 0); +assert.sameValue(datetime.nanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/negative-epochnanoseconds.js new file mode 100644 index 000000000000..5da2cf20aaa3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/negative-epochnanoseconds.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.microsecond +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +assert.sameValue(datetime.microsecond, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/prop-desc.js new file mode 100644 index 000000000000..dee53d01626d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.microsecond +description: The "microsecond" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "microsecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..35983f45d6e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.microsecond +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.microsecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..8317411d0b92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.microsecond +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.microsecond, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..06402f77f11e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.microsecond +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.microsecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..6b2395b728df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/microsecond/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.microsecond +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.microsecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/balance-negative-time-units.js new file mode 100644 index 000000000000..aea08aea3880 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/balance-negative-time-units.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.millisecond +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–6: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.millisecond step 6: + 6. Let _temporalDateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(1_000_001n, tz); + +assert.sameValue(datetime.millisecond, 0); +assert.sameValue(datetime.microsecond, 999); +assert.sameValue(datetime.nanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/negative-epochnanoseconds.js new file mode 100644 index 000000000000..5060779a22da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/negative-epochnanoseconds.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.millisecond +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +assert.sameValue(datetime.millisecond, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/prop-desc.js new file mode 100644 index 000000000000..4f9c8e090da0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.millisecond +description: The "millisecond" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "millisecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..fbbb68669656 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.millisecond +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.millisecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..078accae4a8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.millisecond +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.millisecond, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..ed10f4cbb881 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.millisecond +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.millisecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..9f62512fd262 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/millisecond/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.millisecond +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.millisecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/balance-negative-time-units.js new file mode 100644 index 000000000000..b9489c78a199 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/balance-negative-time-units.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.minute +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–10: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.minute step 6: + 6. Let _temporalDateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(60_000_000_001n, tz); + +assert.sameValue(datetime.minute, 0); +assert.sameValue(datetime.second, 59); +assert.sameValue(datetime.millisecond, 999); +assert.sameValue(datetime.microsecond, 999); +assert.sameValue(datetime.nanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/prop-desc.js new file mode 100644 index 000000000000..b8022201ef94 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.minute +description: The "minute" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "minute"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..6ef401ea7b1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.minute +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.minute); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..98b2e101c4d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.minute +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.minute, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..3968a5b96ada --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.minute +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.minute); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..f87da7b61f17 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/minute/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.minute +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.minute); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/calendar-returns-infinity.js new file mode 100644 index 000000000000..754bfa1981a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.month +description: Getter throws if the calendar returns ±∞ from its month method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + month() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.ZonedDateTime(0n, "UTC", pos); +assert.throws(RangeError, () => instance1.month); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.ZonedDateTime(0n, "UTC", neg); +assert.throws(RangeError, () => instance2.month); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/prop-desc.js new file mode 100644 index 000000000000..8ff141766a99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.month +description: The "month" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "month"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..b4397fc19c73 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.month +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.month); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..c0226117f819 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.month +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.month, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..cc0809870e5b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.month +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.month); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..9edb94d6eba9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/month/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.month +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.month); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/prop-desc.js new file mode 100644 index 000000000000..cf155b4ed0be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthcode +description: The "monthCode" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "monthCode"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..fe0adb168bac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthcode +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.monthCode); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..daca04d4a1ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthcode +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.monthCode, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..f425e14c7326 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthcode +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.monthCode); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..a58a2129ee31 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthCode/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthcode +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.monthCode); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/prop-desc.js new file mode 100644 index 000000000000..6b87643f5bc5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthsinyear +description: The "monthsInYear" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "monthsInYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..6ac52849272c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthsinyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.monthsInYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..f71e835aaf93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthsinyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.monthsInYear, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..c160bb633f39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthsinyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.monthsInYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..3358788ac8cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/monthsInYear/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.monthsinyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.monthsInYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/negative-epochnanoseconds.js new file mode 100644 index 000000000000..d2fad9c258c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/negative-epochnanoseconds.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.nanosecond +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +assert.sameValue(datetime.nanosecond, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/prop-desc.js new file mode 100644 index 000000000000..d3346e59e9fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.nanosecond +description: The "nanosecond" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "nanosecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..db5e26271bbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.nanosecond +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.nanosecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..0ff7a261b0bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.nanosecond +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.nanosecond, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..8569b6a74b74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.nanosecond +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.nanosecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..ca04d2fa12e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/nanosecond/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.nanosecond +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.nanosecond); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/basic.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/basic.js new file mode 100644 index 000000000000..c960aaaf8d88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/basic.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offset +description: Basic tests for Temporal.ZonedDateTime.prototype.offset +features: [BigInt, Temporal] +---*/ + +function test(timeZoneIdentifier, expectedOffsetString, description) { + const timeZone = new Temporal.TimeZone(timeZoneIdentifier); + const datetime = new Temporal.ZonedDateTime(0n, timeZone); + assert.sameValue(datetime.offset, expectedOffsetString, description); +} + +test("UTC", "+00:00", "offset of UTC is +00:00"); +test("+01:00", "+01:00", "positive offset"); +test("-05:00", "-05:00", "negative offset"); +test("+00:44:59.123456789", "+00:44:59.123456789", "sub-minute offset is not rounded"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/prop-desc.js new file mode 100644 index 000000000000..5de842d677f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offset +description: The "offset" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "offset"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..36c98d497a49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offset +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.offset); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..fcdb5e2ead27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offset +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.offset, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..c3a9855366c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offset +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.offset); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..fb9790718e8a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offset/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offset +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.offset); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/prop-desc.js new file mode 100644 index 000000000000..a2c5b57248a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offsetnanoseconds +description: The "offsetNanoseconds" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "offsetNanoseconds"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..e95fdbfc51af --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offsetnanoseconds +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.offsetNanoseconds); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..8304578982eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offsetnanoseconds +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.offsetNanoseconds, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..e485b242b361 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offsetnanoseconds +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.offsetNanoseconds); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..4807071b4bd6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/offsetNanoseconds/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.offsetnanoseconds +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.offsetNanoseconds); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/prop-desc.js new file mode 100644 index 000000000000..d1a3ae3f9d3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-zoneddatetime-prototype +description: The "prototype" property of Temporal.ZonedDateTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.ZonedDateTime.prototype, "object"); +assert.notSameValue(Temporal.ZonedDateTime.prototype, null); + +verifyProperty(Temporal.ZonedDateTime, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/builtin.js new file mode 100644 index 000000000000..6050ed362759 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: > + Tests that Temporal.ZonedDateTime.prototype.round + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.round), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.round), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.round), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.round.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..cf7906055e5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.ZonedDateTime(7200_000_000_000n, timeZone, calendar); +instance.round({ smallestUnit: "day" }); +assert.sameValue(calendar.dateAddCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/dateadd-options.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/dateadd-options.js new file mode 100644 index 000000000000..135f8804f480 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/dateadd-options.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: dateAdd() is called with the correct three arguments +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +let actual = []; +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateAdd(...args) { + actual.push(this, ...args); + return super.dateAdd(...args); + } +} + +const calendar = new Calendar(); +const zdt = new Temporal.ZonedDateTime(0n, "UTC", calendar); +const result = zdt.round({ smallestUnit: "day" }); +assert.sameValue(result.epochNanoseconds, 0n, "Result"); + +assert.sameValue(actual.length, 4, "three arguments"); +assert.sameValue(actual[0], calendar, "this value"); +TemporalHelpers.assertPlainDate(actual[1], 1970, 1, "M01", 1, "date argument"); +TemporalHelpers.assertDuration(actual[2], 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "duration argument"); +assert.sameValue(actual[3], undefined, "options should be undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/div-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/div-zero.js new file mode 100644 index 000000000000..0b74cb7220f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/div-zero.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: RangeError thrown if the calculated day length is zero +features: [Temporal] +---*/ + +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateAdd(d) { + return d; + } +} + +const zdt = new Temporal.ZonedDateTime(0n, "UTC", new Calendar()); + +const units = ["day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]; +for (const smallestUnit of units) { + assert.throws(RangeError, () => zdt.round({ smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/length.js new file mode 100644 index 000000000000..f830dcaef75f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Temporal.ZonedDateTime.prototype.round.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.round, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/name.js new file mode 100644 index 000000000000..c86d40491715 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Temporal.ZonedDateTime.prototype.round.name is "round". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.round, "name", { + value: "round", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/negative-epochnanoseconds.js new file mode 100644 index 000000000000..62de56e9f047 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/negative-epochnanoseconds.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.round({ smallestUnit: "millisecond" }); +assert.sameValue(result.epochNanoseconds, -13849765_000_000_000n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/not-a-constructor.js new file mode 100644 index 000000000000..224c48f7f38f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: > + Temporal.ZonedDateTime.prototype.round does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.round(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.round), false, + "isConstructor(Temporal.ZonedDateTime.prototype.round)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/prop-desc.js new file mode 100644 index 000000000000..b341b4f32d01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: The "round" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.round, + "function", + "`typeof ZonedDateTime.prototype.round` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "round", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-nan.js new file mode 100644 index 000000000000..2efc9c6e4d35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-nan.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal-totemporaldatetimeroundingincrement step 5: + 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*). + sec-temporal.zoneddatetime.prototype.round step 8: + 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +assert.throws(RangeError, () => datetime.round({ smallestUnit: 'second', roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-non-integer.js new file mode 100644 index 000000000000..eec1ad82875e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_005n, "UTC"); +const result = datetime.round({ smallestUnit: "nanosecond", roundingIncrement: 2.5 }); +assert.sameValue(result.epochNanoseconds, 1_000_000_000_000_000_006n, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..713c5065fd8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-out-of-range.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_005n, "UTC"); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "nanoseconds", roundingIncrement: -Infinity })); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "nanoseconds", roundingIncrement: -1 })); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "nanoseconds", roundingIncrement: 0 })); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "nanoseconds", roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-undefined.js new file mode 100644 index 000000000000..ea531dd2517a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal-totemporaldatetimeroundingincrement step 5: + 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*). + sec-temporal.zoneddatetime.prototype.round step 8: + 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + +const explicit = datetime.round({ smallestUnit: 'second', roundingIncrement: undefined }); +assert.sameValue(explicit.epochNanoseconds, 1_000_000_001_000_000_000n, "default roundingIncrement is 1"); + +const implicit = datetime.round({ smallestUnit: 'second' }); +assert.sameValue(implicit.epochNanoseconds, 1_000_000_001_000_000_000n, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..15d56ea82444 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingincrement-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal-totemporaldatetimeroundingincrement step 5: + 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*). + sec-temporal.zoneddatetime.prototype.round step 8: + 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => datetime.round({ smallestUnit: 'second', roundingIncrement }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_001_000_000_000n, descr), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_000_000_000n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-invalid-string.js new file mode 100644 index 000000000000..28c723b4186a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => datetime.round({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-undefined.js new file mode 100644 index 000000000000..29c894c2d8d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Fallback value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); + +const explicit1 = datetime.round({ smallestUnit: "microsecond", roundingMode: undefined }); +assert.sameValue(explicit1.epochNanoseconds, 1_000_000_000_123_988_000n, "default roundingMode is halfExpand"); +const implicit1 = datetime.round({ smallestUnit: "microsecond" }); +assert.sameValue(implicit1.epochNanoseconds, 1_000_000_000_123_988_000n, "default roundingMode is halfExpand"); + +const explicit2 = datetime.round({ smallestUnit: "millisecond", roundingMode: undefined }); +assert.sameValue(explicit2.epochNanoseconds, 1_000_000_000_124_000_000n, "default roundingMode is halfExpand"); +const implicit2 = datetime.round({ smallestUnit: "millisecond" }); +assert.sameValue(implicit2.epochNanoseconds, 1_000_000_000_124_000_000n, "default roundingMode is halfExpand"); + +const explicit3 = datetime.round({ smallestUnit: "second", roundingMode: undefined }); +assert.sameValue(explicit3.epochNanoseconds, 1_000_000_000_000_000_000n, "default roundingMode is halfExpand"); +const implicit3 = datetime.round({ smallestUnit: "second" }); +assert.sameValue(implicit3.epochNanoseconds, 1_000_000_000_000_000_000n, "default roundingMode is halfExpand"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-wrong-type.js new file mode 100644 index 000000000000..d33960097a6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand", + (roundingMode) => datetime.round({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_123_988_000n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-disallowed-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-disallowed-units.js new file mode 100644 index 000000000000..e394beb73e05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-disallowed-units.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Specifically disallowed units for the smallestUnit option +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const invalidUnits = [ + "era", + "eras", + "year", + "month", + "week", + "years", + "months", + "weeks", +]; +invalidUnits.forEach((smallestUnit) => { + assert.throws( + RangeError, + () => instance.round({ smallestUnit }), + `{ smallestUnit: "${smallestUnit}" } should not be allowed as an argument to round` + ); + assert.throws( + RangeError, + () => instance.round(smallestUnit), + `"${smallestUnit}" should not be allowed as an argument to round` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-invalid-string.js new file mode 100644 index 000000000000..70768323ebcb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-invalid-string.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); +assert.throws(RangeError, () => datetime.round({ smallestUnit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..0008b7bc938a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-plurals-accepted.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const validUnits = [ + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => datetime.round({ smallestUnit }), validUnits); +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => datetime.round(smallestUnit), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-string-shorthand.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-string-shorthand.js new file mode 100644 index 000000000000..55d3ad75e194 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-string-shorthand.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: String as first argument is equivalent to options bag with smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const validUnits = [ + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +validUnits.forEach((smallestUnit) => { + const full = instance.round({ smallestUnit }); + const shorthand = instance.round(smallestUnit); + TemporalHelpers.assertZonedDateTimesEqual(shorthand, full, `"${smallestUnit}" as first argument to round is equivalent to options bag`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-wrong-type.js new file mode 100644 index 000000000000..b3369837180f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => datetime.round({ smallestUnit }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_123_988_000n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/subclassing-ignored.js new file mode 100644 index 000000000000..3075e85688a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/subclassing-ignored.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatime.prototype.round +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [10n, "UTC"], + "round", + [{ smallestUnit: 'second', roundingMode: 'ceil' }], + (result) => { + assert.sameValue(result.epochNanoseconds, 1_000_000_000n, "epochNanoseconds result"); + assert.sameValue(result.year, 1970, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 1, "day result"); + assert.sameValue(result.hour, 0, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 1, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 0, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..838e64480443 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.round({ smallestUnit: "second" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..70bb41478a41 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.round({ smallestUnit: "second" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..afec07b04507 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.round({ smallestUnit: "second" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..3fdc52c77023 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.round({ smallestUnit: "second" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..c9fb73495354 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.zoneddatetime.prototype.round steps 14, 16, and 20: + 14. Let _instantStart_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _dtStart_, *"compatible"*). + 16. Let _endNs_ be ? AddZonedDateTime(_startNs_, _timeZone_, _zonedDateTime_.[[Calendar]], 0, 0, 0, 1, 0, 0, 0, 0, 0, 0). + 20. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_roundResult_.[[Year]], [...], _roundResult_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, *"compatible"*, *"prefer"*). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "2001-09-09T00:00:00", // called once on midnight of the input datetime + "2001-09-10T00:00:00", // called once on the previous value plus one calendar day + "2001-09-09T02:00:00", // called once on the rounding result +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.round({ smallestUnit: 'hour' }); +}, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/balance-negative-time-units.js new file mode 100644 index 000000000000..964d4366ea54 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/balance-negative-time-units.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.second +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–8: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.second step 6: + 6. Let _temporalDateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(1_000_000_001n, tz); + +assert.sameValue(datetime.second, 0); +assert.sameValue(datetime.millisecond, 999); +assert.sameValue(datetime.microsecond, 999); +assert.sameValue(datetime.nanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/prop-desc.js new file mode 100644 index 000000000000..4563074e14e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.second +description: The "second" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "second"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..50d2fccc9c78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.second +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.second); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..080cc3230437 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.second +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.second, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..2f66749c74d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.second +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.second); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..84403329fbfd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/second/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.second +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.second); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/argument-propertybag-offset-not-agreeing-with-timezone.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/argument-propertybag-offset-not-agreeing-with-timezone.js new file mode 100644 index 000000000000..154ebf64fe24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/argument-propertybag-offset-not-agreeing-with-timezone.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Property bag with offset property is rejected if offset does not agree with time zone +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+01:00"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +const properties = { year: 2021, month: 10, day: 28, offset: "-07:00", timeZone }; +assert.throws(RangeError, () => instance.since(properties), "offset property not matching time zone is rejected"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..b64c05d72cd6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const properties = { year: 2004, month: 11, day: 9, hour: 11, minute: 33, second: 20, timeZone }; + timeZone.getPossibleInstantsFor = function () { + return []; + }; + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.since(properties, { largestUnit: "days" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/balance-negative-time-units.js new file mode 100644 index 000000000000..e74f6397147f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/balance-negative-time-units.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-differenceisodatetime step 2: + 2. Let _timeDifference_ be ? DifferenceTime(_h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_). + sec-temporal-differencezoneddatetime step 7: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + sec-temporal.zoneddatetime.prototype.since step 16: + 16. Let _difference_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _largestUnit_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const datetime = new Temporal.ZonedDateTime(830998861_001_001_001n, timeZone); +const options = { largestUnit: "days" }; + +const result1 = datetime.since(new Temporal.ZonedDateTime(830995200_000_000_002n, timeZone), options); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = datetime.since(new Temporal.ZonedDateTime(830995200_000_002_000n, timeZone), options); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = datetime.since(new Temporal.ZonedDateTime(830995200_002_000_000n, timeZone), options); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = datetime.since(new Temporal.ZonedDateTime(830995202_000_000_000n, timeZone), options); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = datetime.since(new Temporal.ZonedDateTime(830995320_000_000_000n, timeZone), options); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = datetime.since(new Temporal.ZonedDateTime(831002400_000_000_000n, timeZone), options); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/builtin.js new file mode 100644 index 000000000000..277db970b9d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: > + Tests that Temporal.ZonedDateTime.prototype.since + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.since), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.since), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.since), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.since.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..bed54cef1b90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,71 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const earlier = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +// Basic difference with largestUnit larger than days. +// The calls come from these paths: +// ZonedDateTime.since() -> DifferenceZonedDateTime -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() + +const later1 = new Temporal.ZonedDateTime(1_213_200_000_000_000n, timeZone, calendar); +later1.since(earlier, { largestUnit: "weeks" }); +assert.sameValue(calendar.dateAddCallCount, 2, "basic difference with largestUnit >days"); + +// Basic difference with largestUnit equal to days, to cover the second path in +// AddZonedDateTime. +// The calls come from these paths: +// ZonedDateTime.since() -> DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +calendar.dateAddCallCount = 0; + +later1.since(earlier, { largestUnit: "days" }); +assert.sameValue(calendar.dateAddCallCount, 2, "basic difference with largestUnit days"); + +// Difference with rounding, with smallestUnit a calendar unit. +// The calls come from these paths: +// ZonedDateTime.since() -> +// DifferenceZonedDateTime -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// MoveRelativeDate -> calendar.dateAdd() + +calendar.dateAddCallCount = 0; + +later1.since(earlier, { smallestUnit: "weeks" }); +assert.sameValue(calendar.dateAddCallCount, 5, "rounding difference with calendar smallestUnit"); + +// Difference with rounding, with smallestUnit a non-calendar unit, and having +// the resulting time difference be longer than a calendar day, covering the +// paths that go through AdjustRoundedDurationDays. (The path through +// AdjustRoundedDurationDays -> AddDuration that's covered in the corresponding +// test in until() only happens in one direction.) +// The calls come from these paths: +// ZonedDateTime.since() -> +// DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (3x) +// AdjustRoundedDurationDays -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (3x) + +calendar.dateAddCallCount = 0; + +const later2 = new Temporal.ZonedDateTime(86_399_999_999_999n, timeZone, calendar); +later2.since(earlier, { largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil" }); +assert.sameValue(calendar.dateAddCallCount, 6, "rounding difference with non-calendar smallestUnit and time difference longer than a calendar day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-copy-of-options.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-copy-of-options.js new file mode 100644 index 000000000000..98338070a87a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-copy-of-options.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: The dateUntil() method on the calendar is called with a copy of the options bag +features: [Temporal] +---*/ + +const originalOptions = { + largestUnit: "year", + shouldBeCopied: {}, +}; +let called = false; + +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(d1, d2, options) { + called = true; + assert.notSameValue(options, originalOptions, "options bag should be a copy"); + assert.sameValue(options.shouldBeCopied, originalOptions.shouldBeCopied, "options bag should be a shallow copy"); + return new Temporal.Duration(-1); + } +} +const calendar = new Calendar(); +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +// exactly one year later; avoids NanosecondsToDays path +const later = new Temporal.ZonedDateTime(1_031_536_000_000_000_000n, "UTC", calendar); +later.since(earlier, originalOptions); +assert(called, "calendar.dateUntil must be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..e04bdd864e4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,117 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.zoneddatetime.prototype.since steps 14–18: + 14. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + c. Return ... + 15. ... + 16. Let _difference_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _largestUnit_). + 17. Let _roundResult_ be ? RoundDuration(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _difference_.[[Hours]], _difference_.[[Minutes]], _difference_.[[Seconds]], _difference_.[[Milliseconds]], _difference_.[[Microseconds]], _difference_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_). + 18. Let _result_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_). + sec-temporal-differencezoneddatetime steps 7 and 11: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + 11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_). + sec-temporal-roundduration steps 5.d and 8.n–p: + 5. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + ... + 8. If _unit_ is *"year"*, then + ... + n. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). + o. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). + p. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_) + sec-temporal-adjustroundeddurationdays steps 1 and 9: + 1. If _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot; or _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*; or _unit_ is *"nanosecond"* and _increment_ is 1, then + a. Return ... + ... + 9. Let _adjustedDateDuration_ be ? AddDuration(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0, 0, 0, 0, _direction_, 0, 0, 0, 0, 0, 0, _relativeTo_). + sec-temporal-addduration step 7.a–g: + a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot. + ... + f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + g. Else, + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-nanosecondstodays step 11: + 11. 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*). + sec-temporal-differenceisodatetime steps 9–11: + 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). + 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); + const later = new Temporal.ZonedDateTime(1_086_403_661_988_655_322n, "UTC", calendar); + later.since(earlier, { largestUnit }); + }, + { + years: ["year", "day"], + months: ["month", "day"], + weeks: ["week", "day"], + days: ["day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +// Additionally check the path that goes through AdjustRoundedDurationDays + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.ZonedDateTime(0n, "UTC", calendar); + const later = new Temporal.ZonedDateTime(86_399_999_999_999n, "UTC", calendar); + later.since(earlier, { largestUnit, roundingIncrement: 2, roundingMode: 'ceil' }); + }, + { + years: ["year", "day", "day", "day"], + months: ["month", "day", "day", "day"], + weeks: ["week", "day", "day", "day"], + days: ["day", "day", "day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +// Also check the path that goes through RoundDuration when smallestUnit is +// given + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, smallestUnit) => { + const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); + const later = new Temporal.ZonedDateTime(1_086_403_661_988_655_322n, "UTC", calendar); + later.since(earlier, { smallestUnit }); + }, + { + years: ["year", "day", "day", "year"], + months: ["month", "day", "day"], + weeks: ["week", "day", "day"], + days: ["day", "day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-fields-iterable.js new file mode 100644 index 000000000000..41b1c7646a8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-fields-iterable.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +datetime.since({ year: 2005, month: 6, day: 2, timeZone: "UTC", calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-temporal-object.js new file mode 100644 index 000000000000..15f95945dbec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", temporalObject); + datetime.since({ year: 2005, month: 6, day: 2, timeZone: "UTC", calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..7e6656072ad6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.since +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321, timeZone: "UTC" }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.since({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.since({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-invalid-string.js new file mode 100644 index 000000000000..2c91b22a9e75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +const values = ["era", "eraYear", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..ebe839f87aec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_086_403_661_988_655_322n, "UTC"); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => later.since(earlier, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..228da9d39353 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => later.since(earlier, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-undefined.js new file mode 100644 index 000000000000..68919acea1ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); + +const explicit = later.since(earlier, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default largestUnit is hour"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default largestUnit is hour"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-wrong-type.js new file mode 100644 index 000000000000..ae3d78aaf642 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "year", + (largestUnit) => later.since(earlier, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit.js new file mode 100644 index 000000000000..865d4728d546 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Specify behavior of ZonedDateTime.since when largest specified unit is specified +includes: [temporalHelpers.js] +features: [Temporal, BigInt] +---*/ +const thePast = new Temporal.ZonedDateTime(1234567890123456789n, '-08:00'); +const theFuture = new Temporal.ZonedDateTime(2345678901234567890n, '-08:00'); +TemporalHelpers.assertDuration(theFuture.since(thePast), 0, 0, 0, 0, 308641, 56, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit unspecified)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'years' }), 35, 2, 0, 15, 1, 56, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit is years)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'months' }), 0, 422, 0, 15, 1, 56, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit is months)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'weeks' }), 0, 0, 1837, 1, 1, 56, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit is weeks)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'days' }), 0, 0, 0, 12860, 1, 56, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit is days)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'hours' }), 0, 0, 0, 0, 308641, 56, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit is hours)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'minutes' }), 0, 0, 0, 0, 0, 18518516, 51, 111, 111, 101, 'does not include higher units than necessary (largest unit is minutes)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'seconds' }), 0, 0, 0, 0, 0, 0, 1111111011, 111, 111, 101, 'does not include higher units than necessary (largest unit is seconds)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'milliseconds' }), 0, 0, 0, 0, 0, 0, 0, 1111111011111, 111, 101, 'does not include higher units than necessary (largest unit is milliseconds)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'microseconds' }), 0, 0, 0, 0, 0, 0, 0, 0, 1111111011111111, 101, 'does not include higher units than necessary (largest unit is microseconds)'); +TemporalHelpers.assertDuration(theFuture.since(thePast, { largestUnit: 'nanoseconds' }), 0, 0, 0, 0, 0, 0, 0, 0, 0, 1111111011111111000, 'does not include higher units than necessary (largest unit is nanoseconds)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/length.js new file mode 100644 index 000000000000..7a61f62a4796 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Temporal.ZonedDateTime.prototype.since.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.since, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/name.js new file mode 100644 index 000000000000..097b7317b874 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Temporal.ZonedDateTime.prototype.since.name is "since". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.since, "name", { + value: "since", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/negative-epochnanoseconds.js new file mode 100644 index 000000000000..9fb9b62b72de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.since(new Temporal.ZonedDateTime(0n, "UTC"), { largestUnit: "month" }); +TemporalHelpers.assertDuration(result, 0, -5, 0, -7, -7, -9, -24, -999, -999, -999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/not-a-constructor.js new file mode 100644 index 000000000000..3b1688f792b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: > + Temporal.ZonedDateTime.prototype.since does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.since(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.since), false, + "isConstructor(Temporal.ZonedDateTime.prototype.since)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/options-undefined.js new file mode 100644 index 000000000000..62236069592c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/options-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(957270896_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(959949296_987_654_322n, "UTC"); + +const explicit = later.since(earlier, undefined); +assert.sameValue(explicit.years, 0, "default largest unit is hours"); +assert.sameValue(explicit.months, 0, "default largest unit is hours"); +assert.sameValue(explicit.weeks, 0, "default largest unit is hours"); +assert.sameValue(explicit.days, 0, "default largest unit is hours"); +assert.sameValue(explicit.hours, 744, "default largest unit is hours"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = later.since(earlier); +assert.sameValue(implicit.years, 0, "default largest unit is hours"); +assert.sameValue(implicit.months, 0, "default largest unit is hours"); +assert.sameValue(implicit.weeks, 0, "default largest unit is hours"); +assert.sameValue(implicit.days, 0, "default largest unit is hours"); +assert.sameValue(implicit.hours, 744, "default largest unit is hours"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/prop-desc.js new file mode 100644 index 000000000000..2ad9fd98867e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: The "since" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.since, + "function", + "`typeof ZonedDateTime.prototype.since` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "since", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..1666abdeb5de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/read-time-fields-before-datefromfields.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.zoneddatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.j: + j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const duration = datetime.since({ year: 2001, month: 9, day: 9, timeZone: "UTC", calendar }); + +TemporalHelpers.assertDuration(duration, 0, 0, 0, 0, 1, 46, 40, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-nan.js new file mode 100644 index 000000000000..3db1caac717a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.zoneddatetime.prototype.since step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC"); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-non-integer.js new file mode 100644 index 000000000000..5de1ecc90109 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_000_000_000_000_005n, "UTC"); +const result = later.since(earlier, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..7afb3ebd1ebc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_000_000_000_000_005n, "UTC"); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -1 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 0 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-undefined.js new file mode 100644 index 000000000000..e3330c1ee9d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.zoneddatetime.prototype.since step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC"); + +const explicit = later.since(earlier, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..8c9051961b35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.zoneddatetime.prototype.since step 13: + 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC"); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => later.since(earlier, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-invalid-string.js new file mode 100644 index 000000000000..a159ae3c73f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC"); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-undefined.js new file mode 100644 index 000000000000..c2dcb1606264 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC"); + +const explicit1 = later.since(earlier, { smallestUnit: "microsecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, "default roundingMode is trunc"); +const implicit1 = later.since(earlier, { smallestUnit: "microsecond" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, "default roundingMode is trunc"); + +const explicit2 = later.since(earlier, { smallestUnit: "millisecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 25, 1, 1, 123, 0, 0, "default roundingMode is trunc"); +const implicit2 = later.since(earlier, { smallestUnit: "millisecond" }); +TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 25, 1, 1, 123, 0, 0, "default roundingMode is trunc"); + +const explicit3 = later.since(earlier, { smallestUnit: "second", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 25, 1, 1, 0, 0, 0, "default roundingMode is trunc"); +const implicit3 = later.since(earlier, { smallestUnit: "second" }); +TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 25, 1, 1, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-wrong-type.js new file mode 100644 index 000000000000..4626f91f65ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-invalid-string.js new file mode 100644 index 000000000000..c4e1324bc45b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +const values = ["era", "eraYear", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..9c8cffceef2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_086_403_661_988_655_322n, "UTC"); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => later.since(earlier, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-undefined.js new file mode 100644 index 000000000000..936736ad3af5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); + +const explicit = later.since(earlier, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-wrong-type.js new file mode 100644 index 000000000000..8ca8f08c6415 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => later.since(earlier, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/sub-minute-offset.js new file mode 100644 index 000000000000..b8cbb0361e05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/sub-minute-offset.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Fuzzy matching behaviour for UTC offset in ISO 8601 string +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+00:44:30.123456789"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +const result = instance.since("1970-01-01T00:44:30.123456789+00:45[+00:44:30.123456789]"); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "UTC offset rounded to minutes is accepted"); + +assert.throws(RangeError, () => instance.since("1970-01-01T00:44:30.123456789+00:44:30[+00:44:30.123456789]"), "no other rounding than minutes is accepted"); + +const properties = { offset: "+00:45", year: 1970, month: 1, day: 1, minute: 44, second: 30, millisecond: 123, microsecond: 456, nanosecond: 123, timeZone }; +assert.throws(RangeError, () => instance.since(properties), "no fuzzy matching is done on offset in property bag"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..6646bdde2a57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const other = new Temporal.ZonedDateTime(1_100_000_000_123_456_789n, timeZone); + assert.throws(RangeError, () => datetime.since(other, { largestUnit: "days" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..7a5b8175b049 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const other = new Temporal.ZonedDateTime(1_100_000_000_123_456_789n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.since(other, { largestUnit: "days" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..aae11842933c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const other = new Temporal.ZonedDateTime(1_100_000_000_123_456_789n, timeZone); + assert.throws(RangeError, () => datetime.since(other, { largestUnit: "days" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..c822a90b88d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const other = new Temporal.ZonedDateTime(1_100_000_000_123_456_789n, timeZone); + assert.throws(TypeError, () => datetime.since(other, { largestUnit: "days" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..27d98461ff02 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.zoneddatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// Not called on the instance's time zone + +const expected1 = []; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.since({ year: 2005, month: 6, day: 2, timeZone: "UTC" }); +}, expected1); + +// Called on the argument's time zone + +const expected2 = [ + "2005-06-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + datetime.since({ year: 2005, month: 6, day: 2, timeZone }); +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-string-datetime.js new file mode 100644 index 000000000000..e75f0cb18402 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-string-datetime.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let expectedTimeZone = "UTC"; +const instance1 = new Temporal.ZonedDateTime(0n, expectedTimeZone); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance1.since({ year: 2020, month: 5, day: 2, timeZone }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance1.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw. They should produce +// expectedTimeZone, so additionally the operation will not throw due to the +// time zones being different on the receiver and the argument. + +timeZone = "2021-08-19T17:30Z"; +instance1.since({ year: 2020, month: 5, day: 2, timeZone }); +instance1.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +expectedTimeZone = "-07:00"; +const instance2 = new Temporal.ZonedDateTime(0n, expectedTimeZone); +timeZone = "2021-08-19T17:30-07:00"; +instance2.since({ year: 2020, month: 5, day: 2, timeZone }); +instance2.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +expectedTimeZone = "UTC"; +const instance3 = new Temporal.ZonedDateTime(0n, expectedTimeZone); +timeZone = "2021-08-19T17:30[UTC]"; +instance3.since({ year: 2020, month: 5, day: 2, timeZone }); +instance3.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +timeZone = "2021-08-19T17:30Z[UTC]"; +instance3.since({ year: 2020, month: 5, day: 2, timeZone }); +instance3.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +instance3.since({ year: 2020, month: 5, day: 2, timeZone }); +instance3.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..5d512a0b1ca2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/timezone-string-multiple-offsets.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const expectedTimeZone = "+01:45:30.987654321"; +const instance = new Temporal.ZonedDateTime(0n, expectedTimeZone); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +// These operations should produce expectedTimeZone, so the following operations +// should not throw due to the time zones being different on the receiver and +// the argument. + +instance.since({ year: 2020, month: 5, day: 2, timeZone }); +instance.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/year-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/year-zero.js new file mode 100644 index 000000000000..e1f97a10bc3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/year-zero.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); +const str = "-0000000-01-01T00:02:00.000000000+00:00[UTC]"; + +assert.throws(RangeError, () => { instance.since(str); }, "reject minus zero as extended year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/zoneddatetime-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/zoneddatetime-string-multiple-offsets.js new file mode 100644 index 000000000000..fabaa04dcf96 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/zoneddatetime-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: ZonedDateTime strings with UTC offset fractional part are not confused with time fractional part +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+00:01:30.987654321"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = instance.since(str); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, -29, -12, -345, -679, "Time zone determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/zoneddatetime-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/zoneddatetime-string.js new file mode 100644 index 000000000000..47eaf94d66b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/since/zoneddatetime-string.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Conversion of ISO date-time strings to Temporal.ZonedDateTime instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.since(str), "bare date-time string is not a ZonedDateTime"); +str = "1970-01-01T00:00Z"; +assert.throws(RangeError, () => instance.since(str), "date-time + Z is not a ZonedDateTime"); +str = "1970-01-01T00:00+01:00"; +assert.throws(RangeError, () => instance.since(str), "date-time + offset is not a ZonedDateTime"); + +str = "1970-01-01T00:00[+01:00]"; +const result1 = instance.since(str); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "date-time + IANA annotation preserves wall time in the time zone"); + +str = "1970-01-01T00:00Z[+01:00]"; +const result2 = instance.since(str); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation preserves exact time in the time zone"); + +str = "1970-01-01T00:00+01:00[+01:00]"; +const result3 = instance.since(str); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation ensures both exact and wall time match"); + +str = "1970-01-01T00:00-04:15[+01:00]"; +assert.throws(RangeError, () => instance.since(str), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/builtin.js new file mode 100644 index 000000000000..cfe1732a1962 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: > + Tests that Temporal.ZonedDateTime.prototype.startOfDay + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.startOfDay), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.startOfDay), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.startOfDay), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.startOfDay.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..e7409c3906bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.ZonedDateTime(7200_000_000_000n, timeZone, calendar); +instance.startOfDay(); +assert.sameValue(calendar.dateAddCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/length.js new file mode 100644 index 000000000000..32f06d2d4d0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: Temporal.ZonedDateTime.prototype.startOfDay.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.startOfDay, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/name.js new file mode 100644 index 000000000000..66ed88c966f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: Temporal.ZonedDateTime.prototype.startOfDay.name is "startOfDay". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.startOfDay, "name", { + value: "startOfDay", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/not-a-constructor.js new file mode 100644 index 000000000000..51d61618e673 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: > + Temporal.ZonedDateTime.prototype.startOfDay does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.startOfDay(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.startOfDay), false, + "isConstructor(Temporal.ZonedDateTime.prototype.startOfDay)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/prop-desc.js new file mode 100644 index 000000000000..3c179924afab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: The "startOfDay" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.startOfDay, + "function", + "`typeof ZonedDateTime.prototype.startOfDay` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "startOfDay", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/subclassing-ignored.js new file mode 100644 index 000000000000..dde7d4f3c9bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/subclassing-ignored.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [88000_123_456_789n, "UTC"], + "startOfDay", + [], + (result) => { + assert.sameValue(result.epochNanoseconds, 86400_000_000_000n, "epochNanoseconds result"); + assert.sameValue(result.year, 1970, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 2, "day result"); + assert.sameValue(result.hour, 0, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 0, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 0, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..78787c63547b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.startOfDay()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..bbd89f19c19e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.startOfDay(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..ed64a39165df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.startOfDay()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..c2dbe54cc269 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/startOfDay/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.startofday +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.startOfDay()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 000000000000..77b992e115b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: Strings with fractional duration units are rounded with the correct rounding mode +features: [Temporal] +---*/ + +const epoch = new Temporal.ZonedDateTime(0n, "UTC"); + +assert.sameValue(epoch.subtract("PT1.03125H").epochNanoseconds, -3712_500_000_000n, + "positive fractional units rounded with correct rounding mode"); +assert.sameValue(epoch.subtract("-PT1.03125H").epochNanoseconds, 3712_500_000_000n, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/argument-string-negative-fractional-units.js new file mode 100644 index 000000000000..b6069cb6c7ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/argument-string-negative-fractional-units.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: Strings with fractional duration units are treated with the correct sign +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + +const resultHours = instance.subtract("-PT24.567890123H"); +assert.sameValue(resultHours.epochNanoseconds, 1_000_088_444_404_442_799n, "negative fractional hours"); + +const resultMinutes = instance.subtract("-PT1440.567890123M"); +assert.sameValue(resultMinutes.epochNanoseconds, 1_000_086_434_073_407_379n, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/builtin.js new file mode 100644 index 000000000000..3cb69d03e5d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: > + Tests that Temporal.ZonedDateTime.prototype.subtract + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.subtract), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.subtract), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.subtract), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.subtract.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/length.js new file mode 100644 index 000000000000..157fc8a0f3bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: Temporal.ZonedDateTime.prototype.subtract.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.subtract, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/name.js new file mode 100644 index 000000000000..c186490ffc7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: Temporal.ZonedDateTime.prototype.subtract.name is "subtract". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.subtract, "name", { + value: "subtract", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/negative-epochnanoseconds.js new file mode 100644 index 000000000000..f41cc7db4e66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/negative-epochnanoseconds.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.subtract(new Temporal.Duration(0, 0, 0, 1)); +assert.sameValue(result.epochNanoseconds, -13936164_999_999_999n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/non-integer-throws-rangeerror.js new file mode 100644 index 000000000000..9b1b96337f2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.subtract({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/not-a-constructor.js new file mode 100644 index 000000000000..aa62c02687ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: > + Temporal.ZonedDateTime.prototype.subtract does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.subtract(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.subtract), false, + "isConstructor(Temporal.ZonedDateTime.prototype.subtract)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/options-undefined.js new file mode 100644 index 000000000000..fc6df20242dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(954506096_987_654_321n, "UTC"); +const duration = { months: 1 }; + +const explicit = datetime.subtract(duration, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = datetime.subtract(duration); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js new file mode 100644 index 000000000000..d8606c63a465 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-addzoneddatetime step 6: + 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.zoneddatetime.prototype.subtract step 7: + 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-undefined.js new file mode 100644 index 000000000000..b2d933412aca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-addzoneddatetime step 6: + 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.zoneddatetime.prototype.subtract step 7: + 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-1n, "UTC"); +const duration = new Temporal.Duration(0, 1); + +const explicit = datetime.subtract(duration, { overflow: undefined }); +assert.sameValue(explicit.epochNanoseconds, -2678400_000_000_001n, "default overflow is constrain"); +const implicit = datetime.subtract(duration, {}); +assert.sameValue(implicit.epochNanoseconds, -2678400_000_000_001n, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-wrong-type.js new file mode 100644 index 000000000000..a440bf9d2d7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal-addzoneddatetime step 6: + 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_). + sec-temporal.zoneddatetime.prototype.subtract step 7: + 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const duration = new Temporal.Duration(0, 0, 0, 1); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => datetime.subtract(duration, { overflow }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 999_913_600_987_654_321n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/prop-desc.js new file mode 100644 index 000000000000..00645ce865d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: The "subtract" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.subtract, + "function", + "`typeof ZonedDateTime.prototype.subtract` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "subtract", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/subclassing-ignored.js new file mode 100644 index 000000000000..572d3afcfe50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/subclassing-ignored.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [10n, "UTC"], + "subtract", + [{ nanoseconds: 5 }], + (result) => { + assert.sameValue(result.epochNanoseconds, 5n, "epochNanoseconds result"); + assert.sameValue(result.year, 1970, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 1, "day result"); + assert.sameValue(result.hour, 0, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 0, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 5, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..dfeedaedeb49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.subtract(duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..730e27771d3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.subtract(duration), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..633bbd72b4c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.subtract(duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..1581d6698fbc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/subtract/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.subtract +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.subtract(duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/timeZone/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/timeZone/prop-desc.js new file mode 100644 index 000000000000..8c5015d36f37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/timeZone/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.timezone +description: The "timeZone" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "timeZone"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/builtin.js new file mode 100644 index 000000000000..34d19ffdf289 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toinstant +description: > + Tests that Temporal.ZonedDateTime.prototype.toInstant + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toInstant), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toInstant), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toInstant), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toInstant.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/length.js new file mode 100644 index 000000000000..1e1db8d8c5a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toinstant +description: Temporal.ZonedDateTime.prototype.toInstant.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toInstant, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/name.js new file mode 100644 index 000000000000..fa5b9b1bd164 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toinstant +description: Temporal.ZonedDateTime.prototype.toInstant.name is "toInstant". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toInstant, "name", { + value: "toInstant", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/not-a-constructor.js new file mode 100644 index 000000000000..2ad403f91557 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toinstant +description: > + Temporal.ZonedDateTime.prototype.toInstant does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toInstant(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toInstant), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toInstant)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/prop-desc.js new file mode 100644 index 000000000000..2182b3b1aafe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toinstant +description: The "toInstant" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toInstant, + "function", + "`typeof ZonedDateTime.prototype.toInstant` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toInstant", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toInstant/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/balance-negative-time-units.js new file mode 100644 index 000000000000..aff346a41a90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/balance-negative-time-units.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-temporalzoneddatetimetostring step 9: + 9. Let _dateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _isoCalendar_). + sec-get-temporal.zoneddatetime.prototype.tojson step 3: + 3. Return ? TemporalZonedDateTimeToString(_zonedDateTime_, *"auto"*, *"auto"*, *"auto"*, *"auto"*). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// ZonedDateTime +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(1001n, tz); + +const jsonString = datetime.toJSON(); + +assert.sameValue(jsonString, "1970-01-01T00:00:00.000000999+00:00[-00:00:00.000000002]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/builtin.js new file mode 100644 index 000000000000..35482dcd9339 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: > + Tests that Temporal.ZonedDateTime.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/length.js new file mode 100644 index 000000000000..056ec3587dfb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: Temporal.ZonedDateTime.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/name.js new file mode 100644 index 000000000000..2699a27b3fe8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: Temporal.ZonedDateTime.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/negative-epochnanoseconds.js new file mode 100644 index 000000000000..426bd622b14e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/negative-epochnanoseconds.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.toJSON(); +assert.sameValue(result, "1969-07-24T16:50:35.000000001+00:00[UTC]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/not-a-constructor.js new file mode 100644 index 000000000000..a01937eb0f71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: > + Temporal.ZonedDateTime.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toJSON), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/offset.js new file mode 100644 index 000000000000..1d98022c8091 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/offset.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: The time zone offset part of the string serialization +features: [BigInt, Temporal] +---*/ + +function test(timeZoneIdentifier, expected, description) { + const timeZone = new Temporal.TimeZone(timeZoneIdentifier); + const datetime = new Temporal.ZonedDateTime(0n, timeZone); + assert.sameValue(datetime.toJSON(), expected, description); +} + +test("UTC", "1970-01-01T00:00:00+00:00[UTC]", "offset of UTC is +00:00"); +test("+01:00", "1970-01-01T01:00:00+01:00[+01:00]", "positive offset"); +test("-05:00", "1969-12-31T19:00:00-05:00[-05:00]", "negative offset"); +test("+00:44:59.123456789", "1970-01-01T00:44:59.123456789+00:45[+00:44:59.123456789]", "sub-minute offset"); +test("-00:00:10.987654321", "1969-12-31T23:59:49.012345679+00:00[-00:00:10.987654321]", "sub-minute offset that rounds to zero"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/prop-desc.js new file mode 100644 index 000000000000..c372a486bc95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: The "toJSON" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toJSON, + "function", + "`typeof ZonedDateTime.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..5321e80586f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toJSON()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..a33a46450c48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.toJSON(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..29567ee952ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toJSON()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..48d1efcb4d2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.toJSON()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/year-format.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/year-format.js new file mode 100644 index 000000000000..fc6f98258367 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toJSON/year-format.js @@ -0,0 +1,58 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +function epochNsInYear(year) { + // Return an epoch nanoseconds value near the middle of the given year + const avgNsPerYear = 31_556_952_000_000_000n; + return (year - 1970n) * avgNsPerYear + (avgNsPerYear / 2n); +} + +const utc = new Temporal.TimeZone("UTC"); + +let instance = new Temporal.ZonedDateTime(epochNsInYear(-100000n), utc); +assert.sameValue(instance.toJSON(), "-100000-07-01T21:30:36+00:00[UTC]", "large negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-10000n), utc); +assert.sameValue(instance.toJSON(), "-010000-07-01T21:30:36+00:00[UTC]", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-9999n), utc); +assert.sameValue(instance.toJSON(), "-009999-07-02T03:19:48+00:00[UTC]", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-1000n), utc); +assert.sameValue(instance.toJSON(), "-001000-07-02T09:30:36+00:00[UTC]", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-999n), utc); +assert.sameValue(instance.toJSON(), "-000999-07-02T15:19:48+00:00[UTC]", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-1n), utc); +assert.sameValue(instance.toJSON(), "-000001-07-02T15:41:24+00:00[UTC]", "year -1 formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(0n), utc); +assert.sameValue(instance.toJSON(), "0000-07-01T21:30:36+00:00[UTC]", "year 0 formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(1n), utc); +assert.sameValue(instance.toJSON(), "0001-07-02T03:19:48+00:00[UTC]", "year 1 formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(999n), utc); +assert.sameValue(instance.toJSON(), "0999-07-02T03:41:24+00:00[UTC]", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(1000n), utc); +assert.sameValue(instance.toJSON(), "1000-07-02T09:30:36+00:00[UTC]", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(9999n), utc); +assert.sameValue(instance.toJSON(), "9999-07-02T15:41:24+00:00[UTC]", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(10000n), utc); +assert.sameValue(instance.toJSON(), "+010000-07-01T21:30:36+00:00[UTC]", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(100000n), utc); +assert.sameValue(instance.toJSON(), "+100000-07-01T21:30:36+00:00[UTC]", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/builtin.js new file mode 100644 index 000000000000..6fa3ea745b6b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: > + Tests that Temporal.ZonedDateTime.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/length.js new file mode 100644 index 000000000000..ca2626e50309 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: Temporal.ZonedDateTime.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/name.js new file mode 100644 index 000000000000..36f34c047216 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: Temporal.ZonedDateTime.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 000000000000..b82240c1a635 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: > + Temporal.ZonedDateTime.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toLocaleString), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/prop-desc.js new file mode 100644 index 000000000000..d0027b4c5334 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toLocaleString, + "function", + "`typeof ZonedDateTime.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/return-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/return-string.js new file mode 100644 index 000000000000..ae4a76b0c19f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/return-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: > + toLocaleString return a string. +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC"); + +assert.sameValue(typeof datetime.toLocaleString("en", { dateStyle: "short" }), "string"); +assert.sameValue(typeof datetime.toLocaleString("en", { timeStyle: "short" }), "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/builtin.js new file mode 100644 index 000000000000..d220b4ca01a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: > + Tests that Temporal.ZonedDateTime.prototype.toPlainDate + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toPlainDate), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toPlainDate), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toPlainDate), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toPlainDate.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/length.js new file mode 100644 index 000000000000..8a972f282e70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: Temporal.ZonedDateTime.prototype.toPlainDate.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainDate, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/name.js new file mode 100644 index 000000000000..cba001d9fa9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: Temporal.ZonedDateTime.prototype.toPlainDate.name is "toPlainDate". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainDate, "name", { + value: "toPlainDate", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/not-a-constructor.js new file mode 100644 index 000000000000..c068eaa41fc2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: > + Temporal.ZonedDateTime.prototype.toPlainDate does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toPlainDate(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toPlainDate), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toPlainDate)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/prop-desc.js new file mode 100644 index 000000000000..b4e25baf8536 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: The "toPlainDate" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toPlainDate, + "function", + "`typeof ZonedDateTime.prototype.toPlainDate` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toPlainDate", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..c60099438a07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainDate()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..4326d84a7bde --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.toPlainDate(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..ab76c43b0b58 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainDate()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..afbcf23e1208 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDate/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindate +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.toPlainDate()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/balance-negative-time-units.js new file mode 100644 index 000000000000..54cdb83d9793 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/balance-negative-time-units.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.toplaindatetime step 5: + 5. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _zonedDateTime_.[[Calendar]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(1001n, tz); + +const pdt = datetime.toPlainDateTime(); + +TemporalHelpers.assertPlainDateTime(pdt, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/builtin.js new file mode 100644 index 000000000000..ce2151900e9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: > + Tests that Temporal.ZonedDateTime.prototype.toPlainDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toPlainDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toPlainDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toPlainDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toPlainDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/length.js new file mode 100644 index 000000000000..a2e1dd6bf017 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: Temporal.ZonedDateTime.prototype.toPlainDateTime.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainDateTime, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/name.js new file mode 100644 index 000000000000..327899bf7ddf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: Temporal.ZonedDateTime.prototype.toPlainDateTime.name is "toPlainDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainDateTime, "name", { + value: "toPlainDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/negative-epochnanoseconds.js new file mode 100644 index 000000000000..419ba27b35df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.toPlainDateTime(); +TemporalHelpers.assertPlainDateTime(result, 1969, 7, "M07", 24, 16, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/not-a-constructor.js new file mode 100644 index 000000000000..7b01012bd878 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: > + Temporal.ZonedDateTime.prototype.toPlainDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toPlainDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toPlainDateTime), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toPlainDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/plain-custom-timezone.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/plain-custom-timezone.js new file mode 100644 index 000000000000..1ff3dd2d0a7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/plain-custom-timezone.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: timeZone.getOffsetNanosecondsFor() called +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "has timeZone.timeZone", + "get timeZone.getOffsetNanosecondsFor", + "call timeZone.getOffsetNanosecondsFor", +]; + +const timeZone = new Proxy({ + getOffsetNanosecondsFor() { + actual.push("call timeZone.getOffsetNanosecondsFor"); + return -8735135802468; + }, +}, { + has(target, property) { + actual.push(`has timeZone.${property}`); + return property in target; + }, + get(target, property) { + actual.push(`get timeZone.${property}`); + return target[property]; + }, +}); + +const zdt = new Temporal.ZonedDateTime(160583136123456789n, timeZone); +const dateTime = Temporal.PlainDateTime.from("1975-02-02T12:00:00.987654321"); +const result = zdt.toPlainDateTime(); +for (const property of ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]) { + assert.sameValue(result[property], dateTime[property], property); +} + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/prop-desc.js new file mode 100644 index 000000000000..2908e35f849d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: The "toPlainDateTime" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toPlainDateTime, + "function", + "`typeof ZonedDateTime.prototype.toPlainDateTime` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toPlainDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..1a41ff5fc99e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainDateTime()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..2c55923b6d4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.toPlainDateTime(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..2bef748125cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainDateTime()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..5b7afe3ef21d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaindatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.toPlainDateTime()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/builtin.js new file mode 100644 index 000000000000..efb3fa0b5a30 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: > + Tests that Temporal.ZonedDateTime.prototype.toPlainMonthDay + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toPlainMonthDay), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toPlainMonthDay), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toPlainMonthDay), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toPlainMonthDay.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-arguments.js new file mode 100644 index 000000000000..36db546a677c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-arguments.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: Correct options value is passed to calendar method +info: | + MonthDayFromFields ( calendar, fields [ , options ] ) + + 3. If options is not present, then + a. Set options to undefined. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + monthDayFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.sameValue(args[1], undefined, "args[1]"); + return super.monthDayFromFields(...args); + } +} +const zonedDateTime = new Temporal.ZonedDateTime(957270896123456789n, "UTC", new CustomCalendar()); +const result = zonedDateTime.toPlainMonthDay(); +TemporalHelpers.assertPlainMonthDay(result, "M05", 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-fields-iterable.js new file mode 100644 index 000000000000..35725ec9d8b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-fields-iterable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.prototype.toplainmonthday step 7: + 7. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"monthCode"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "monthCode", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +datetime.toPlainMonthDay(); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..38da47c9be3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +instance.toPlainMonthDay(); +assert.sameValue(calendar.monthDayFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-result.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-result.js new file mode 100644 index 000000000000..1a6c8680ddad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-result.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: TypeError thrown when calendar method returns an object with the wrong brand +info: | + MonthDayFromFields ( calendar, fields, options ) + + 4. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + monthDayFromFields() { + return {}; + } +} +const zonedDateTime = new Temporal.ZonedDateTime(957270896123456789n, "UTC", new CustomCalendar()); +assert.throws(TypeError, () => zonedDateTime.toPlainMonthDay()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/length.js new file mode 100644 index 000000000000..21ae4b7fdaa2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: Temporal.ZonedDateTime.prototype.toPlainMonthDay.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainMonthDay, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/name.js new file mode 100644 index 000000000000..677720579330 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: Temporal.ZonedDateTime.prototype.toPlainMonthDay.name is "toPlainMonthDay". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainMonthDay, "name", { + value: "toPlainMonthDay", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/not-a-constructor.js new file mode 100644 index 000000000000..4a5ef356de59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: > + Temporal.ZonedDateTime.prototype.toPlainMonthDay does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toPlainMonthDay(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toPlainMonthDay), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toPlainMonthDay)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/prop-desc.js new file mode 100644 index 000000000000..a238a36a3d10 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: The "toPlainMonthDay" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toPlainMonthDay, + "function", + "`typeof ZonedDateTime.prototype.toPlainMonthDay` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toPlainMonthDay", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..c8afa3cf1b2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainMonthDay()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..086ed868766f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.toPlainMonthDay(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..cfc4eadbbd2a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainMonthDay()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..5817141d8b6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainmonthday +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.toPlainMonthDay()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/balance-negative-time-units.js new file mode 100644 index 000000000000..a08d9616c799 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/balance-negative-time-units.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-get-temporal.zoneddatetime.prototype.toplaintime step 5: + 5. Let _temporalDateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _zonedDateTime_.[[Calendar]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(1001n, tz); + +const time = datetime.toPlainTime(); + +TemporalHelpers.assertPlainTime(time, 0, 0, 0, 0, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/builtin.js new file mode 100644 index 000000000000..786dd916fa1f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: > + Tests that Temporal.ZonedDateTime.prototype.toPlainTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toPlainTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toPlainTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toPlainTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toPlainTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/length.js new file mode 100644 index 000000000000..1abee379e65f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: Temporal.ZonedDateTime.prototype.toPlainTime.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainTime, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/name.js new file mode 100644 index 000000000000..102e9757754e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: Temporal.ZonedDateTime.prototype.toPlainTime.name is "toPlainTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainTime, "name", { + value: "toPlainTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/negative-epochnanoseconds.js new file mode 100644 index 000000000000..f6b8a4cc1d3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.toPlainTime(); +TemporalHelpers.assertPlainTime(result, 16, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/not-a-constructor.js new file mode 100644 index 000000000000..90c579b572b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: > + Temporal.ZonedDateTime.prototype.toPlainTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toPlainTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toPlainTime), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toPlainTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/prop-desc.js new file mode 100644 index 000000000000..a66e6cf3ed1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: The "toPlainTime" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toPlainTime, + "function", + "`typeof ZonedDateTime.prototype.toPlainTime` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toPlainTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..5b98aa2a2e33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainTime()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..8fd1f89652c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.toPlainTime(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..44b0309325e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainTime()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..408990cc8d6a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainTime/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplaintime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.toPlainTime()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/builtin.js new file mode 100644 index 000000000000..540022da8366 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: > + Tests that Temporal.ZonedDateTime.prototype.toPlainYearMonth + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toPlainYearMonth), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toPlainYearMonth), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toPlainYearMonth), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toPlainYearMonth.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-arguments.js new file mode 100644 index 000000000000..8f48742c5e7d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-arguments.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: Correct options value is passed to calendar method +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 3. If options is not present, then + a. Set options to undefined. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + yearMonthFromFields(...args) { + assert.sameValue(args.length, 2, "args.length"); + assert.sameValue(typeof args[0], "object", "args[0]"); + assert.sameValue(args[1], undefined, "args[1]"); + return super.yearMonthFromFields(...args); + } +} +const zonedDateTime = new Temporal.ZonedDateTime(957270896123456789n, "UTC", new CustomCalendar()); +const result = zonedDateTime.toPlainYearMonth(); +TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-fields-iterable.js new file mode 100644 index 000000000000..f534e3d52ed1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-fields-iterable.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.prototype.toplainyearmonth step 7: + 7. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "monthCode", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +datetime.toPlainYearMonth(); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-result.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-result.js new file mode 100644 index 000000000000..f67515f6a161 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-result.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: TypeError thrown when calendar method returns an object with the wrong brand +info: | + YearMonthFromFields ( calendar, fields [ , options ] ) + + 4. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + yearMonthFromFields() { + return {}; + } +} +const zonedDateTime = new Temporal.ZonedDateTime(957270896123456789n, "UTC", new CustomCalendar()); +assert.throws(TypeError, () => zonedDateTime.toPlainYearMonth()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..af59df3f2e27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +instance.toPlainYearMonth(); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/length.js new file mode 100644 index 000000000000..4ae9b200895a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: Temporal.ZonedDateTime.prototype.toPlainYearMonth.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainYearMonth, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/name.js new file mode 100644 index 000000000000..97e29711e349 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: Temporal.ZonedDateTime.prototype.toPlainYearMonth.name is "toPlainYearMonth". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toPlainYearMonth, "name", { + value: "toPlainYearMonth", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/not-a-constructor.js new file mode 100644 index 000000000000..9929ea1155e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: > + Temporal.ZonedDateTime.prototype.toPlainYearMonth does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toPlainYearMonth(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toPlainYearMonth), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toPlainYearMonth)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/prop-desc.js new file mode 100644 index 000000000000..5a7bea42bda8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: The "toPlainYearMonth" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toPlainYearMonth, + "function", + "`typeof ZonedDateTime.prototype.toPlainYearMonth` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toPlainYearMonth", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..bd1b8be5e5c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainYearMonth()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..79e9e2a5c36b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.toPlainYearMonth(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..07949cc4775f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toPlainYearMonth()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..923b828b6b37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.toplainyearmonth +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.toPlainYearMonth()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/balance-negative-time-units.js new file mode 100644 index 000000000000..10af31a2e7b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/balance-negative-time-units.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-temporalzoneddatetimetostring step 9: + 9. Let _dateTime_ be ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _isoCalendar_). + sec-get-temporal.zoneddatetime.prototype.tostring step 9: + 9. Return ? TemporalZonedDateTimeToString(_zonedDateTime_, _precision_.[[Precision]], _showCalendar_, _showTimeZone_, _showOffset_, _precision_.[[Increment]], _precision_.[[Unit]], _roundingMode_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// ZonedDateTime +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(1001n, tz); + +const isoString = datetime.toString(); + +assert.sameValue(isoString, "1970-01-01T00:00:00.000000999+00:00[-00:00:00.000000002]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/builtin.js new file mode 100644 index 000000000000..e24876234d9b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: > + Tests that Temporal.ZonedDateTime.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-invalid-string.js new file mode 100644 index 000000000000..bd5d1a32b3ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-invalid-string.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: RangeError thrown when calendarName option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 6: + 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_64_321n, "UTC"); +assert.throws(RangeError, () => datetime.toString({ calendarName: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-undefined.js new file mode 100644 index 000000000000..bac01c83f388 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-undefined.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: Fallback value for calendarName option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 6: + 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const datetime1 = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const datetime2 = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); + +[ + [datetime1, "2001-09-09T01:46:40.987654321+00:00[UTC]"], + [datetime2, "2001-09-09T01:46:40.987654321+00:00[UTC][u-ca=custom]"], +].forEach(([datetime, expected]) => { + const explicit = datetime.toString({ calendarName: undefined }); + assert.sameValue(explicit, expected, "default calendarName option is auto"); + + // See options-undefined.js for {} +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-wrong-type.js new file mode 100644 index 000000000000..c57bf9233da2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/calendarname-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: Type conversions for calendarName option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-toshowcalendaroption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 6: + 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); + +TemporalHelpers.checkStringOptionWrongType("calendarName", "auto", + (calendarName) => datetime.toString({ calendarName }), + (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.987654321+00:00[UTC][u-ca=custom]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js new file mode 100644 index 000000000000..d9f0b319ea2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values +info: | + sec-getstringornumberoption step 4: + 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.instant.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); + +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-nan.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-nan.js new file mode 100644 index 000000000000..2b91d0ae94f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-nan.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.zoneddatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js new file mode 100644 index 000000000000..4d40e23ed6e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Rounding for fractionalSecondDigits option +info: | + sec-getstringornumberoption step 3.b: + b. Return floor(ℝ(_value_)). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.zoneddatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); + +const string = datetime.toString({ fractionalSecondDigits: 2.5 }); +assert.sameValue(string, "2001-09-09T01:46:40.98+00:00[UTC]", "fractionalSecondDigits 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js new file mode 100644 index 000000000000..72e8cf6b69ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option out of range +info: | + sec-getstringornumberoption step 3.a: + a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception. + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.zoneddatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); + +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -1 })); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 10 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js new file mode 100644 index 000000000000..c1ea7eb7daa4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Fallback value for fractionalSecondDigits option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.zoneddatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); + +const explicit = datetime.toString({ fractionalSecondDigits: undefined }); +assert.sameValue(explicit, "2001-09-09T01:46:40.98765+00:00[UTC]", "default fractionalSecondDigits is auto"); + +// See options-undefined.js for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js new file mode 100644 index 000000000000..2b82767ab51f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Type conversions for fractionalSecondDigits option +info: | + sec-getoption steps 8–9: + 8. Else if _type_ is Number, then + a. Set _value_ to ? ToNumber(value). + b. ... + 9. Else, + a. Set _value_ to ? ToString(value). + sec-getstringornumberoption step 2: + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). + sec-temporal-tosecondsstringprecision step 9: + 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). + sec-temporal.zoneddatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); +TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(datetime); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/length.js new file mode 100644 index 000000000000..0c5995d3fd64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Temporal.ZonedDateTime.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/name.js new file mode 100644 index 000000000000..9bbe15edec65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Temporal.ZonedDateTime.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/negative-epochnanoseconds.js new file mode 100644 index 000000000000..781d6ec7bd47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/negative-epochnanoseconds.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.toString(); +assert.sameValue(result, "1969-07-24T16:50:35.000000001+00:00[UTC]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/not-a-constructor.js new file mode 100644 index 000000000000..9e2f3072ef7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: > + Temporal.ZonedDateTime.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.toString), false, + "isConstructor(Temporal.ZonedDateTime.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-invalid-string.js new file mode 100644 index 000000000000..1ef596771fc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-invalid-string.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: RangeError thrown when offset option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-toshowoffsetoption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"auto"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 8: + 8. Let _showOffset_ be ? ToShowOffsetOption(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_64_321n, "UTC"); +assert.throws(RangeError, () => datetime.toString({ offset: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-undefined.js new file mode 100644 index 000000000000..36e2cff0eea0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: Fallback value for offset option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-toshowoffsetoption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"auto"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 8: + 8. Let _showOffset_ be ? ToShowOffsetOption(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + +const explicit = datetime.toString({ offset: undefined }); +assert.sameValue(explicit, "2001-09-09T01:46:40.987654321+00:00[UTC]", "default offset option is auto"); + +// See options-undefined.js for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-wrong-type.js new file mode 100644 index 000000000000..ba67f067652a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: Type conversions for offset option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-toshowoffsetoption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"auto"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 8: + 8. Let _showOffset_ be ? ToShowOffsetOption(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + +TemporalHelpers.checkStringOptionWrongType("offset", "auto", + (offset) => datetime.toString({ offset }), + (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.987654321+00:00[UTC]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset.js new file mode 100644 index 000000000000..43169a7736c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/offset.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: The time zone offset part of the string serialization +features: [BigInt, Temporal] +---*/ + +function test(timeZoneIdentifier, expected, description) { + const timeZone = new Temporal.TimeZone(timeZoneIdentifier); + const datetime = new Temporal.ZonedDateTime(0n, timeZone); + assert.sameValue(datetime.toString(), expected, description); +} + +test("UTC", "1970-01-01T00:00:00+00:00[UTC]", "offset of UTC is +00:00"); +test("+01:00", "1970-01-01T01:00:00+01:00[+01:00]", "positive offset"); +test("-05:00", "1969-12-31T19:00:00-05:00[-05:00]", "negative offset"); +test("+00:44:59.123456789", "1970-01-01T00:44:59.123456789+00:45[+00:44:59.123456789]", "sub-minute offset"); +test("-00:00:10.987654321", "1969-12-31T23:59:49.012345679+00:00[-00:00:10.987654321]", "sub-minute offset that rounds to zero"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/options-undefined.js new file mode 100644 index 000000000000..ea89f62105ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/options-undefined.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const calendar = { + toString() { return "custom"; } +}; +const datetime1 = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC"); +const datetime2 = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC", calendar); + +[ + [datetime1, "2000-05-02T12:34:56.98765+00:00[UTC]"], + [datetime2, "2000-05-02T12:34:56.98765+00:00[UTC][u-ca=custom]"], +].forEach(([datetime, expected]) => { + const explicit = datetime.toString(undefined); + assert.sameValue(explicit, expected, "default show options are auto, precision is auto, and no rounding"); + + const propertyImplicit = datetime.toString({}); + assert.sameValue(propertyImplicit, expected, "default show options are auto, precision is auto, and no rounding"); + + const implicit = datetime.toString(); + assert.sameValue(implicit, expected, "default show options are auto, precision is auto, and no rounding"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/prop-desc.js new file mode 100644 index 000000000000..f8f5fdc1f826 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: The "toString" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.toString, + "function", + "`typeof ZonedDateTime.prototype.toString` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js new file mode 100644 index 000000000000..f5ffd61c8d38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => datetime.toString({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-undefined.js new file mode 100644 index 000000000000..463acda6c22b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Fallback value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); + +const explicit1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: undefined }); +assert.sameValue(explicit1, "2001-09-09T01:46:40.123987+00:00[UTC]", "default roundingMode is trunc"); +const implicit1 = datetime.toString({ smallestUnit: "microsecond" }); +assert.sameValue(implicit1, "2001-09-09T01:46:40.123987+00:00[UTC]", "default roundingMode is trunc"); + +const explicit2 = datetime.toString({ smallestUnit: "millisecond", roundingMode: undefined }); +assert.sameValue(explicit2, "2001-09-09T01:46:40.123+00:00[UTC]", "default roundingMode is trunc"); +const implicit2 = datetime.toString({ smallestUnit: "millisecond" }); +assert.sameValue(implicit2, "2001-09-09T01:46:40.123+00:00[UTC]", "default roundingMode is trunc"); + +const explicit3 = datetime.toString({ smallestUnit: "second", roundingMode: undefined }); +assert.sameValue(explicit3, "2001-09-09T01:46:40+00:00[UTC]", "default roundingMode is trunc"); +const implicit3 = datetime.toString({ smallestUnit: "second" }); +assert.sameValue(implicit3, "2001-09-09T01:46:40+00:00[UTC]", "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-wrong-type.js new file mode 100644 index 000000000000..23a9dc3a67c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => datetime.toString({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.123987+00:00[UTC]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js new file mode 100644 index 000000000000..7a8d748ea137 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js @@ -0,0 +1,14 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); +assert.throws(RangeError, () => datetime.toString({ smallestUnit: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..012c209997be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_456_789n, "UTC"); +const validUnits = [ + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => datetime.toString({ smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-undefined.js new file mode 100644 index 000000000000..87c8fd375f0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-undefined.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Fallback value for smallestUnit option +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); + +const explicit1 = datetime.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 }); +assert.sameValue(explicit1, "2001-09-09T01:46:40.123987+00:00[UTC]", "default smallestUnit defers to fractionalSecondDigits"); +const implicit1 = datetime.toString({ fractionalSecondDigits: 6 }); +assert.sameValue(implicit1, "2001-09-09T01:46:40.123987+00:00[UTC]", "default smallestUnit defers to fractionalSecondDigits"); + +const explicit2 = datetime.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 }); +assert.sameValue(explicit2, "2001-09-09T01:46:40.123+00:00[UTC]", "default smallestUnit defers to fractionalSecondDigits"); +const implicit2 = datetime.toString({ fractionalSecondDigits: 3 }); +assert.sameValue(implicit2, "2001-09-09T01:46:40.123+00:00[UTC]", "default smallestUnit defers to fractionalSecondDigits"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-valid-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-valid-units.js new file mode 100644 index 000000000000..f3a407bce3ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-valid-units.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Valid units for the smallestUnit option +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_456_789n, "UTC"); + +assert.sameValue(datetime.toString({ smallestUnit: "minute" }), "2001-09-09T01:46+00:00[UTC]"); +assert.sameValue(datetime.toString({ smallestUnit: "second" }), "2001-09-09T01:46:40+00:00[UTC]"); +assert.sameValue(datetime.toString({ smallestUnit: "millisecond" }), "2001-09-09T01:46:40.123+00:00[UTC]"); +assert.sameValue(datetime.toString({ smallestUnit: "microsecond" }), "2001-09-09T01:46:40.123456+00:00[UTC]"); +assert.sameValue(datetime.toString({ smallestUnit: "nanosecond" }), "2001-09-09T01:46:40.123456789+00:00[UTC]"); + +const notValid = [ + "year", + "month", + "week", + "day", + "hour", +]; + +notValid.forEach((smallestUnit) => { + assert.throws(RangeError, () => datetime.toString({ smallestUnit }), smallestUnit); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-wrong-type.js new file mode 100644 index 000000000000..a40859fa9b6b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => datetime.toString({ smallestUnit }), + (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.123987+00:00[UTC]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..b7533b8b7b2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toString()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..5beb4ac542cf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.toString(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..a4ebaf6eb75c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.toString()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..990f34baf5f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.toString()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-invalid-string.js new file mode 100644 index 000000000000..c15a826720ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-invalid-string.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: RangeError thrown when timeZoneName option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-toshowtimezonenameoption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, « String », « *"auto"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 7: + 7. Let _showTimeZone_ be ? ToShowTimeZoneNameOption(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_64_321n, "UTC"); +assert.throws(RangeError, () => datetime.toString({ timeZoneName: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-undefined.js new file mode 100644 index 000000000000..cc2b8f6400b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: Fallback value for timeZoneName option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-toshowtimezonenameoption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, « String », « *"auto"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 7: + 7. Let _showTimeZone_ be ? ToShowTimeZoneNameOption(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + +const explicit = datetime.toString({ timeZoneName: undefined }); +assert.sameValue(explicit, "2001-09-09T01:46:40.987654321+00:00[UTC]", "default timeZoneName option is auto"); + +// See options-undefined.js for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-wrong-type.js new file mode 100644 index 000000000000..20d39a9c2812 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/timezonename-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.tostring +description: Type conversions for timeZoneName option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-toshowtimezonenameoption step 1: + 1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, « String », « *"auto"*, *"never"* », *"auto"*). + sec-temporal.zoneddatetime.protoype.tostring step 7: + 7. Let _showTimeZone_ be ? ToShowTimeZoneNameOption(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + +TemporalHelpers.checkStringOptionWrongType("timeZoneName", "auto", + (timeZoneName) => datetime.toString({ timeZoneName }), + (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.987654321+00:00[UTC]", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/year-format.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/year-format.js new file mode 100644 index 000000000000..d2cd98b7d0e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/toString/year-format.js @@ -0,0 +1,58 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +function epochNsInYear(year) { + // Return an epoch nanoseconds value near the middle of the given year + const avgNsPerYear = 31_556_952_000_000_000n; + return (year - 1970n) * avgNsPerYear + (avgNsPerYear / 2n); +} + +const utc = new Temporal.TimeZone("UTC"); + +let instance = new Temporal.ZonedDateTime(epochNsInYear(-100000n), utc); +assert.sameValue(instance.toString(), "-100000-07-01T21:30:36+00:00[UTC]", "large negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-10000n), utc); +assert.sameValue(instance.toString(), "-010000-07-01T21:30:36+00:00[UTC]", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-9999n), utc); +assert.sameValue(instance.toString(), "-009999-07-02T03:19:48+00:00[UTC]", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-1000n), utc); +assert.sameValue(instance.toString(), "-001000-07-02T09:30:36+00:00[UTC]", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-999n), utc); +assert.sameValue(instance.toString(), "-000999-07-02T15:19:48+00:00[UTC]", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-1n), utc); +assert.sameValue(instance.toString(), "-000001-07-02T15:41:24+00:00[UTC]", "year -1 formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(0n), utc); +assert.sameValue(instance.toString(), "0000-07-01T21:30:36+00:00[UTC]", "year 0 formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(1n), utc); +assert.sameValue(instance.toString(), "0001-07-02T03:19:48+00:00[UTC]", "year 1 formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(999n), utc); +assert.sameValue(instance.toString(), "0999-07-02T03:41:24+00:00[UTC]", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(1000n), utc); +assert.sameValue(instance.toString(), "1000-07-02T09:30:36+00:00[UTC]", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(9999n), utc); +assert.sameValue(instance.toString(), "9999-07-02T15:41:24+00:00[UTC]", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(10000n), utc); +assert.sameValue(instance.toString(), "+010000-07-01T21:30:36+00:00[UTC]", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(100000n), utc); +assert.sameValue(instance.toString(), "+100000-07-01T21:30:36+00:00[UTC]", "large positive year formatted as 6-digit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/argument-propertybag-offset-not-agreeing-with-timezone.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/argument-propertybag-offset-not-agreeing-with-timezone.js new file mode 100644 index 000000000000..b0a5620088c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/argument-propertybag-offset-not-agreeing-with-timezone.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Property bag with offset property is rejected if offset does not agree with time zone +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+01:00"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +const properties = { year: 2021, month: 10, day: 28, offset: "-07:00", timeZone }; +assert.throws(RangeError, () => instance.until(properties), "offset property not matching time zone is rejected"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..517ae82c52da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/argument-propertybag-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const properties = { year: 2004, month: 11, day: 9, hour: 11, minute: 33, second: 20, timeZone }; + timeZone.getPossibleInstantsFor = function () { + return []; + }; + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.until(properties, { largestUnit: "days" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/balance-negative-time-units.js new file mode 100644 index 000000000000..d1e873adf5c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/balance-negative-time-units.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-differenceisodatetime step 2: + 2. Let _timeDifference_ be ? DifferenceTime(_h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_). + sec-temporal-differencezoneddatetime step 7: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + sec-temporal.zoneddatetime.prototype.until step 15: + 15. Let _difference_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _largestUnit_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const datetime = new Temporal.ZonedDateTime(830998861_001_001_001n, timeZone); +const options = { largestUnit: "days" }; + +const result1 = new Temporal.ZonedDateTime(830995200_000_000_002n, timeZone).until(datetime, options); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = new Temporal.ZonedDateTime(830995200_000_002_000n, timeZone).until(datetime, options); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = new Temporal.ZonedDateTime(830995200_002_000_000n, timeZone).until(datetime, options); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = new Temporal.ZonedDateTime(830995202_000_000_000n, timeZone).until(datetime, options); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = new Temporal.ZonedDateTime(830995320_000_000_000n, timeZone).until(datetime, options); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = new Temporal.ZonedDateTime(831002400_000_000_000n, timeZone).until(datetime, options); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/builtin.js new file mode 100644 index 000000000000..03da966d440f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: > + Tests that Temporal.ZonedDateTime.prototype.until + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.until), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.until), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.until), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.until.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..79a8c7301700 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,72 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const earlier = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +// Basic difference with largestUnit larger than days. +// The calls come from these paths: +// ZonedDateTime.until() -> DifferenceZonedDateTime -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() + +const later1 = new Temporal.ZonedDateTime(1_213_200_000_000_000n, timeZone, calendar); +earlier.until(later1, { largestUnit: "weeks" }); +assert.sameValue(calendar.dateAddCallCount, 2, "basic difference with largestUnit >days"); + +// Basic difference with largestUnit equal to days, to cover the second path in +// AddZonedDateTime. +// The calls come from these paths: +// ZonedDateTime.until() -> DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +calendar.dateAddCallCount = 0; + +earlier.until(later1, { largestUnit: "days" }); +assert.sameValue(calendar.dateAddCallCount, 2, "basic difference with largestUnit days"); + +// Difference with rounding, with smallestUnit a calendar unit. +// The calls come from these paths: +// ZonedDateTime.until() -> +// DifferenceZonedDateTime -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// MoveRelativeDate -> calendar.dateAdd() + +calendar.dateAddCallCount = 0; + +earlier.until(later1, { smallestUnit: "weeks" }); +assert.sameValue(calendar.dateAddCallCount, 5, "rounding difference with calendar smallestUnit"); + +// Difference with rounding, with smallestUnit a non-calendar unit, and having +// the resulting time difference be longer than a calendar day, covering the +// paths that go through AdjustRoundedDurationDays. +// The calls come from these paths: +// ZonedDateTime.until() -> +// DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// AdjustRoundedDurationDays -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// AddDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +calendar.dateAddCallCount = 0; + +const later2 = new Temporal.ZonedDateTime(86_399_999_999_999n, timeZone, calendar); +earlier.until(later2, { largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil" }); +assert.sameValue(calendar.dateAddCallCount, 5, "rounding difference with non-calendar smallestUnit and time difference longer than a calendar day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-copy-of-options.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-copy-of-options.js new file mode 100644 index 000000000000..90749d75c227 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-copy-of-options.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: The dateUntil() method on the calendar is called with a copy of the options bag +features: [Temporal] +---*/ + +const originalOptions = { + largestUnit: "year", + shouldBeCopied: {}, +}; +let called = false; + +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(d1, d2, options) { + called = true; + assert.notSameValue(options, originalOptions, "options bag should be a copy"); + assert.sameValue(options.shouldBeCopied, originalOptions.shouldBeCopied, "options bag should be a shallow copy"); + return new Temporal.Duration(1); + } +} +const calendar = new Calendar(); +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +// exactly one year later; avoids NanosecondsToDays path +const later = new Temporal.ZonedDateTime(1_031_536_000_000_000_000n, "UTC", calendar); +earlier.until(later, originalOptions); +assert(called, "calendar.dateUntil must be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 000000000000..ea6c02c51624 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,117 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.zoneddatetime.prototype.until steps 13–17: + 13. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + c. Return ... + 14. ... + 15. Let _difference_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _largestUnit_). + 16. Let _roundResult_ be ? RoundDuration(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _difference_.[[Hours]], _difference_.[[Minutes]], _difference_.[[Seconds]], _difference_.[[Milliseconds]], _difference_.[[Microseconds]], _difference_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_). + 17. Let _result_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_). + sec-temporal-differencezoneddatetime steps 7 and 11: + 7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_). + 11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_). + sec-temporal-roundduration steps 5.d and 8.n–p: + 5. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + ... + 8. If _unit_ is *"year"*, then + ... + n. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). + o. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). + p. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_) + sec-temporal-adjustroundeddurationdays steps 1 and 9: + 1. If _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot; or _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*; or _unit_ is *"nanosecond"* and _increment_ is 1, then + a. Return ... + ... + 9. Let _adjustedDateDuration_ be ? AddDuration(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0, 0, 0, 0, _direction_, 0, 0, 0, 0, 0, 0, _relativeTo_). + sec-temporal-addduration step 7.a–g: + a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot. + ... + f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then + ... + g. Else, + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-nanosecondstodays step 11: + 11. 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*). + sec-temporal-differenceisodatetime steps 9–11: + 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). + 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). + 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); + const later = new Temporal.ZonedDateTime(1_086_403_661_988_655_322n, "UTC", calendar); + earlier.until(later, { largestUnit }); + }, + { + years: ["year", "day"], + months: ["month", "day"], + weeks: ["week", "day"], + days: ["day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +// Additionally check the path that goes through AdjustRoundedDurationDays + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.ZonedDateTime(0n, "UTC", calendar); + const later = new Temporal.ZonedDateTime(86_399_999_999_999n, "UTC", calendar); + earlier.until(later, { largestUnit, roundingIncrement: 2, roundingMode: 'ceil' }); + }, + { + years: ["year", "day", "day", "day"], + months: ["month", "day", "day", "day"], + weeks: ["week", "day", "day", "day"], + days: ["day", "day", "day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +// Also check the path that goes through RoundDuration when smallestUnit is +// given + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, smallestUnit) => { + const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); + const later = new Temporal.ZonedDateTime(1_086_403_661_988_655_322n, "UTC", calendar); + earlier.until(later, { smallestUnit }); + }, + { + years: ["year", "day", "day", "year"], + months: ["month", "day", "day"], + weeks: ["week", "day", "day"], + days: ["day", "day", "day"], + hours: [], + minutes: [], + seconds: [], + milliseconds: [], + microseconds: [], + nanoseconds: [] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-fields-iterable.js new file mode 100644 index 000000000000..520b4cda194b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-fields-iterable.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +datetime.until({ year: 2005, month: 6, day: 2, timeZone: "UTC", calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-temporal-object.js new file mode 100644 index 000000000000..848dacdf90ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.b: + b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", temporalObject); + datetime.until({ year: 2005, month: 6, day: 2, timeZone: "UTC", calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..339a1f53b51a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321, timeZone: "UTC" }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + assert.throws(RangeError, () => instance.until({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.until({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-invalid-string.js new file mode 100644 index 000000000000..cc1f3eb0c7d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +const values = ["era", "eraYear", "other string"]; +for (const largestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-plurals-accepted.js new file mode 100644 index 000000000000..207607de62d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_086_403_661_988_655_322n, "UTC"); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => earlier.until(later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-smallestunit-mismatch.js new file mode 100644 index 000000000000..51c4b4424dfa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => earlier.until(later, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-undefined.js new file mode 100644 index 000000000000..1d98fbb6c2c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); + +const explicit = earlier.until(later, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default largestUnit is hour"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default largestUnit is hour"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-wrong-type.js new file mode 100644 index 000000000000..2dca91ef4223 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "year", + (largestUnit) => earlier.until(later, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/length.js new file mode 100644 index 000000000000..8f12f5c6fe9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Temporal.ZonedDateTime.prototype.until.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.until, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/name.js new file mode 100644 index 000000000000..1acd2c34ea58 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Temporal.ZonedDateTime.prototype.until.name is "until". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.until, "name", { + value: "until", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/negative-epochnanoseconds.js new file mode 100644 index 000000000000..d52e1125762f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.until(new Temporal.ZonedDateTime(0n, "UTC"), { largestUnit: "month" }); +TemporalHelpers.assertDuration(result, 0, 5, 0, 7, 7, 9, 24, 999, 999, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/not-a-constructor.js new file mode 100644 index 000000000000..2e757017e654 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: > + Temporal.ZonedDateTime.prototype.until does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.until(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.until), false, + "isConstructor(Temporal.ZonedDateTime.prototype.until)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/options-undefined.js new file mode 100644 index 000000000000..8bb2683646b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/options-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(957270896_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(959949296_987_654_322n, "UTC"); + +const explicit = earlier.until(later, undefined); +assert.sameValue(explicit.years, 0, "default largest unit is hours"); +assert.sameValue(explicit.months, 0, "default largest unit is hours"); +assert.sameValue(explicit.weeks, 0, "default largest unit is hours"); +assert.sameValue(explicit.days, 0, "default largest unit is hours"); +assert.sameValue(explicit.hours, 744, "default largest unit is hours"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = earlier.until(later); +assert.sameValue(implicit.years, 0, "default largest unit is hours"); +assert.sameValue(implicit.months, 0, "default largest unit is hours"); +assert.sameValue(implicit.weeks, 0, "default largest unit is hours"); +assert.sameValue(implicit.days, 0, "default largest unit is hours"); +assert.sameValue(implicit.hours, 744, "default largest unit is hours"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/prop-desc.js new file mode 100644 index 000000000000..941c8e19054b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: The "until" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.until, + "function", + "`typeof ZonedDateTime.prototype.until` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "until", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..bbe241117ee8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/read-time-fields-before-datefromfields.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.zoneddatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 2.e: + e. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); +const duration = datetime.until({ year: 2001, month: 9, day: 9, timeZone: "UTC", calendar }); + +TemporalHelpers.assertDuration(duration, 0, 0, 0, 0, -1, -46, -40, -987, -654, -321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-nan.js new file mode 100644 index 000000000000..5b9e7a4de268 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.zoneddatetime.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC"); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-non-integer.js new file mode 100644 index 000000000000..6b2b128c85b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-non-integer.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Rounding for roundingIncrement option +info: | + sec-temporal-totemporalroundingincrement step 7: + 7. Set _increment_ to floor(ℝ(_increment_)). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_000_000_000_000_005n, "UTC"); +const result = earlier.until(later, { roundingIncrement: 2.5 }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 floors to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-out-of-range.js new file mode 100644 index 000000000000..23c59e845153 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: RangeError thrown when roundingIncrement option out of range +info: | + sec-temporal-totemporalroundingincrement step 6: + 6. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_000_000_000_000_005n, "UTC"); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-undefined.js new file mode 100644 index 000000000000..9ec699975358 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.zoneddatetime.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC"); + +const explicit = earlier.until(later, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-wrong-type.js new file mode 100644 index 000000000000..55b27b15d80b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.zoneddatetime.prototype.until step 12: + 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC"); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => earlier.until(later, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-invalid-string.js new file mode 100644 index 000000000000..9f7a2a67533c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC"); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-undefined.js new file mode 100644 index 000000000000..e5c99ce34b6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-undefined.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC"); + +const explicit1 = earlier.until(later, { smallestUnit: "microsecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, "default roundingMode is trunc"); +const implicit1 = earlier.until(later, { smallestUnit: "microsecond" }); +TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, "default roundingMode is trunc"); + +const explicit2 = earlier.until(later, { smallestUnit: "millisecond", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 25, 1, 1, 123, 0, 0, "default roundingMode is trunc"); +const implicit2 = earlier.until(later, { smallestUnit: "millisecond" }); +TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 25, 1, 1, 123, 0, 0, "default roundingMode is trunc"); + +const explicit3 = earlier.until(later, { smallestUnit: "second", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 25, 1, 1, 0, 0, 0, "default roundingMode is trunc"); +const implicit3 = earlier.until(later, { smallestUnit: "second" }); +TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 25, 1, 1, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-wrong-type.js new file mode 100644 index 000000000000..fd00dbe2373e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-invalid-string.js new file mode 100644 index 000000000000..b0c08616ef67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-invalid-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +const values = ["era", "eraYear", "other string"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-plurals-accepted.js new file mode 100644 index 000000000000..c8f92d9d5c78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-plurals-accepted.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const later = new Temporal.ZonedDateTime(1_086_403_661_988_655_322n, "UTC"); +const validUnits = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => earlier.until(later, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-undefined.js new file mode 100644 index 000000000000..f0462840f446 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); + +const explicit = earlier.until(later, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-wrong-type.js new file mode 100644 index 000000000000..3571d3876ecd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => earlier.until(later, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/sub-minute-offset.js new file mode 100644 index 000000000000..f9d344e3d009 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/sub-minute-offset.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Fuzzy matching behaviour for UTC offset in ISO 8601 string +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+00:44:30.123456789"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +const result = instance.until("1970-01-01T00:44:30.123456789+00:45[+00:44:30.123456789]"); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "UTC offset rounded to minutes is accepted"); + +assert.throws(RangeError, () => instance.until("1970-01-01T00:44:30.123456789+00:44:30[+00:44:30.123456789]"), "no other rounding than minutes is accepted"); + +const properties = { offset: "+00:45", year: 1970, month: 1, day: 1, minute: 44, second: 30, millisecond: 123, microsecond: 456, nanosecond: 123, timeZone }; +assert.throws(RangeError, () => instance.until(properties), "no fuzzy matching is done on offset in property bag"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..5eed545ea9e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const other = new Temporal.ZonedDateTime(1_100_000_000_123_456_789n, timeZone); + assert.throws(RangeError, () => datetime.until(other, { largestUnit: "days" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..17e192cd730e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const other = new Temporal.ZonedDateTime(1_100_000_000_123_456_789n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.until(other, { largestUnit: "days" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..23b2b349d642 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const other = new Temporal.ZonedDateTime(1_100_000_000_123_456_789n, timeZone); + assert.throws(RangeError, () => datetime.until(other, { largestUnit: "days" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..0487575d921a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const other = new Temporal.ZonedDateTime(1_100_000_000_123_456_789n, timeZone); + assert.throws(TypeError, () => datetime.until(other, { largestUnit: "days" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..00d855fc1b53 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.zoneddatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// Not called on the instance's time zone + +const expected1 = []; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.until({ year: 2005, month: 6, day: 2, timeZone: "UTC" }); +}, expected1); + +// Called on the argument's time zone + +const expected2 = [ + "2005-06-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + datetime.until({ year: 2005, month: 6, day: 2, timeZone }); +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-string-datetime.js new file mode 100644 index 000000000000..0fa754912fcd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-string-datetime.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let expectedTimeZone = "UTC"; +const instance1 = new Temporal.ZonedDateTime(0n, expectedTimeZone); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance1.until({ year: 2020, month: 5, day: 2, timeZone }), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance1.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw. They should produce +// expectedTimeZone, so additionally the operation will not throw due to the +// time zones being different on the receiver and the argument. + +timeZone = "2021-08-19T17:30Z"; +instance1.until({ year: 2020, month: 5, day: 2, timeZone }); +instance1.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +expectedTimeZone = "-07:00"; +const instance2 = new Temporal.ZonedDateTime(0n, expectedTimeZone); +timeZone = "2021-08-19T17:30-07:00"; +instance2.until({ year: 2020, month: 5, day: 2, timeZone }); +instance2.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +expectedTimeZone = "UTC"; +const instance3 = new Temporal.ZonedDateTime(0n, expectedTimeZone); +timeZone = "2021-08-19T17:30[UTC]"; +instance3.until({ year: 2020, month: 5, day: 2, timeZone }); +instance3.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +timeZone = "2021-08-19T17:30Z[UTC]"; +instance3.until({ year: 2020, month: 5, day: 2, timeZone }); +instance3.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +instance3.until({ year: 2020, month: 5, day: 2, timeZone }); +instance3.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..70ac4693cfef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/timezone-string-multiple-offsets.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const expectedTimeZone = "+01:45:30.987654321"; +const instance = new Temporal.ZonedDateTime(0n, expectedTimeZone); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +// These operations should produce expectedTimeZone, so the following operations +// should not throw due to the time zones being different on the receiver and +// the argument. + +instance.until({ year: 2020, month: 5, day: 2, timeZone }); +instance.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/year-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/year-zero.js new file mode 100644 index 000000000000..a0c654f8d9ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/year-zero.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Negative zero, as an extended year, is rejected +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); +const str = "-0000000-01-01T00:02:00.000000000+00:00[UTC]"; + +assert.throws(RangeError, () => { instance.until(str); }, "reject minus zero as extended year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string-multiple-offsets.js new file mode 100644 index 000000000000..0d4172cfb144 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: ZonedDateTime strings with UTC offset fractional part are not confused with time fractional part +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("+00:01:30.987654321"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); +const str = "1970-01-01T00:02:00.000000000+00:02[+00:01:30.987654321]"; + +const result = instance.until(str); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 29, 12, 345, 679, "Time zone determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string.js new file mode 100644 index 000000000000..8f0940d10145 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Conversion of ISO date-time strings to Temporal.ZonedDateTime instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.ZonedDateTime(0n, timeZone); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.until(str), "bare date-time string is not a ZonedDateTime"); +str = "1970-01-01T00:00Z"; +assert.throws(RangeError, () => instance.until(str), "date-time + Z is not a ZonedDateTime"); +str = "1970-01-01T00:00+01:00"; +assert.throws(RangeError, () => instance.until(str), "date-time + offset is not a ZonedDateTime"); + +str = "1970-01-01T00:00[+01:00]"; +const result1 = instance.until(str); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, "date-time + IANA annotation preserves wall time in the time zone"); + +str = "1970-01-01T00:00Z[+01:00]"; +const result2 = instance.until(str); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation preserves exact time in the time zone"); + +str = "1970-01-01T00:00+01:00[+01:00]"; +const result3 = instance.until(str); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation ensures both exact and wall time match"); + +str = "1970-01-01T00:00-04:15[+01:00]"; +assert.throws(RangeError, () => instance.until(str), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/builtin.js new file mode 100644 index 000000000000..2d5cedc86886 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.valueof +description: > + Tests that Temporal.ZonedDateTime.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/length.js new file mode 100644 index 000000000000..330b34743a16 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.valueof +description: Temporal.ZonedDateTime.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/name.js new file mode 100644 index 000000000000..394888ad0239 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.valueof +description: Temporal.ZonedDateTime.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/not-a-constructor.js new file mode 100644 index 000000000000..b690fc394c11 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.valueof +description: > + Temporal.ZonedDateTime.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.valueOf), false, + "isConstructor(Temporal.ZonedDateTime.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/prop-desc.js new file mode 100644 index 000000000000..1ae34964f908 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.valueof +description: The "valueOf" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.valueOf, + "function", + "`typeof ZonedDateTime.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/valueOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/prop-desc.js new file mode 100644 index 000000000000..91bc6ed90173 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.weekofyear +description: The "weekOfYear" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "weekOfYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..abec8fe5603d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.weekofyear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.weekOfYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..aa3695d32525 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.weekofyear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.weekOfYear, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..f209381d58d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.weekofyear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.weekOfYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..cd9be743776b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/weekOfYear/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.weekofyear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.weekOfYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/balance-negative-time-units.js new file mode 100644 index 000000000000..658607da773c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/balance-negative-time-units.js @@ -0,0 +1,65 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-adddatetime step 1: + 1. Let _timeResult_ be ? AddTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal-builtintimezonegetinstantfor step 13.a: + a. Let _earlier_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], 0, 0, 0, 0, 0, 0, 0, 0, 0, −_nanoseconds_, *"constrain"*). + sec-temporal-interpretisodatetimeoffset steps 4–10: + 4. If _offsetNanoseconds_ is *null*, or _offset_ is *"ignore"*, then + a. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _dateTime_, _disambiguation_). + ... + ... + 6. Assert: _offset_ is *"prefer"* or *"reject"*. + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + ... + 9. If _offset_ is *"reject"*, throw a *RangeError* exception. + 10. Let _instant_ be ? DisambiguatePossibleInstants(_possibleInstants_, _timeZone_, _dateTime_, _disambiguation_). + sec-temporal.zoneddatetime.prototype.with step 26: + 26. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_dateTimeResult_.[[Year]], _dateTimeResult_.[[Month]], _dateTimeResult_.[[Day]], _dateTimeResult_.[[Hour]], _dateTimeResult_.[[Minute]], _dateTimeResult_.[[Second]], _dateTimeResult_.[[Millisecond]], _dateTimeResult_.[[Microsecond]], _dateTimeResult_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const shiftInstant = new Temporal.Instant(3661_001_001_001n); +const tz1 = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2); +const datetime1 = new Temporal.ZonedDateTime(3661_001_001_000n, tz1); + +// This code path is encountered if offset is `ignore` or `prefer`, +// disambiguation is `earlier` and the shift is a spring-forward change +datetime1.with({ nanosecond: 1 }, { offset: "ignore", disambiguation: "earlier" }); + +const expected = [ + "1970-01-01T01:01:01.001001001", + "1970-01-01T01:01:01.001000999", +]; +assert.compareArray(tz1.getPossibleInstantsForCalledWith, expected); + +const tz2 = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2); +const datetime2 = new Temporal.ZonedDateTime(3661_001_001_000n, tz2); + +datetime2.with({ nanosecond: 1 }, { offset: "prefer", disambiguation: "earlier" }); + +assert.compareArray(tz2.getPossibleInstantsForCalledWith, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin.js new file mode 100644 index 000000000000..4fb934911b50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: > + Tests that Temporal.ZonedDateTime.prototype.with + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.with), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.with), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.with), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.with.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fields-iterable.js new file mode 100644 index 000000000000..197f2b48426e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fields-iterable.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.prototype.with step 9: + 9. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "hour", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "nanosecond", + "second", + "year", +]; + +const calendar = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +datetime.with({ year: 2005 }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-merge-fields-returns-primitive.js new file mode 100644 index 000000000000..4b68b3006c3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-merge-fields-returns-primitive.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: > + with() should throw a TypeError if mergeFields() returns a primitive, + without passing the value on to any other calendar methods +includes: [compareArray.js, temporalHelpers.js] +features: [BigInt, Symbol, Temporal] +---*/ + +[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => { + const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive); + const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + assert.throws(TypeError, () => instance.with({ year: 2005 }), "bad return from mergeFields() throws"); + assert.sameValue(calendar.dateFromFieldsCallCount, 0, "dateFromFields() never called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copies-merge-fields-object.js new file mode 100644 index 000000000000..935285d7949a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copies-merge-fields-object.js @@ -0,0 +1,62 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: The object returned from mergeFields() is copied before being passed to dateFromFields(). +info: | + sec-temporal.plaindatetime.prototype.with steps 18–19 and 23: + 18. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialDate_). + 19. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « *"timeZone"* »). + 23. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields step 2: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get day", + "get day.valueOf", + "call day.valueOf", + "get hour", + "get hour.valueOf", + "call hour.valueOf", + "get microsecond", + "get microsecond.valueOf", + "call microsecond.valueOf", + "get millisecond", + "get millisecond.valueOf", + "call millisecond.valueOf", + "get minute", + "get minute.valueOf", + "call minute.valueOf", + "get month", + "get month.valueOf", + "call month.valueOf", + "get monthCode", + "get monthCode.toString", + "call monthCode.toString", + "get nanosecond", + "get nanosecond.valueOf", + "call nanosecond.valueOf", + "get second", + "get second.valueOf", + "call second.valueOf", + "get year", + "get year.valueOf", + "call year.valueOf", + "get offset", + "get offset.toString", + "call offset.toString", + "get timeZone", +]; + +const calendar = TemporalHelpers.calendarMergeFieldsGetters(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +datetime.with({ year: 2022 }); + +assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copy-properties-not-undefined.js new file mode 100644 index 000000000000..4878a42db34a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copy-properties-not-undefined.js @@ -0,0 +1,52 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: PreparePartialTemporalFields copies only defined properties of source object +info: | + 4. For each value _property_ of _fieldNames_, do + a. Let _value_ be ? Get(_fields_, _property_). + b. If _value_ is not *undefined*, then + ... + iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_). +features: [Temporal] +---*/ + +const d1 = new Temporal.ZonedDateTime(1_000_000_000_000_000_789n, "UTC"); + +const d2 = d1.with({ day: 1, hour: 10, year: undefined }); + +assert.sameValue(d2.year, 2001, + "only the properties that are present and defined in the plain object are copied (year value)" +); + +assert.sameValue(d2.month, 9, + "only the properties that are present and defined in the plain object are copied (month value)" +); + +assert.sameValue(d2.day, 1, + "only the properties that are present and defined in the plain object are copied (day value)" +); + +assert.sameValue(d2.hour, 10, + "only the properties that are present and defined in the plain object are copied (hour value)" +); +assert.sameValue(d2.minute, 46, + "only the properties that are present and defined in the plain object are copied (minute value)" +); +assert.sameValue(d2.second, 40, + "only the properties that are present and defined in the plain object are copied (second value)" +); +assert.sameValue(d2.millisecond, 0, + "only the properties that are present and defined in the plain object are copied (millisecond value)" +); +assert.sameValue(d2.microsecond, 0, + "only the properties that are present and defined in the plain object are copied (microsecond value)" +); +assert.sameValue(d2.nanosecond, 789, + "only the properties that are present and defined in the plain object are copied (nanosecond value)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-invalid-string.js new file mode 100644 index 000000000000..4c0920fb12f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-invalid-string.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.with +description: RangeError thrown when disambiguation option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.zoneddatetime.protoype.with step 14: + 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +assert.throws(RangeError, () => datetime.with({ hour: 2 }, { disambiguation: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-undefined.js new file mode 100644 index 000000000000..7c69f453c0f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-undefined.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Fallback value for disambiguation option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.zoneddatetime.protoype.with step 14: + 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); +const springForwardDatetime = new Temporal.ZonedDateTime(954702001_000_000_000n, timeZone); +const fallBackDatetime = new Temporal.ZonedDateTime(972849601_000_000_000n, timeZone); +const offset = "ignore"; + +[ + [springForwardDatetime, { hour: 2, minute: 30 }, 954671401_000_000_000n], + [fallBackDatetime, { hour: 1, minute: 30 }, 972808201_000_000_000n], +].forEach(([datetime, fields, expected]) => { + const explicit = datetime.with(fields, { offset, disambiguation: undefined }); + assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible"); + const implicit = datetime.with(fields, { offset }); + assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-wrong-type.js new file mode 100644 index 000000000000..aef98a86f1fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-wrong-type.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Type conversions for disambiguation option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaldisambiguation step 1: + 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*). + sec-temporal.zoneddatetime.protoype.with step 14: + 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible", + (disambiguation) => datetime.with({ hour: 2 }, { disambiguation }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_003_600_987_654_321n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..c59c89424139 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.with +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.with({ [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.with({ [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/length.js new file mode 100644 index 000000000000..1e6bdbff351e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Temporal.ZonedDateTime.prototype.with.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.with, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/name.js new file mode 100644 index 000000000000..9d27f4c29590 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Temporal.ZonedDateTime.prototype.with.name is "with". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/not-a-constructor.js new file mode 100644 index 000000000000..3d15011c5934 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: > + Temporal.ZonedDateTime.prototype.with does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.with(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.with), false, + "isConstructor(Temporal.ZonedDateTime.prototype.with)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-invalid-string.js new file mode 100644 index 000000000000..ba287d911612 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-invalid-string.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.with +description: RangeError thrown when offset option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloffset step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_). + sec-temporal.zoneddatetime.protoype.with step 15: + 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +assert.throws(RangeError, () => datetime.with({ hour: 2 }, { offset: "other string" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-property-sub-minute.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-property-sub-minute.js new file mode 100644 index 000000000000..615e4b30b9ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-property-sub-minute.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Fuzzy matching behaviour with UTC offsets in ISO 8601 strings and offset option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("-00:44:30.123456789"); +const instance = Temporal.ZonedDateTime.from({ year: 1970, month: 1, day: 1, hour: 12, timeZone }); +assert.sameValue(instance.offset, "-00:44:30.123456789", "original offset"); +const properties = { day: 2, offset: "-00:45" }; + +["ignore", "prefer"].forEach((offset) => { + const result = instance.with(properties, { offset }); + assert.sameValue(result.epochNanoseconds, 132270_123_456_789n, `ignores new offset (offset=${offset})`); + assert.sameValue(result.offset, instance.offset, "offset property is unchanged"); + TemporalHelpers.assertPlainDateTime(result.toPlainDateTime(), 1970, 1, "M01", 2, 12, 0, 0, 0, 0, 0, "wall time is not shifted"); +}); + +const result = instance.with(properties, { offset: "use" }); +assert.sameValue(result.epochNanoseconds, 132300_000_000_000n, "accepts HH:MM rounded offset (offset=use)"); +assert.sameValue(result.offset, instance.offset, "offset property is unchanged"); +TemporalHelpers.assertPlainDateTime(result.toPlainDateTime(), 1970, 1, "M01", 2, 12, 0, 29, 876, 543, 211, "wall time is shifted by the difference between exact and rounded offset"); + +assert.throws(RangeError, () => instance.with(properties, { offset: "reject" }), "no fuzzy matching is done in with()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-undefined.js new file mode 100644 index 000000000000..5012f181d37d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Fallback value for offset option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloffset step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_). + sec-temporal.zoneddatetime.protoype.with step 15: + 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*). +features: [Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("-03:30"); + +const datetime = new Temporal.ZonedDateTime(1572757201_000_000_000n, timeZone); +const explicit = datetime.with({ minute: 31 }, { offset: undefined }); +assert.sameValue(explicit.epochNanoseconds, 1572757261_000_000_000n, "default offset is prefer"); +const implicit = datetime.with({ minute: 31 }, {}); +assert.sameValue(implicit.epochNanoseconds, 1572757261_000_000_000n, "default offset is prefer"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-wrong-type.js new file mode 100644 index 000000000000..1910321429ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-wrong-type.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Type conversions for offset option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloffset step 1: + 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_). + sec-temporal.zoneddatetime.protoype.with step 15: + 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +TemporalHelpers.checkStringOptionWrongType("offset", "prefer", + (offset) => datetime.with({ hour: 2 }, { offset }), + (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_003_600_987_654_321n, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-undefined.js new file mode 100644 index 000000000000..73ca26a92def --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(949494896_987_654_321n, "UTC"); +const fields = { day: 31 }; + +const explicit = datetime.with(fields, undefined); +assert.sameValue(explicit.month, 2, "default overflow is constrain"); +assert.sameValue(explicit.day, 29, "default overflow is constrain"); + +const implicit = datetime.with(fields); +assert.sameValue(implicit.month, 2, "default overflow is constrain"); +assert.sameValue(implicit.day, 29, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js new file mode 100644 index 000000000000..08fec9861dbf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.zoneddatetime.prototype.with step 24: + 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.with({ minute: 45 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-undefined.js new file mode 100644 index 000000000000..3b126ca1be75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.zoneddatetime.prototype.with step 24: + 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +const explicit = datetime.with({ second: 67 }, { overflow: undefined }); +assert.sameValue(explicit.epochNanoseconds, 1_000_000_019_987_654_321n, "default overflow is constrain"); +const implicit = datetime.with({ second: 67 }, {}); +assert.sameValue(implicit.epochNanoseconds, 1_000_000_019_987_654_321n, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-wrong-type.js new file mode 100644 index 000000000000..729fb1aac7dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-wrong-type.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-interprettemporaldatetimefields steps 2–3: + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). + 3. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.zoneddatetime.prototype.with step 24: + 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + +// See TemporalHelpers.checkStringOptionWrongType(); this code path has +// different expectations for observable calls + +assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: null }), "null"); +assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: true }), "true"); +assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: false }), "false"); +assert.throws(TypeError, () => datetime.with({ second: 41 }, { overflow: Symbol() }), "symbol"); +assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: 2n }), "bigint"); +assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: {} }), "plain object"); + +// toString property is read once by Calendar.dateFromFields() in the builtin +// calendars, to get the option value for the date part, and then once again +// internally to get the option value for the time part. +const expected = [ + "get overflow.toString", + "call overflow.toString", + "get overflow.toString", + "call overflow.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); +const result = datetime.with({ second: 41 }, { overflow: observer }); +assert.sameValue(result.epochNanoseconds, 1_000_000_001_987_654_321n, "object with toString"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/prop-desc.js new file mode 100644 index 000000000000..69f1599c401e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: The "with" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.with, + "function", + "`typeof ZonedDateTime.prototype.with` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "with", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/read-time-fields-before-datefromfields.js new file mode 100644 index 000000000000..78e5f3e6e95b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/read-time-fields-before-datefromfields.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: The time fields are read from the object before being passed to dateFromFields(). +info: | + sec-temporal.zoneddatetime.prototype.with step 23: + 23. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_). + sec-temporal-interprettemporaldatetimefields steps 1–2: + 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_). + 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarMakeInfinityTime(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar); +const newDatetime = datetime.with({ year: 2022 }); + +assert.sameValue(newDatetime.hour, 1, "hour value"); +assert.sameValue(newDatetime.minute, 46, "minute value"); +assert.sameValue(newDatetime.second, 40, "second value"); +assert.sameValue(newDatetime.millisecond, 987, "millisecond value"); +assert.sameValue(newDatetime.microsecond, 654, "microsecond value"); +assert.sameValue(newDatetime.nanosecond, 321, "nanosecond value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/receiver-offset-broken.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/receiver-offset-broken.js new file mode 100644 index 000000000000..0661345be3ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/receiver-offset-broken.js @@ -0,0 +1,79 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.protoype.with +description: TypeError thrown when the offset field of the receiver is broken +info: | + 10. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »). + 11. Append *"offset"* to _fieldNames_. + 12. Let _partialZonedDateTime_ be ? PreparePartialTemporalFields(_temporalZonedDateTimeLike_, _fieldNames_). + ... + 17. Append *"timeZone"* to _fieldNames_. + 18. Let _fields_ be ? PrepareTemporalFields(_zonedDateTime_, _fieldNames_, « *"timeZone"*, *"offset"* »). + 19. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialZonedDateTime_). + 20. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « *"timeZone"*, *"offset"* »). + 21. Let _offsetString_ be ! Get(_fields_, *"offset"*). + 22. Assert: Type(_offsetString_) is String. +features: [Temporal] +---*/ + +class ObservedCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.resetCalls(); + } + + toString() { + return "observed-calendar"; + } + + mergeFields(original, additional) { + this.mergeFieldsCalled++; + const result = super.mergeFields(original, additional); + result.offset = Symbol("can't convert to string"); + return result; + } + + resetCalls() { + this.mergeFieldsCalled = 0; + } +} + +const calendar = new ObservedCalendar(); +const dateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + +// Test throw in step 12 + +assert.throws(TypeError, () => dateTime.with({ offset: Symbol("can't convert to string") }), "conversion failure on ZonedDateTime-like"); +assert.sameValue(calendar.mergeFieldsCalled, 0, "calendar.mergeFields should not be called"); + +calendar.resetCalls(); + +// Test throw in step 20 (before sabotaging the ZonedDateTime instance) + +assert.throws(TypeError, () => dateTime.with({ year: 2002 }), "conversion failure on sabotaged return value from mergeFields"); +assert.sameValue(calendar.mergeFieldsCalled, 1, "calendar.mergeFields was called once"); + +calendar.resetCalls(); + +// Test throw in step 18 + +Object.defineProperty(dateTime, "offset", { value: Symbol("can't convert to string"), configurable: true }); + +assert.throws(TypeError, () => dateTime.with({ year: 2002 }), "conversion failure on sabotaged offset field of receiver"); +assert.sameValue(calendar.mergeFieldsCalled, 0, "calendar.mergeFields should not be called"); + +calendar.resetCalls(); + +// Test offset being required in step 18 + +Object.defineProperty(dateTime, "offset", { value: undefined }); + +assert.throws(TypeError, () => dateTime.with({ year: 2002 }), "offset property is required on receiver"); +assert.sameValue(calendar.mergeFieldsCalled, 0, "calendar.mergeFields should not be called"); + +calendar.resetCalls(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/subclassing-ignored.js new file mode 100644 index 000000000000..5cb6021d14ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/subclassing-ignored.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [10n, "UTC"], + "with", + [{ year: 2000 }], + (result) => { + assert.sameValue(result.epochNanoseconds, 946684800_000_000_010n, "epochNanoseconds result"); + assert.sameValue(result.year, 2000, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 1, "day result"); + assert.sameValue(result.hour, 0, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 0, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 10, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..55669491f3bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.with({ day: 27 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..e78fb41fa6af --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.with({ day: 27 }, { offset: "prefer" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=prefer and no disambiguation case)` + ); + + const badTimeZone = { + getPossibleInstantsFor() { return []; }, + getOffsetNanosecondsFor: notCallable, + }; + const badDateTime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, badTimeZone); + assert.throws( + TypeError, + () => badDateTime.with({ day: 27 }, { offset: "ignore" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=ignore and no possible instants case)` + ); + assert.throws( + TypeError, + () => badDateTime.with({ day: 27 }, { offset: "prefer" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=prefer and no possible instants case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..6c05382e343e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.with({ day: 27 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..0cb58aaef0a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.with({ day: 27 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 000000000000..368ac0f5f93c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.zoneddatetime.prototype.with step 24: + 24. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_dateTimeResult_.[[Year]], [...], _dateTimeResult_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "2005-09-09T01:46:40", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.with({ year: 2005 }); +}, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/builtin.js new file mode 100644 index 000000000000..fad17c612b52 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withcalendar +description: > + Tests that Temporal.ZonedDateTime.prototype.withCalendar + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.withCalendar), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.withCalendar), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.withCalendar), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.withCalendar.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/calendar-temporal-object.js new file mode 100644 index 000000000000..77ccf7b99d49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/calendar-temporal-object.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withcalendar +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime.prototype.withcalendar step 3: + 3. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const result = zonedDateTime.withCalendar(temporalObject); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/length.js new file mode 100644 index 000000000000..73a3a11bc886 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withcalendar +description: Temporal.ZonedDateTime.prototype.withCalendar.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.withCalendar, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/missing-argument.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/missing-argument.js new file mode 100644 index 000000000000..523839aa667a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/missing-argument.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withcalendar +description: RangeError thrown when calendar argument not given +features: [Temporal] +---*/ + +const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); +assert.throws(RangeError, () => zonedDateTime.withCalendar(), "missing argument"); +assert.throws(RangeError, () => zonedDateTime.withCalendar(undefined), "undefined argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/name.js new file mode 100644 index 000000000000..7bb512e17df3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withcalendar +description: Temporal.ZonedDateTime.prototype.withCalendar.name is "withCalendar". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.withCalendar, "name", { + value: "withCalendar", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/not-a-constructor.js new file mode 100644 index 000000000000..13d29ce0f48a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withcalendar +description: > + Temporal.ZonedDateTime.prototype.withCalendar does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.withCalendar(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.withCalendar), false, + "isConstructor(Temporal.ZonedDateTime.prototype.withCalendar)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/prop-desc.js new file mode 100644 index 000000000000..fdfeadffe10b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withcalendar +description: The "withCalendar" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.withCalendar, + "function", + "`typeof ZonedDateTime.prototype.withCalendar` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "withCalendar", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/subclassing-ignored.js new file mode 100644 index 000000000000..8fdab7cc29a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withCalendar/subclassing-ignored.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withcalendar +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const customCalendar = { + year() { return 1900; }, + month() { return 2; }, + day() { return 5; }, + toString() { return "custom-calendar"; }, +}; + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [10n, "UTC"], + "withCalendar", + [customCalendar], + (result) => { + assert.sameValue(result.epochNanoseconds, 10n, "epochNanoseconds result"); + assert.sameValue(result.year, 1900, "year result"); + assert.sameValue(result.month, 2, "month result"); + assert.sameValue(result.day, 5, "day result"); + assert.sameValue(result.hour, 0, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 0, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 10, "nanosecond result"); + assert.sameValue(result.calendar, customCalendar, "calendar result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-plaindatetime.js new file mode 100644 index 000000000000..85b617df84f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-plaindatetime.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.withplaindate +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.zoneddatetime.prototype.withplaindate step 3: + 3. Let _plainDate_ be ? ToTemporalDate(_plainDateLike_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const receiver = new Temporal.ZonedDateTime(1_000_000_000_123_456_789n, "UTC"); + const result = receiver.withPlainDate(datetime); + assert.sameValue(result.year, 2000, "year result"); + assert.sameValue(result.month, 5, "month result"); + assert.sameValue(result.day, 2, "day result"); + assert.sameValue(result.hour, 1, "hour result"); + assert.sameValue(result.minute, 46, "minute result"); + assert.sameValue(result.second, 40, "second result"); + assert.sameValue(result.millisecond, 123, "millisecond result"); + assert.sameValue(result.microsecond, 456, "microsecond result"); + assert.sameValue(result.nanosecond, 789, "nanosecond result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js new file mode 100644 index 000000000000..de75df681c9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.withPlainDate(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..4c47c02e608e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.withPlainDate(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..738ab93610e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const other = new Temporal.ZonedDateTime(1_100_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.withPlainDate(other)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..a5ab813faef9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const other = new Temporal.ZonedDateTime(1_100_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.withPlainDate(other), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..394bf59a2254 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const other = new Temporal.ZonedDateTime(1_100_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.withPlainDate(other)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..9228c009d81e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const other = new Temporal.ZonedDateTime(1_100_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.withPlainDate(other)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/builtin.js new file mode 100644 index 000000000000..a9e22e5899f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: > + Tests that Temporal.ZonedDateTime.prototype.withPlainDate + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.withPlainDate), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.withPlainDate), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.withPlainDate), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.withPlainDate.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..4a9db20b3f7d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.ZonedDateTime(82800_000_000_000n, timeZone, calendar); +instance.withPlainDate(new Temporal.PlainDate(1970, 1, 1, calendar)); +assert.sameValue(calendar.dateAddCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..60efab821f8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +instance.withPlainDate({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-fields-iterable.js new file mode 100644 index 000000000000..76f14409c32e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-fields-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.zoneddatetime.prototype.withplaindate step 3: + 3. Let _plainDate_ be ? ToTemporalDate(_plainDateLike_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +datetime.withPlainDate({ year: 2001, month: 6, day: 4, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-temporal-object.js new file mode 100644 index 000000000000..b1202b5aed79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.zoneddatetime.prototype.withplaindate step 3: + 3. Let _plainDate_ be ? ToTemporalDate(_plainDateLike_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + // the PlainDate's calendar will override the ZonedDateTime's ISO calendar + const result = datetime.withPlainDate({ year: 2001, month: 6, day: 4, calendar: temporalObject }); + assert.sameValue(result.calendar, calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..c4f3436df9ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.withplaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.withPlainDate({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.withPlainDate({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/length.js new file mode 100644 index 000000000000..f8fd06b0587f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: Temporal.ZonedDateTime.prototype.withPlainDate.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.withPlainDate, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/name.js new file mode 100644 index 000000000000..5558e49c65d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: Temporal.ZonedDateTime.prototype.withPlainDate.name is "withPlainDate". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.withPlainDate, "name", { + value: "withPlainDate", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/negative-epochnanoseconds.js new file mode 100644 index 000000000000..c55a1467586a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/negative-epochnanoseconds.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = datetime.withPlainDate(new Temporal.PlainDate(2000, 5, 2)); +assert.sameValue(result.epochNanoseconds, 957286235_000_000_001n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/not-a-constructor.js new file mode 100644 index 000000000000..170469cf7d08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: > + Temporal.ZonedDateTime.prototype.withPlainDate does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.withPlainDate(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.withPlainDate), false, + "isConstructor(Temporal.ZonedDateTime.prototype.withPlainDate)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/prop-desc.js new file mode 100644 index 000000000000..7db76582ebca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: The "withPlainDate" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.withPlainDate, + "function", + "`typeof ZonedDateTime.prototype.withPlainDate` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "withPlainDate", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/subclassing-ignored.js new file mode 100644 index 000000000000..38702fb1024a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/subclassing-ignored.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [10n, "UTC"], + "withPlainDate", + ["2000-01-01"], + (result) => { + assert.sameValue(result.epochNanoseconds, 946684800_000_000_010n, "epochNanoseconds result"); + assert.sameValue(result.year, 2000, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 1, "day result"); + assert.sameValue(result.hour, 0, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 0, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 10, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..5aa3dcb0b8e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const date = new Temporal.PlainDate(2000, 5, 2); + assert.throws(RangeError, () => datetime.withPlainDate(date)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..3abf12483512 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const date = new Temporal.PlainDate(2000, 5, 2); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.withPlainDate(date), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..d4845b7be2b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const date = new Temporal.PlainDate(2000, 5, 2); + assert.throws(RangeError, () => datetime.withPlainDate(date)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..5d10531290ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const date = new Temporal.PlainDate(2000, 5, 2); + assert.throws(TypeError, () => datetime.withPlainDate(date)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/year-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/year-zero.js new file mode 100644 index 000000000000..0cc8f250a238 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + +assert.throws( + RangeError, + () => { instance.withPlainDate(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-no-implicit-midnight.js new file mode 100644 index 000000000000..b85534132e97 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +assert.throws( + RangeError, + () => instance.withPlainTime(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 000000000000..26cfd1b0cf22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: ISO 8601 time designator "T" required in cases of ambiguity +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + +const ambiguousStrings = [ + "2021-12", // ambiguity between YYYY-MM and HHMM-UU + "1214", // ambiguity between MMDD and HHMM + "0229", // ditto, including MMDD that doesn't occur every year + "1130", // ditto, including DD that doesn't occur in every month + "12-14", // ambiguity between MM-DD and HH-UU + "202112", // ambiguity between YYYYMM and HHMMSS +]; +ambiguousStrings.forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.withPlainTime(arg), + `${string} is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.withPlainTime(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.withPlainTime(arg), + 'space is not accepted as a substitute for T prefix' + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +const unambiguousStrings = [ + "2021-13", // 13 is not a month + "202113", // ditto + "0000-00", // 0 is not a month + "000000", // ditto + "1314", // 13 is not a month + "13-14", // ditto + "1232", // 32 is not a day + "0230", // 30 is not a day in February + "0631", // 31 is not a day in June + "0000", // 0 is neither a month nor a day + "00-00", // ditto +]; +unambiguousStrings.forEach((arg) => instance.withPlainTime(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-with-time-designator.js new file mode 100644 index 000000000000..fd0ebd49503d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-with-time-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.withPlainTime(arg); + assert.sameValue(result.epochNanoseconds, 999995400_000_000_000n, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..41bebd9532b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.withPlainTime(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 000000000000..7399593f2172 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.zoneddatetime.prototype.withplaintime step 4.a: + a. Let _plainTime_ be ? ToTemporalTime(_plainTimeLike_). +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = new Temporal.TimeZone("-00:00:00.000000002"); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const otherTimeZone = new Temporal.TimeZone("UTC"); // should not be used to convert datetime -> PlainTime +const zdt = new Temporal.ZonedDateTime(86400_000_000_000n, otherTimeZone); +const newzdt = zdt.withPlainTime(datetime); + +assert.sameValue(newzdt.microsecond, 0); +assert.sameValue(newzdt.nanosecond, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 000000000000..eda4111b56d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 106. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.ZonedDateTime(0n, "UTC"); +const result = instance.withPlainTime(datetime); +assert.sameValue(result.epochNanoseconds, 60635_000_000_001n); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..ee75947b1243 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const other = new Temporal.ZonedDateTime(1_100_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.withPlainTime(other)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..cf50cf90ebda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const other = new Temporal.ZonedDateTime(1_100_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.withPlainTime(other), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..55ecdc411f3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const other = new Temporal.ZonedDateTime(1_100_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.withPlainTime(other)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..cfbbcd5fecbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + const other = new Temporal.ZonedDateTime(1_100_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.withPlainTime(other)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/builtin.js new file mode 100644 index 000000000000..7b288c09f006 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: > + Tests that Temporal.ZonedDateTime.prototype.withPlainTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.withPlainTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.withPlainTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.withPlainTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.withPlainTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/calendar-dateadd-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 000000000000..0535f0d953ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const instance = new Temporal.ZonedDateTime(7200_000_000_000n, timeZone, calendar); +instance.withPlainTime(); +assert.sameValue(calendar.dateAddCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/calendar-temporal-object.js new file mode 100644 index 000000000000..a25a0aa10cae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/calendar-temporal-object.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindatetime.prototype.withplaintime step 4: + 3. Let _plainTime_ be ? ToTemporalTime(_plainTimeLike_). + sec-temporal-totemporaltime step 3.d: + d. If _calendar_ is not *undefined*, then + i. Set _calendar_ to ? ToTemporalCalendar(_calendar_). + ii. If ? ToString(_calendar_) is not *"iso8601"*, then + 1. Throw a *RangeError* exception. + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 3, 13, 3, 27, 123, 456, 789); + assert.throws(RangeError, () => datetime.withPlainTime({ hour: 12, minute: 30, calendar: temporalObject })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/length.js new file mode 100644 index 000000000000..2a35784e29da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: Temporal.ZonedDateTime.prototype.withPlainTime.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.withPlainTime, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/name.js new file mode 100644 index 000000000000..7d3dcd064eac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: Temporal.ZonedDateTime.prototype.withPlainTime.name is "withPlainTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.withPlainTime, "name", { + value: "withPlainTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/not-a-constructor.js new file mode 100644 index 000000000000..899f4f140a32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: > + Temporal.ZonedDateTime.prototype.withPlainTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.withPlainTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.withPlainTime), false, + "isConstructor(Temporal.ZonedDateTime.prototype.withPlainTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/plaintime-propertybag-no-time-units.js new file mode 100644 index 000000000000..4fc6257d54e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/plaintime-propertybag-no-time-units.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: Missing time units in property bag default to 0 +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + +const props = {}; +assert.throws(TypeError, () => instance.withPlainTime(props), "TypeError if at least one property is not present"); + +props.minute = 30; +const result = instance.withPlainTime(props); +assert.sameValue(result.epochNanoseconds, 999995400_000_000_000n, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/prop-desc.js new file mode 100644 index 000000000000..6d0c78f067e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: The "withPlainTime" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.withPlainTime, + "function", + "`typeof ZonedDateTime.prototype.withPlainTime` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "withPlainTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/subclassing-ignored.js new file mode 100644 index 000000000000..9544d5f894b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/subclassing-ignored.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [10n, "UTC"], + "withPlainTime", + ["05:43:21.123456789"], + (result) => { + assert.sameValue(result.epochNanoseconds, 20601_123_456_789n, "epochNanoseconds result"); + assert.sameValue(result.year, 1970, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 1, "day result"); + assert.sameValue(result.hour, 5, "hour result"); + assert.sameValue(result.minute, 43, "minute result"); + assert.sameValue(result.second, 21, "second result"); + assert.sameValue(result.millisecond, 123, "millisecond result"); + assert.sameValue(result.microsecond, 456, "microsecond result"); + assert.sameValue(result.nanosecond, 789, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/time-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/time-undefined.js new file mode 100644 index 000000000000..c44bfdab31b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/time-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: The time is assumed to be midnight if not given +features: [BigInt, Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(957270896_987_654_321n, "UTC"); + +const explicit = datetime.withPlainTime(undefined); +assert.sameValue(explicit.hour, 0, "default time is midnight"); +assert.sameValue(explicit.minute, 0, "default time is midnight"); +assert.sameValue(explicit.second, 0, "default time is midnight"); +assert.sameValue(explicit.millisecond, 0, "default time is midnight"); +assert.sameValue(explicit.microsecond, 0, "default time is midnight"); +assert.sameValue(explicit.nanosecond, 0, "default time is midnight"); + +const implicit = datetime.withPlainTime(); +assert.sameValue(implicit.hour, 0, "default time is midnight"); +assert.sameValue(implicit.minute, 0, "default time is midnight"); +assert.sameValue(implicit.second, 0, "default time is midnight"); +assert.sameValue(implicit.millisecond, 0, "default time is midnight"); +assert.sameValue(implicit.microsecond, 0, "default time is midnight"); +assert.sameValue(implicit.nanosecond, 0, "default time is midnight"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..ff5eec32ffdb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => datetime.withPlainTime(time)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..7add21b1dd9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.withPlainTime(time), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..c30292aec26b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(RangeError, () => datetime.withPlainTime(time)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..25b24e885155 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + assert.throws(TypeError, () => datetime.withPlainTime(time)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/year-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/year-zero.js new file mode 100644 index 000000000000..6e2f10c34fa3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withPlainTime/year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaintime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + '-000000-12-07T03:24:30', + '-000000-12-07T03:24:30+01:00[UTC]' +]; +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.withPlainTime(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/builtin.js new file mode 100644 index 000000000000..affb2f59519c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withtimezone +description: > + Tests that Temporal.ZonedDateTime.prototype.withTimeZone + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.withTimeZone), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.withTimeZone), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.withTimeZone), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.ZonedDateTime.prototype.withTimeZone.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/length.js new file mode 100644 index 000000000000..bbb7774defc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withtimezone +description: Temporal.ZonedDateTime.prototype.withTimeZone.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.withTimeZone, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/name.js new file mode 100644 index 000000000000..d70b1c9b266e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withtimezone +description: Temporal.ZonedDateTime.prototype.withTimeZone.name is "withTimeZone". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.ZonedDateTime.prototype.withTimeZone, "name", { + value: "withTimeZone", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/not-a-constructor.js new file mode 100644 index 000000000000..89fce3c8a3e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withtimezone +description: > + Temporal.ZonedDateTime.prototype.withTimeZone does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.ZonedDateTime.prototype.withTimeZone(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.withTimeZone), false, + "isConstructor(Temporal.ZonedDateTime.prototype.withTimeZone)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/prop-desc.js new file mode 100644 index 000000000000..3f261d071663 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withtimezone +description: The "withTimeZone" property of Temporal.ZonedDateTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.ZonedDateTime.prototype.withTimeZone, + "function", + "`typeof ZonedDateTime.prototype.withTimeZone` is `function`" +); + +verifyProperty(Temporal.ZonedDateTime.prototype, "withTimeZone", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/shell.js index e69de29bb2d1..54371b778989 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/subclassing-ignored.js new file mode 100644 index 000000000000..abe9ed226549 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/subclassing-ignored.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withtimezone +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.ZonedDateTime, + [10n, "UTC"], + "withTimeZone", + ["+01:00"], + (result) => { + assert.sameValue(result.epochNanoseconds, 10n, "epochNanoseconds result"); + assert.sameValue(result.year, 1970, "year result"); + assert.sameValue(result.month, 1, "month result"); + assert.sameValue(result.day, 1, "day result"); + assert.sameValue(result.hour, 1, "hour result"); + assert.sameValue(result.minute, 0, "minute result"); + assert.sameValue(result.second, 0, "second result"); + assert.sameValue(result.millisecond, 0, "millisecond result"); + assert.sameValue(result.microsecond, 0, "microsecond result"); + assert.sameValue(result.nanosecond, 10, "nanosecond result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-datetime.js new file mode 100644 index 000000000000..2e33a6f7f0fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-datetime.js @@ -0,0 +1,47 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withtimezone +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(0n, "UTC"); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.withTimeZone(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => instance.withTimeZone({ timeZone }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = instance.withTimeZone(timeZone); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = instance.withTimeZone({ timeZone }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = instance.withTimeZone(timeZone); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = instance.withTimeZone({ timeZone }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = instance.withTimeZone(timeZone); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = instance.withTimeZone({ timeZone }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = instance.withTimeZone(timeZone); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = instance.withTimeZone({ timeZone }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = instance.withTimeZone(timeZone); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = instance.withTimeZone({ timeZone }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-multiple-offsets.js new file mode 100644 index 000000000000..44e5ce54d1c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-multiple-offsets.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withtimezone +description: Time zone strings with UTC offset fractional part are not confused with time fractional part +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(0n, "UTC"); +const timeZone = "2021-08-19T17:30:45.123456789+01:46[+01:45:30.987654321]"; + +const result1 = instance.withTimeZone(timeZone); +assert.sameValue(result1.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); +const result2 = instance.withTimeZone({ timeZone }); +assert.sameValue(result2.timeZone.id, "+01:45:30.987654321", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/calendar-returns-infinity.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/calendar-returns-infinity.js new file mode 100644 index 000000000000..b7ca1d7e7699 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.year +description: Getter throws if the calendar returns ±∞ from its year method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + year() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.ZonedDateTime(0n, "UTC", pos); +assert.throws(RangeError, () => instance1.year); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.ZonedDateTime(0n, "UTC", neg); +assert.throws(RangeError, () => instance2.year); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/prop-desc.js new file mode 100644 index 000000000000..17f4269bd7fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.year +description: The "year" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "year"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..03eef3f027d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.year +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.year); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..af569950a4ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.year +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.year, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..45bbe4f752d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.year +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.year); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..521148a7825b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/year/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.year +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.year); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/shell.js index e69de29bb2d1..1d70b7579ee9 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/shell.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..04270409e7fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => new Temporal.ZonedDateTime(0n, timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => new Temporal.ZonedDateTime(0n, { timeZone }), "bare date-time string is not a time zone"); + +timeZone = "2021-08-19T17:30Z"; +const result1 = new Temporal.ZonedDateTime(0n, timeZone); +assert.sameValue(result1.timeZone.id, "UTC", "date-time + Z is UTC time zone"); +const result2 = new Temporal.ZonedDateTime(0n, { timeZone }); +assert.sameValue(result2.timeZone.id, "UTC", "date-time + Z is UTC time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00"; +const result3 = new Temporal.ZonedDateTime(0n, timeZone); +assert.sameValue(result3.timeZone.id, "-07:00", "date-time + offset is the offset time zone"); +const result4 = new Temporal.ZonedDateTime(0n, { timeZone }); +assert.sameValue(result4.timeZone.id, "-07:00", "date-time + offset is the offset time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result5 = new Temporal.ZonedDateTime(0n, timeZone); +assert.sameValue(result5.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone"); +const result6 = new Temporal.ZonedDateTime(0n, { timeZone }); +assert.sameValue(result6.timeZone.id, "UTC", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result7 = new Temporal.ZonedDateTime(0n, timeZone); +assert.sameValue(result7.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); +const result8 = new Temporal.ZonedDateTime(0n, { timeZone }); +assert.sameValue(result8.timeZone.id, "UTC", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result9 = new Temporal.ZonedDateTime(0n, timeZone); +assert.sameValue(result9.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); +const result10 = new Temporal.ZonedDateTime(0n, { timeZone }); +assert.sameValue(result10.timeZone.id, "UTC", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/getOwnPropertyNames.js b/js/src/tests/test262/built-ins/Temporal/getOwnPropertyNames.js new file mode 100644 index 000000000000..8da3469a9180 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/getOwnPropertyNames.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-objects +description: Temporal has own property names +features: [Temporal] +---*/ + +const keys = Object.getOwnPropertyNames(Temporal); + +assert(keys.indexOf("Instant") > -1, "Instant"); +assert(keys.indexOf("TimeZone") > -1, "TimeZone"); +assert(keys.indexOf("PlainDate") > -1, "PlainDate"); +assert(keys.indexOf("PlainTime") > -1, "PlainTime"); +assert(keys.indexOf("PlainDateTime") > -1, "PlainDateTime"); +assert(keys.indexOf("ZonedDateTime") > -1, "ZonedDateTime"); +assert(keys.indexOf("PlainYearMonth") > -1, "PlainYearMonth"); +assert(keys.indexOf("PlainMonthDay") > -1, "PlainMonthDay"); +assert(keys.indexOf("Duration") > -1, "Duration"); +assert(keys.indexOf("Calendar") > -1, "Calendar"); +assert(keys.indexOf("Now") > -1, "Now"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/keys.js b/js/src/tests/test262/built-ins/Temporal/keys.js new file mode 100644 index 000000000000..610bb109d8d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/keys.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-objects +description: Temporal has no enumerable properties +includes: [compareArray.js] +features: [Temporal] +---*/ + +const keys = Object.keys(Temporal); +assert.compareArray(keys, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/prop-desc.js new file mode 100644 index 000000000000..110821d4d09e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-objects +includes: [propertyHelper.js] +description: The "Temporal" property of the global object +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal, "object"); +verifyProperty(this, "Temporal", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/toStringTag/browser.js b/js/src/tests/test262/built-ins/Temporal/toStringTag/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/toStringTag/prop-desc.js new file mode 100644 index 000000000000..4d430e0b5b8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/toStringTag/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-@@tostringtag +description: The @@toStringTag property of Temporal +includes: [propertyHelper.js] +features: [Symbol.toStringTag, Temporal] +---*/ + +verifyProperty(Temporal, Symbol.toStringTag, { + value: "Temporal", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/toStringTag/shell.js b/js/src/tests/test262/built-ins/Temporal/toStringTag/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/toStringTag/string.js b/js/src/tests/test262/built-ins/Temporal/toStringTag/string.js new file mode 100644 index 000000000000..9b036e1b9dba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/toStringTag/string.js @@ -0,0 +1,13 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-@@tostringtag +description: The @@toStringTag property of Temporal produces the correct value in toString +features: [Symbol.toStringTag, Temporal] +---*/ + +assert.sameValue(String(Temporal), "[object Temporal]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/browser.js b/js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..33f5aeb6d421 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.at +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, TypedArray.prototype.at, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.at, + 'function', + 'implements TypedArray.prototype.at' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.at(0); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.at(0); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the at operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.at(0); + throw new Test262Error('at completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/shell.js b/js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/shell.js new file mode 100644 index 000000000000..90ee9c114d87 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/at/BigInt/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/BigInt/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/BigInt/resizable-array-buffer-auto.js new file mode 100644 index 000000000000..e3051b920a49 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/BigInt/resizable-array-buffer-auto.js @@ -0,0 +1,56 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-get-%typedarray%.prototype.byteoffset +description: | + reset to 0 if the underlying ArrayBuffer is resized beyond the boundary of + the dynamically-sized TypedArray instance +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, "function"); + +testWithBigIntTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE); + var expected = BPE * 3; + + assert.sameValue(array.byteLength, expected); + + try { + ab.resize(BPE * 5); + expected = BPE * 4; + } catch (_) {} + + assert.sameValue(array.byteLength, expected, "following grow"); + + try { + ab.resize(BPE * 3); + expected = BPE * 2; + } catch (_) {} + + assert.sameValue(array.byteLength, expected, "following shrink (within bounds)"); + + try { + ab.resize(BPE); + expected = 0; + } catch (_) {} + + assert.sameValue(array.byteLength, expected, "following shrink (on boundary)"); + + try { + ab.resize(0); + expected = 0; + } catch (_) {} + + assert.sameValue(array.byteLength, expected, "following shrink (out of bounds)"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/BigInt/resizable-array-buffer-fixed.js b/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/BigInt/resizable-array-buffer-fixed.js new file mode 100644 index 000000000000..366e9c00fae5 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/BigInt/resizable-array-buffer-fixed.js @@ -0,0 +1,49 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-get-%typedarray%.prototype.bytelength +description: | + reset to 0 if the underlying ArrayBuffer is resized beyond the boundary of + the fixed-sized TypedArray instance +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, "function"); + +testWithBigIntTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + assert.sameValue(array.byteLength, BPE * 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + assert.sameValue(array.byteLength, BPE * 2, "following grow"); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + assert.sameValue(array.byteLength, BPE * 2, "following shrink (within bounds)"); + + var expected; + try { + ab.resize(BPE * 2); + expected = 0; + } catch (_) { + expected = BPE * 2; + } + + assert.sameValue(array.byteLength, expected, "following shrink (out of bounds)"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/resizable-array-buffer-auto.js index 4c5495bdb7cf..16c93b6cacc5 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/resizable-array-buffer-auto.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/byteLength/resizable-array-buffer-auto.js @@ -43,6 +43,13 @@ testWithTypedArrayConstructors(function(TA) { expected = 0; } catch (_) {} + assert.sameValue(array.byteLength, expected, "following shrink (on boundary)"); + + try { + ab.resize(0); + expected = 0; + } catch (_) {} + assert.sameValue(array.byteLength, expected, "following shrink (out of bounds)"); }); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/BigInt/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/BigInt/resizable-array-buffer-auto.js new file mode 100644 index 000000000000..82604a178cd3 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/BigInt/resizable-array-buffer-auto.js @@ -0,0 +1,53 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-get-%typedarray%.prototype.byteoffset +description: | + reset to 0 if the underlying ArrayBuffer is resized beyond the boundary of + the dynamically-sized TypedArray instance +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, "function"); + +testWithBigIntTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE); + + assert.sameValue(array.byteOffset, BPE); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + assert.sameValue(array.byteOffset, BPE, "following grow"); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + assert.sameValue(array.byteOffset, BPE, "following shrink (within bounds)"); + + try { + ab.resize(BPE); + } catch (_) {} + + assert.sameValue(array.byteOffset, BPE, "following shrink (on boundary)"); + + var expected = BPE; + try { + ab.resize(0); + expected = 0; + } catch (_) {} + + assert.sameValue(array.byteOffset, expected, "following shrink (out of bounds)"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/BigInt/resizable-array-buffer-fixed.js b/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/BigInt/resizable-array-buffer-fixed.js new file mode 100644 index 000000000000..f047af9c48e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/BigInt/resizable-array-buffer-fixed.js @@ -0,0 +1,49 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-get-%typedarray%.prototype.byteoffset +description: | + reset to 0 if the underlying ArrayBuffer is resized beyond the boundary of + the fixed-sized TypedArray instance +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, "function"); + +testWithBigIntTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + assert.sameValue(array.byteOffset, BPE); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + assert.sameValue(array.byteOffset, BPE, "following grow"); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + assert.sameValue(array.byteOffset, BPE, "following shrink (within bounds)"); + + var expected; + try { + ab.resize(BPE * 2); + expected = 0; + } catch (_) { + expected = BPE; + } + + assert.sameValue(array.byteOffset, expected, "following shrink (out of bounds)"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/resizable-array-buffer-auto.js index 685dd9cfa87c..3f902220558d 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/resizable-array-buffer-auto.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/byteOffset/resizable-array-buffer-auto.js @@ -35,13 +35,17 @@ testWithTypedArrayConstructors(function(TA) { assert.sameValue(array.byteOffset, BPE, "following shrink (within bounds)"); - var expected; try { ab.resize(BPE); + } catch (_) {} + + assert.sameValue(array.byteOffset, BPE, "following shrink (on boundary)"); + + var expected = BPE; + try { + ab.resize(0); expected = 0; - } catch (_) { - expected = BPE; - } + } catch (_) {} assert.sameValue(array.byteOffset, expected, "following shrink (out of bounds)"); }); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..fcf1f9323a1c --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.copywithin +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.copyWithin, + 'function', + 'implements TypedArray.prototype.copyWithin' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.copyWithin(0, 0); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.copyWithin(0, 0); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the copyWithin operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.copyWithin(0, 0); + throw new Test262Error('copyWithin completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/byteoffset.js b/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/byteoffset.js new file mode 100644 index 000000000000..ec9f014d04fa --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/byteoffset.js @@ -0,0 +1,35 @@ +// Copyright (C) 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.copywithin +description: > + copyWithin should respect typedarray's byteOffset +info: | + 22.2.3.5%TypedArray%.prototype.copyWithin ( target, start [ , end ] ) + ... + 17. If count > 0, then + e. Let elementSize be the Element Size value specified in Table 72 for typedArrayName. + f. Let byteOffset be O.[[ByteOffset]]. + g. Let toByteIndex be to × elementSize + byteOffset. + h. Let fromByteIndex be from × elementSize + byteOffset. + ... +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray] +---*/ + +testWithTypedArrayConstructors(function(TA) { + var ta = new TA([0, 1, 2, 3]); + assert.compareArray( + new TA(ta.buffer, TA.BYTES_PER_ELEMENT).copyWithin(2, 0), + [1, 2, 1], + 'copyWithin should respect typedarray\'s byteOffset' + ); + + assert.compareArray( + ta, + [0, 1, 2, 1], + 'underlying arraybuffer should have been updated' + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/coerced-values-target.js b/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/coerced-values-target.js index a6f3b3e86122..cfe5773f8f45 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/coerced-values-target.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/coerced-values-target.js @@ -89,6 +89,14 @@ testWithTypedArrayConstructors(function(TA) { ), '1.5 float value coerced to integer 1' ); + + assert( + compareArray( + new TA([0, 1, 2, 3]).copyWithin({}, 1), + [1, 2, 3, 3] + ), + 'object value coerced to integer 0' + ); }); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/return-abrupt-from-this-out-of-bounds.js index 9ef49c50290f..a9c562a62a80 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/copyWithin/return-abrupt-from-this-out-of-bounds.js @@ -30,14 +30,14 @@ testWithTypedArrayConstructors(TA => { } catch (_) {} // no error following grow: - array.copyWithin(new TA(), 0); + array.copyWithin(0, 0); try { ab.resize(BPE * 3); } catch (_) {} // no error following shrink (within bounds): - array.copyWithin(new TA(), 0); + array.copyWithin(0, 0); var expectedError; try { @@ -54,7 +54,7 @@ testWithTypedArrayConstructors(TA => { } assert.throws(expectedError, () => { - array.copyWithin(new TA(), 0); + array.copyWithin(0, 0); throw new Test262Error('copyWithin completed successfully'); }); }); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/entries/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/entries/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..8aed92e4394e --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/entries/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.entries +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.entries, + 'function', + 'implements TypedArray.prototype.entries' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.entries(); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.entries(); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the entries operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.entries(); + throw new Test262Error('entries completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/every/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/every/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..7d9bf0d85ff4 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/every/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.every +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.every, + 'function', + 'implements TypedArray.prototype.every' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.every(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.every(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the every operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.every(() => {}); + throw new Test262Error('every completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/every/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/every/callbackfn-resize.js new file mode 100644 index 000000000000..6dca2c649d5b --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/every/callbackfn-resize.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.every +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.every(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return true; + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, true, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.every(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return true; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, true, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/fill/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/fill/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..7d483c1ce073 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/fill/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.fill +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.fill, + 'function', + 'implements TypedArray.prototype.fill' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.fill(0n); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.fill(0n); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the fill operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.fill(0n); + throw new Test262Error('fill completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/filter/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/filter/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..f16b6b0daffe --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/filter/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.filter +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.filter, + 'function', + 'implements TypedArray.prototype.filter' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.filter(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.filter(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the filter operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.filter(() => {}); + throw new Test262Error('filter completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/filter/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/filter/callbackfn-resize.js new file mode 100644 index 000000000000..bbbdd4c1b092 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/filter/callbackfn-resize.js @@ -0,0 +1,79 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.filter +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var NaNvalue = (TA === Float32Array || TA === Float64Array) ? NaN : 0; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, finalResult, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.filter(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + finalResult = NaNvalue; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + finalResult = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return true; + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.compareArray(result, [0, 0, finalResult], 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.filter(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return true; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.compareArray(result, expectedElements, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/find/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/find/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..bd9d8b9de73e --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/find/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.find +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.find, + 'function', + 'implements TypedArray.prototype.find' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.find(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.find(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the find operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.find(() => {}); + throw new Test262Error('find completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/find/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/find/callbackfn-resize.js new file mode 100644 index 000000000000..3165cc78d0d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/find/callbackfn-resize.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.find +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.find(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, undefined, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.find(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, undefined, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/findIndex/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/findIndex/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..bbcc35680530 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/findIndex/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.findindex +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.findIndex, + 'function', + 'implements TypedArray.prototype.findIndex' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.findIndex(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.findIndex(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the findIndex operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.findIndex(() => {}); + throw new Test262Error('findIndex completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/findIndex/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/findIndex/callbackfn-resize.js new file mode 100644 index 000000000000..1986131e11c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/findIndex/callbackfn-resize.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.findindex +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.findIndex(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, -1, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.findIndex(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, -1, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/findLast/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/findLast/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..bc3d2e7866a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/findLast/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- array-find-from-last,resizable-arraybuffer is not supported +// Copyright (C) 2021 Microsoft. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.findlast +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, array-find-from-last, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.findLast, + 'function', + 'implements TypedArray.prototype.findLast' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.findLast(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.findLast(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the findLast operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.findLast(() => {}); + throw new Test262Error('findLast completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/findLast/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/findLast/callbackfn-resize.js new file mode 100644 index 000000000000..9205a424fb2a --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/findLast/callbackfn-resize.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.findlast +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var secondElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.findLast(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(BPE); + secondElement = undefined; + expectedElements = [0]; + expectedIndices = [0]; + expectedArrays = [sample]; + } catch (_) { + secondElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [2, 1, 0]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, secondElement, 0], 'elements (shrink)'); + assert.compareArray(indices, [2, 1, 0], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, undefined, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.findLast(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, undefined, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..4c81ec933660 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- array-find-from-last,resizable-arraybuffer is not supported +// Copyright (C) 2021 Microsoft. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.findlastindex +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, array-find-from-last, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.findLastIndex, + 'function', + 'implements TypedArray.prototype.findLastIndex' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.findLastIndex(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.findLastIndex(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the findLastIndex operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.findLastIndex(() => {}); + throw new Test262Error('findLastIndex completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/findLastIndex/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/findLastIndex/callbackfn-resize.js new file mode 100644 index 000000000000..b79f2aa982af --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/findLastIndex/callbackfn-resize.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.findlastindex +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var secondElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.findLastIndex(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(BPE); + secondElement = undefined; + expectedElements = [0]; + expectedIndices = [0]; + expectedArrays = [sample]; + } catch (_) { + secondElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [2, 1, 0]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, secondElement, 0], 'elements (shrink)'); + assert.compareArray(indices, [2, 1, 0], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, -1, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.findLastIndex(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, -1, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/forEach/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/forEach/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..35bab2380676 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/forEach/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.foreach +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.forEach, + 'function', + 'implements TypedArray.prototype.forEach' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.forEach(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.forEach(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the forEach operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.forEach(() => {}); + throw new Test262Error('forEach completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/forEach/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/forEach/callbackfn-resize.js new file mode 100644 index 000000000000..0b84275ac48f --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/forEach/callbackfn-resize.js @@ -0,0 +1,74 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.forEach +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.forEach(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, undefined, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.forEach(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, undefined, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/includes/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/includes/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..0b97d929e9a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/includes/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.includes +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.includes, + 'function', + 'implements TypedArray.prototype.includes' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.includes(0n); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.includes(0n); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the includes operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.includes(0n); + throw new Test262Error('includes completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/indexOf/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/indexOf/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..8a774ae4e2a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/indexOf/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.indexof +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.indexOf, + 'function', + 'implements TypedArray.prototype.indexOf' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.indexOf(0n); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.indexOf(0n); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the indexOf operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.indexOf(0n); + throw new Test262Error('indexOf completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/join/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/join/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..7b8d2a5db769 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/join/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.join +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.join, + 'function', + 'implements TypedArray.prototype.join' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.join(','); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.join(','); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the join operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.join(','); + throw new Test262Error('join completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/keys/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/keys/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..dcba1b298327 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/keys/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.keys +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.keys, + 'function', + 'implements TypedArray.prototype.keys' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.keys(); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.keys(); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the keys operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.keys(); + throw new Test262Error('keys completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/lastIndexOf/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/lastIndexOf/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..a5b1c107679b --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/lastIndexOf/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.lastindexof +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.lastIndexOf, + 'function', + 'implements TypedArray.prototype.lastIndexOf' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.lastIndexOf(0n); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.lastIndexOf(0n); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the lastIndexOf operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.lastIndexOf(0n); + throw new Test262Error('lastIndexOf completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/lastIndexOf/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/lastIndexOf/return-abrupt-from-this-out-of-bounds.js index 336f3588e5c1..819cd1d16e45 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/lastIndexOf/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/lastIndexOf/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.lastindexof description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-auto.js new file mode 100644 index 000000000000..54aa11b80581 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-auto.js @@ -0,0 +1,56 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-get-%typedarray%.prototype.length +description: | + reset to 0 if the underlying ArrayBuffer is resized beyond the boundary of + the dynamically-sized TypedArray instance +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, "function"); + +testWithBigIntTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE); + var expected = 3; + + assert.sameValue(array.length, expected, "initial value"); + + try { + ab.resize(BPE * 5); + expected = 4; + } catch (_) {} + + assert.sameValue(array.length, expected, "following grow"); + + try { + ab.resize(BPE * 3); + expected = 2; + } catch (_) {} + + assert.sameValue(array.length, expected, "following shrink (within bounds)"); + + try { + ab.resize(BPE); + expected = 0; + } catch (_) {} + + assert.sameValue(array.length, expected, "following shrink (on boundary)"); + + try { + ab.resize(0); + expected = 0; + } catch (_) {} + + assert.sameValue(array.length, expected, "following shrink (out of bounds)"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-fixed.js b/js/src/tests/test262/built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-fixed.js new file mode 100644 index 000000000000..0aada8a10b67 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-fixed.js @@ -0,0 +1,49 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-get-%typedarray%.prototype.length +description: | + reset to 0 if the underlying ArrayBuffer is resized beyond the boundary of + the fixed-sized TypedArray instance +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, "function"); + +testWithBigIntTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + assert.sameValue(array.length, 2, "initial value"); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + assert.sameValue(array.length, 2, "following grow"); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + assert.sameValue(array.length, 2, "following shrink (within bounds)"); + + var expected; + try { + ab.resize(BPE * 2); + expected = 0; + } catch (_) { + expected = 2; + } + + assert.sameValue(array.length, expected, "following shrink (out of bounds)"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/length/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/TypedArray/prototype/length/resizable-array-buffer-auto.js index e35bbdd3da2e..919ea0da4021 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/length/resizable-array-buffer-auto.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/length/resizable-array-buffer-auto.js @@ -43,6 +43,13 @@ testWithTypedArrayConstructors(function(TA) { expected = 0; } catch (_) {} + assert.sameValue(array.length, expected, "following shrink (on boundary)"); + + try { + ab.resize(0); + expected = 0; + } catch (_) {} + assert.sameValue(array.length, expected, "following shrink (out of bounds)"); }); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/map/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/map/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..5ccc7ca1b976 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/map/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.map +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.map, + 'function', + 'implements TypedArray.prototype.map' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.map(() => 0n); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.map(() => 0n); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the map operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.map(() => 0n); + throw new Test262Error('map completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/map/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/map/callbackfn-resize.js new file mode 100644 index 000000000000..deae7ab6d176 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/map/callbackfn-resize.js @@ -0,0 +1,81 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.map +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var NaNvalue = (TA === Float32Array || TA === Float64Array) ? NaN : 0; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, finalResult, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.map(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + finalResult = NaNvalue; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + finalResult = 2; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + + return index; + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.compareArray(result, [0, 1, finalResult], 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.map(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + + return index; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.compareArray(result, expectedIndices, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/map/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/map/return-abrupt-from-this-out-of-bounds.js index 75e025d625e6..266cbd53208f 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/map/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/map/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.map description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..0564ee92a950 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.reduce +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.reduce, + 'function', + 'implements TypedArray.prototype.reduce' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.reduce(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.reduce(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the reduce operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.reduce(() => {}); + throw new Test262Error('reduce completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/callbackfn-resize.js new file mode 100644 index 000000000000..a10f3adf0b8b --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/callbackfn-resize.js @@ -0,0 +1,78 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.reduce +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 3}); + var sample = new TA(buffer); + var finalNext, expectedPrevs, expectedNexts, expectedIndices, expectedArrays; + var prevs, nexts, indices, arrays, result; + + prevs = []; + nexts = []; + indices = []; + arrays = []; + result = sample.reduce(function(prev, next, index, array) { + if (prevs.length === 0) { + try { + buffer.resize(2 * BPE); + finalNext = undefined; + expectedPrevs = [262, 0]; + expectedNexts = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalNext = 0; + expectedPrevs = [262, 0, 1]; + expectedNexts = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + prevs.push(prev); + nexts.push(next); + indices.push(index); + arrays.push(array); + return index; + }, 262); + + assert.compareArray(prevs, [262, 0, 1], 'prevs (shrink)'); + assert.compareArray(nexts, [0, 0, finalNext], 'nexts (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, 2, 'result (shrink)'); + + prevs = []; + nexts = []; + indices = []; + arrays = []; + result = sample.reduce(function(prev, next, index, array) { + if (prevs.length === 0) { + try { + buffer.resize(3 * BPE); + } catch (_) {} + } + + prevs.push(prev); + nexts.push(next); + indices.push(index); + arrays.push(array); + return index; + }, 262); + + assert.compareArray(prevs, expectedPrevs, 'prevs (grow)'); + assert.compareArray(nexts, expectedNexts, 'nexts (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, expectedIndices[expectedIndices.length - 1], 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/return-abrupt-from-this-out-of-bounds.js index 69521b20a457..5466d1210f80 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/reduce/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.reduce description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..2f14282ea0cb --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.reduceright +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.reduceRight, + 'function', + 'implements TypedArray.prototype.reduceRight' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.reduceRight(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.reduceRight(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the reduceRight operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.reduceRight(() => {}); + throw new Test262Error('reduceRight completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/callbackfn-resize.js new file mode 100644 index 000000000000..910645a26301 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/callbackfn-resize.js @@ -0,0 +1,78 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.reduceright +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 3}); + var sample = new TA(buffer); + var secondNext, expectedPrevs, expectedNexts, expectedIndices, expectedArrays; + var prevs, nexts, indices, arrays, result; + + prevs = []; + nexts = []; + indices = []; + arrays = []; + result = sample.reduceRight(function(prev, next, index, array) { + if (prevs.length === 0) { + try { + buffer.resize(BPE); + secondNext = undefined; + expectedPrevs = [262]; + expectedNexts = [0]; + expectedIndices = [0]; + expectedArrays = [sample]; + } catch (_) { + secondNext = 0; + expectedPrevs = [262, 2, 1]; + expectedNexts = [0, 0, 0]; + expectedIndices = [2, 1, 0]; + expectedArrays = [sample, sample, sample]; + } + } + + prevs.push(prev); + nexts.push(next); + indices.push(index); + arrays.push(array); + return index; + }, 262); + + assert.compareArray(prevs, [262, 2, 1], 'prevs (shrink)'); + assert.compareArray(nexts, [0, secondNext, 0], 'nexts (shrink)'); + assert.compareArray(indices, [2, 1, 0], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, 0, 'result (shrink)'); + + prevs = []; + nexts = []; + indices = []; + arrays = []; + result = sample.reduceRight(function(prev, next, index, array) { + if (prevs.length === 0) { + try { + buffer.resize(3 * BPE); + } catch (_) {} + } + + prevs.push(prev); + nexts.push(next); + indices.push(index); + arrays.push(array); + return index; + }, 262); + + assert.compareArray(prevs, expectedPrevs, 'prevs (grow)'); + assert.compareArray(nexts, expectedNexts, 'nexts (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, expectedIndices[expectedIndices.length - 1], 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/return-abrupt-from-this-out-of-bounds.js index 31cebab33d77..29269658d772 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/reduceRight/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.reduceright description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/reverse/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/reverse/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..8b4a48b0e894 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/reverse/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.reverse +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.reverse, + 'function', + 'implements TypedArray.prototype.reverse' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.reverse(); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.reverse(); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the reverse operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.reverse(); + throw new Test262Error('reverse completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/set/BigInt/typedarray-arg-set-values-same-buffer-same-type-resized.js b/js/src/tests/test262/built-ins/TypedArray/prototype/set/BigInt/typedarray-arg-set-values-same-buffer-same-type-resized.js new file mode 100644 index 000000000000..64cb87810977 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/set/BigInt/typedarray-arg-set-values-same-buffer-same-type-resized.js @@ -0,0 +1,48 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.set-typedarray-offset +description: > + Set values from different instances using the same buffer and same + constructor when underlying ArrayBuffer has been resized +includes: [testBigIntTypedArray.js, compareArray.js] +features: [BigInt, TypedArray, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var source = new TA(ab); + var target = new TA(ab); + var expected = [10, 20, 30, 40]; + + source[0] = 10n; + source[1] = 20n; + source[2] = 30n; + source[3] = 40n; + + try { + ab.resize(BPE * 5); + expected = [10n, 20n, 30n, 40n, 0n]; + } catch (_) {} + + target.set(source); + assert(compareArray(target, expected), 'following grow'); + + try { + ab.resize(BPE * 3); + expected = [10n, 20n, 30n]; + } catch (_) {} + + target.set(source); + assert(compareArray(target, expected), 'following shrink'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/set/BigInt/typedarray-arg-target-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/set/BigInt/typedarray-arg-target-out-of-bounds.js new file mode 100644 index 000000000000..81abb8493652 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/set/BigInt/typedarray-arg-target-out-of-bounds.js @@ -0,0 +1,46 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.set-typedarray-offset +description: Error when target TypedArray fails boundary checks +includes: [testBigIntTypedArray.js] +features: [BigInt, TypedArray, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.set, + 'function', + 'implements TypedArray.prototype.set' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 4}); + var target = new TA(ab, 0, 4); + var source = new TA(new ArrayBuffer(BPE * 4)); + + var expectedError; + try { + ab.resize(BPE * 3); + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the reverse operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + target.set(source, 0); + throw new Test262Error('The `set` operation completed successfully.'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js b/js/src/tests/test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js new file mode 100644 index 000000000000..e67af3acb5b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js @@ -0,0 +1,38 @@ +// Copyright (C) 2022 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.set-array-offset +description: > + Does not throw if target TA is detached mid-iteration +includes: [testTypedArray.js, detachArrayBuffer.js] +features: [TypedArray] +---*/ + +testWithTypedArrayConstructors(function(TA) { + var sample = new TA([1, 2, 3]); + var obj = { + length: 3, + "0": 42 + }; + Object.defineProperty(obj, 1, { + get: function() { + $DETACHBUFFER(sample.buffer); + } + }); + let get2Called = false; + Object.defineProperty(obj, 2, { + get: function() { + get2Called = true; + return 2; + } + }); + + sample.set(obj); + + assert.sameValue(true, get2Called); + assert.sameValue(0, sample.byteLength); + assert.sameValue(0, sample.byteOffset); + assert.sameValue(0, sample.length); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js b/js/src/tests/test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js deleted file mode 100644 index 55d59b430980..000000000000 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.set-array-offset -description: > - Throws an error if buffer is detached before setting a value -info: | - 22.2.3.23.1 %TypedArray%.prototype.set (array [ , offset ] ) - - 1. Assert: array is any ECMAScript language value other than an Object with a - [[TypedArrayName]] internal slot. If it is such an Object, the definition in - 22.2.3.23.2 applies. - ... - 21. Repeat, while targetByteIndex < limit - a. Let Pk be ! ToString(k). - b. Let kNumber be ? ToNumber(? Get(src, Pk)). - c. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError exception. - d. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, - kNumber). - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA([1, 2, 3]); - var obj = { - length: 3, - "0": 42 - }; - Object.defineProperty(obj, 1, { - get: function() { - $DETACHBUFFER(sample.buffer); - } - }); - Object.defineProperty(obj, 2, { - get: function() { - throw new Test262Error("Should not get other values"); - } - }); - - assert.throws(TypeError, function() { - sample.set(obj); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/slice/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/slice/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..fc66f5270d59 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/slice/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.slice +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.slice, + 'function', + 'implements TypedArray.prototype.slice' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.slice(0); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.slice(0); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the slice operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.slice(0); + throw new Test262Error('slice completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/slice/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/slice/return-abrupt-from-this-out-of-bounds.js index 21ec736aa4a8..f2a0fa7b94b6 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/slice/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/slice/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.slice description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/some/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/some/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..193e8a29015d --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/some/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.some +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.some, + 'function', + 'implements TypedArray.prototype.some' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.some(() => {}); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.some(() => {}); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the some operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.some(() => {}); + throw new Test262Error('some completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/some/callbackfn-resize.js b/js/src/tests/test262/built-ins/TypedArray/prototype/some/callbackfn-resize.js new file mode 100644 index 000000000000..71389fb57a25 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/some/callbackfn-resize.js @@ -0,0 +1,76 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.some +description: Instance buffer can be resized during iteration +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, resizable-arraybuffer] +---*/ + +// If the host chooses to throw as allowed by the specification, the observed +// behavior will be identical to the case where `ArrayBuffer.prototype.resize` +// has not been implemented. The following assertion prevents this test from +// passing in runtimes which have not implemented the method. +assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); + +testWithTypedArrayConstructors(function(TA) { + var BPE = TA.BYTES_PER_ELEMENT; + var buffer = new ArrayBuffer(BPE * 3, {maxByteLength: BPE * 4}); + var sample = new TA(buffer); + var finalElement, expectedElements, expectedIndices, expectedArrays; + var elements, indices, arrays, result; + + elements = []; + indices = []; + arrays = []; + result = sample.some(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(2 * BPE); + finalElement = undefined; + expectedElements = [0, 0]; + expectedIndices = [0, 1]; + expectedArrays = [sample, sample]; + } catch (_) { + finalElement = 0; + expectedElements = [0, 0, 0]; + expectedIndices = [0, 1, 2]; + expectedArrays = [sample, sample, sample]; + } + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, [0, 0, finalElement], 'elements (shrink)'); + assert.compareArray(indices, [0, 1, 2], 'indices (shrink)'); + assert.compareArray(arrays, [sample, sample, sample], 'arrays (shrink)'); + assert.sameValue(result, false, 'result (shrink)'); + + elements = []; + indices = []; + arrays = []; + result = sample.some(function(element, index, array) { + if (elements.length === 0) { + try { + buffer.resize(4 * BPE); + } catch (_) {} + } + + elements.push(element); + indices.push(index); + arrays.push(array); + return false; + }); + + assert.compareArray(elements, expectedElements, 'elements (grow)'); + assert.compareArray(indices, expectedIndices, 'indices (grow)'); + assert.compareArray(arrays, expectedArrays, 'arrays (grow)'); + assert.sameValue(result, false, 'result (grow)'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/some/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/some/return-abrupt-from-this-out-of-bounds.js index b1b1576abd39..39a555e728b1 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/some/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/some/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.some description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn.js b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn.js deleted file mode 100644 index b2524d406d0a..000000000000 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn.js +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.sort -description: Throws a TypeError if comparefn detaches the object buffer -info: | - 22.2.3.26 %TypedArray%.prototype.sort ( comparefn ) - - When the TypedArray SortCompare abstract operation is called with two - arguments x and y, the following steps are taken: - - ... - 2. If the argument comparefn is not undefined, then - a. Let v be ? Call(comparefn, undefined, « x, y »). - b. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - ... - ... -includes: [testBigIntTypedArray.js, detachArrayBuffer.js] -features: [BigInt, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(4); - var calls = 0; - var comparefn = function() { - if (calls > 0) { - throw new Test262Error(); - } - calls++; - $DETACHBUFFER(sample.buffer); - }; - - assert.throws(TypeError, function() { - sample.sort(comparefn); - }); - - assert.sameValue(calls, 1); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..dee08240ed76 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.sort +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.sort, + 'function', + 'implements TypedArray.prototype.sort' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.sort(); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.sort(); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the sort operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.sort(); + throw new Test262Error('sort completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn-coerce.js b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn-coerce.js deleted file mode 100644 index 6022797c918b..000000000000 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn-coerce.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2020 Google. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.sort -description: > - SECURITY Throws a TypeError if coercion of the comparefn return value - detaches the object buffer -info: | - 22.2.3.26 %TypedArray%.prototype.sort ( comparefn ) - - When the TypedArray SortCompare abstract operation is called with two - arguments x and y, the following steps are taken: - - ... - 2. If the argument comparefn is not undefined, then - a. Let v be ? ToNumber(? Call(comparefn, undefined, « x, y »)). - b. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - ... - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(4); - var calls = 0; - var convertfn = function(){ - $DETACHBUFFER(sample.buffer); - return 1; - } - var comparefn = function() { - if (calls > 0) { - throw new Test262Error(); - } - calls++; - return {valueOf : convertfn} - }; - - assert.throws(TypeError, function() { - sample.sort(comparefn); - }, "Coercion that detaches buffer should throw TypeError"); - - assert.sameValue(calls, 1); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js deleted file mode 100644 index 98ec6d320168..000000000000 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.sort -description: Throws a TypeError if comparefn detaches the object buffer -info: | - 22.2.3.26 %TypedArray%.prototype.sort ( comparefn ) - - When the TypedArray SortCompare abstract operation is called with two - arguments x and y, the following steps are taken: - - ... - 2. If the argument comparefn is not undefined, then - a. Let v be ? Call(comparefn, undefined, « x, y »). - b. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - ... - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(4); - var calls = 0; - var comparefn = function() { - if (calls > 0) { - throw new Test262Error(); - } - calls++; - $DETACHBUFFER(sample.buffer); - }; - - assert.throws(TypeError, function() { - sample.sort(comparefn); - }); - - assert.sameValue(calls, 1); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/return-abrupt-from-this-out-of-bounds.js index a271eaa84267..aa4f91883b07 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.sort description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/sort-tonumber.js b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/sort-tonumber.js index 9cf29a304ecb..dcc99bc87c81 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/sort/sort-tonumber.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/sort/sort-tonumber.js @@ -21,16 +21,12 @@ testWithTypedArrayConstructors(function(TA) { var ab = ta.buffer; var called = false; - assert.throws(TypeError, function() { - ta.sort(function(a, b) { - // IsDetachedBuffer is checked right after calling comparefn. - // So, detach the ArrayBuffer to cause sort to throw, to make sure we're actually calling ToNumber immediately (as spec'd) - // (a possible bug is to wait until the result is inspected to call ToNumber, rather than immediately) - $DETACHBUFFER(ab); - return { - [Symbol.toPrimitive]() { called = true; } - }; - }); + ta.sort(function(a, b) { + // Detaching the buffer does not cause sort to throw. + $DETACHBUFFER(ab); + return { + [Symbol.toPrimitive]() { called = true; } + }; }); assert.sameValue(true, called); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/toLocaleString/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/toLocaleString/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..bbd84a46a971 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/toLocaleString/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.tolocalestring +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.toLocaleString, + 'function', + 'implements TypedArray.prototype.toLocaleString' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.toLocaleString(); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.toLocaleString(); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the toLocaleString operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.toLocaleString(); + throw new Test262Error('toLocaleString completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-this-out-of-bounds.js index 559f372a3a4f..04a4238da7df 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.tolocalestring description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/values/BigInt/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/values/BigInt/return-abrupt-from-this-out-of-bounds.js new file mode 100644 index 000000000000..adaab3ae2be5 --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/values/BigInt/return-abrupt-from-this-out-of-bounds.js @@ -0,0 +1,62 @@ +// |reftest| skip -- resizable-arraybuffer is not supported +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.values +description: Return abrupt when "this" value fails buffer boundary checks +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, BigInt, TypedArray, arrow-function, resizable-arraybuffer] +---*/ + +assert.sameValue( + typeof TypedArray.prototype.values, + 'function', + 'implements TypedArray.prototype.values' +); + +assert.sameValue( + typeof ArrayBuffer.prototype.resize, + 'function', + 'implements ArrayBuffer.prototype.resize' +); + +testWithBigIntTypedArrayConstructors(TA => { + var BPE = TA.BYTES_PER_ELEMENT; + var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); + var array = new TA(ab, BPE, 2); + + try { + ab.resize(BPE * 5); + } catch (_) {} + + // no error following grow: + array.values(); + + try { + ab.resize(BPE * 3); + } catch (_) {} + + // no error following shrink (within bounds): + array.values(); + + var expectedError; + try { + ab.resize(BPE * 2); + // If the preceding "resize" operation is successful, the typed array will + // be out out of bounds, so the subsequent prototype method should produce + // a TypeError due to the semantics of ValidateTypedArray. + expectedError = TypeError; + } catch (_) { + // The host is permitted to fail any "resize" operation at its own + // discretion. If that occurs, the values operation should complete + // successfully. + expectedError = Test262Error; + } + + assert.throws(expectedError, () => { + array.values(); + throw new Test262Error('values completed successfully'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArray/prototype/values/return-abrupt-from-this-out-of-bounds.js b/js/src/tests/test262/built-ins/TypedArray/prototype/values/return-abrupt-from-this-out-of-bounds.js index 1257a8d42b64..3c6a3decc8fe 100644 --- a/js/src/tests/test262/built-ins/TypedArray/prototype/values/return-abrupt-from-this-out-of-bounds.js +++ b/js/src/tests/test262/built-ins/TypedArray/prototype/values/return-abrupt-from-this-out-of-bounds.js @@ -5,7 +5,7 @@ esid: sec-%typedarray%.prototype.values description: Return abrupt when "this" value fails buffer boundary checks includes: [testTypedArray.js] -features: [TypedArray, resizable-arraybuffer] +features: [ArrayBuffer, TypedArray, arrow-function, resizable-arraybuffer] ---*/ assert.sameValue( diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-different-type.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-different-type.js deleted file mode 100644 index 57413bcd1df8..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-different-type.js +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-typedarray-typedarray -description: > - When a TypedArray is created from another TypedArray with a different element-type - and SpeciesConstructor detaches the source buffer, AllocateArrayBuffer is still - executed. -info: | - 22.2.4.3 TypedArray ( typedArray ) - - ... - 16. If IsSharedArrayBuffer(srcData) is false, then - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - 18. If SameValue(elementType, srcType) is true, then - ... - 19. Else, - a. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - b. If IsDetachedBuffer(srcData) is true, throw a TypeError exception. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBufferPrototype%", - « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). - ... -includes: [testBigIntTypedArray.js, detachArrayBuffer.js] -features: [BigInt, TypedArray, Symbol.species] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var speciesCallCount = 0; - var bufferConstructor = Object.defineProperty({}, Symbol.species, { - get: function() { - speciesCallCount += 1; - $DETACHBUFFER(ta.buffer); - return speciesConstructor; - } - }); - - var prototypeCallCount = 0; - var speciesConstructor = Object.defineProperty(function(){}.bind(), "prototype", { - get: function() { - prototypeCallCount += 1; - return null; - } - }); - - var ta = new TA(0); - ta.buffer.constructor = bufferConstructor; - - assert.throws(TypeError, function() { - var targetType = TA !== BigInt64Array ? BigInt64Array : BigUint64Array; - new targetType(ta); - }, "TypeError thrown for detached source buffer"); - - assert.sameValue(speciesCallCount, 1, "@@species getter called once"); - assert.sameValue(prototypeCallCount, 1, "prototype getter called once"); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-same-type.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-same-type.js deleted file mode 100644 index e289acb11cfd..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-same-type.js +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-typedarray-typedarray -description: > - When a TypedArray is created from another TypedArray with the same element-type - and SpeciesConstructor detaches the source buffer, AllocateArrayBuffer is still - executed. -info: | - 22.2.4.3 TypedArray ( typedArray ) - - ... - 16. If IsSharedArrayBuffer(srcData) is false, then - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - 18. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset, byteLength, bufferConstructor). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor ) - - ... - 3. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, srcLength). - 4. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBufferPrototype%", - « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). - ... -includes: [testBigIntTypedArray.js, detachArrayBuffer.js] -features: [BigInt, TypedArray, Symbol.species] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var speciesCallCount = 0; - var bufferConstructor = Object.defineProperty({}, Symbol.species, { - get: function() { - speciesCallCount += 1; - $DETACHBUFFER(ta.buffer); - return speciesConstructor; - } - }); - - var prototypeCallCount = 0; - var speciesConstructor = Object.defineProperty(function(){}.bind(), "prototype", { - get: function() { - prototypeCallCount += 1; - return null; - } - }); - - var ta = new TA(0); - ta.buffer.constructor = bufferConstructor; - - assert.throws(TypeError, function() { - new TA(ta); - }, "TypeError thrown for detached source buffer"); - - assert.sameValue(speciesCallCount, 1, "@@species getter called once"); - assert.sameValue(prototypeCallCount, 1, "prototype getter called once"); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-access-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-access-throws.js deleted file mode 100644 index 02dc3aae25dc..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-access-throws.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from getting typedArray argument's buffer.constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var OtherCtor = TA === BigInt64Array ? BigUint64Array : BigInt64Array; - var sample = new OtherCtor(); - - Object.defineProperty(sample.buffer, "constructor", { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js deleted file mode 100644 index 3b5fa8a24125..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Derive the ArrayBuffer prototype from the realm of the species constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 9.1.14 GetPrototypeFromConstructor - - ... - 3. Let proto be ? Get(constructor, "prototype"). - 4. If Type(proto) is not Object, then - a. Let realm be ? GetFunctionRealm(constructor). - b. Let proto be realm's intrinsic object named intrinsicDefaultProto. - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, cross-realm, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); -var other = $262.createRealm().global; -var C = new other.Function(); -C.prototype = null; - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = C; - - var typedArray = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), other.ArrayBuffer.prototype - ); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species.js deleted file mode 100644 index 3e4a8021bf68..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species.js +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - var ctor = {}; - var called = 0; - var custom = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() { - called++; - }; - - ctor[Symbol.species].prototype = custom; - - var typedArray = new TA(sample); - assert.sameValue(Object.getPrototypeOf(typedArray.buffer), custom); - assert.sameValue(called, 0); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js deleted file mode 100644 index a3eaca4ecd70..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from typedArray argument's buffer.constructor's value -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... - 4. If Type(C) is not Object, throw a TypeError exception. - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - - sample.buffer.constructor = 1; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = true; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = ""; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = null; - assert.throws(TypeError, function() { - new TA(sample); - }); - - var s = Symbol("1"); - sample.buffer.constructor = s; - assert.throws(TypeError, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js deleted file mode 100644 index 4f3d4260164e..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from getting typedArray argument's buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - var ctor = {}; - - sample.buffer.constructor = ctor; - Object.defineProperty(ctor, Symbol.species, { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js deleted file mode 100644 index 6284a19af31b..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - 8. Throw a TypeError exception. -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -var ctor = function() { - throw new Test262Error(); -}; -var m = { m() {} }.m; -ctor[Symbol.species] = m; - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - - sample.buffer.constructor = ctor; - - assert.throws(TypeError, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js deleted file mode 100644 index 3b79a001ac11..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - ... - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, - "%ArrayBufferPrototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] » ) - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - var ctor = {}; - var called = 0; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() {called++;}.bind(null); - Object.defineProperty(ctor[Symbol.species], "prototype", { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); - assert.sameValue(called, 0); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-access-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-access-throws.js deleted file mode 100644 index 6c8f0657d92b..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-access-throws.js +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from getting typedArray argument's buffer.constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - Object.defineProperty(sample.buffer, "constructor", { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js deleted file mode 100644 index 59c313a9ff83..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Derive the ArrayBuffer prototype from the realm of the species constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... - - 9.1.14 GetPrototypeFromConstructor - - ... - 3. Let proto be ? Get(constructor, "prototype"). - 4. If Type(proto) is not Object, then - a. Let realm be ? GetFunctionRealm(constructor). - b. Let proto be realm's intrinsic object named intrinsicDefaultProto. - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, cross-realm, Symbol.species, TypedArray] ----*/ - -var other = $262.createRealm().global; -var C = new other.Function(); -C.prototype = null; - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = C; - - var typedArray = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), other.ArrayBuffer.prototype - ); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom.js deleted file mode 100644 index f0a1f41611fb..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom.js +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - var called = 0; - var custom = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() { - called++; - }; - - ctor[Symbol.species].prototype = custom; - - var typedArray = new TA(sample); - assert.sameValue(Object.getPrototypeOf(typedArray.buffer), custom); - assert.sameValue(called, 0); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js deleted file mode 100644 index 335d7485696e..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - 8. Throw a TypeError exception. -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - var m = { m() {} }; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = m; - - assert.throws(TypeError, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js deleted file mode 100644 index 5f0c6bb8cc8a..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - ... - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, - "%ArrayBufferPrototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] » ) - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function(){}.bind(null); - Object.defineProperty(ctor[Symbol.species], "prototype", { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-throws.js deleted file mode 100644 index 7581e5be3800..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-throws.js +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from getting typedArray argument's buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - Object.defineProperty(ctor, Symbol.species, { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js deleted file mode 100644 index d0b3c5830c83..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from typedArray argument's buffer.constructor's value -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... - 4. If Type(C) is not Object, throw a TypeError exception. - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - - sample.buffer.constructor = 1; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = true; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = ''; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = null; - assert.throws(TypeError, function() { - new TA(sample); - }); - - var s = Symbol('1'); - sample.buffer.constructor = s; - assert.throws(TypeError, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/shell.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/shell.js index 55abcab93595..1157ee53187d 100644 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/shell.js +++ b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/shell.js @@ -1,22 +1,4 @@ // GENERATED, DO NOT EDIT -// file: detachArrayBuffer.js -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -description: | - A function used in the process of asserting correctness of TypedArray objects. - - $262.detachArrayBuffer is defined by a host. -defines: [$DETACHBUFFER] ----*/ - -function $DETACHBUFFER(buffer) { - if (!$262 || typeof $262.detachArrayBuffer !== "function") { - throw new Test262Error("No method available to detach an ArrayBuffer"); - } - $262.detachArrayBuffer(buffer); -} - // file: testBigIntTypedArray.js // Copyright (C) 2015 André Bargull. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/no-species.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/no-species.js new file mode 100644 index 000000000000..c13f6bb416df --- /dev/null +++ b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/no-species.js @@ -0,0 +1,32 @@ +// Copyright (C) 2022 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Creating TypedArray from other TypedArrays doesn't look up Symbol.species. +features: [Symbol.species] +---*/ + +let throwOnGrossBufferConstruction = false; + +class GrossBuffer extends ArrayBuffer { + constructor() { + super(...arguments); + if (throwOnGrossBufferConstruction) { + throw new Test262Error("unreachable"); + } + } + static get [Symbol.species]() { + throw new Test262Error("unreachable"); + } +} + +let grossBuf = new GrossBuffer(1024); +throwOnGrossBufferConstruction = true; +let grossTA = new Uint8Array(grossBuf); +let mysteryTA = new Int8Array(grossTA); + +assert.sameValue(mysteryTA.buffer.__proto__, ArrayBuffer.prototype); +assert.sameValue(mysteryTA.buffer.constructor, ArrayBuffer); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js deleted file mode 100644 index 52ca5fd5d2cc..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-typedarray-typedarray -description: > - When a TypedArray is created from another TypedArray with a different element-type - and SpeciesConstructor detaches the source buffer, AllocateArrayBuffer is still - executed. -info: | - 22.2.4.3 TypedArray ( typedArray ) - - ... - 16. If IsSharedArrayBuffer(srcData) is false, then - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - 18. If SameValue(elementType, srcType) is true, then - ... - 19. Else, - a. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - b. If IsDetachedBuffer(srcData) is true, throw a TypeError exception. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBufferPrototype%", - « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray, Symbol.species] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var speciesCallCount = 0; - var bufferConstructor = Object.defineProperty({}, Symbol.species, { - get: function() { - speciesCallCount += 1; - $DETACHBUFFER(ta.buffer); - return speciesConstructor; - } - }); - - var prototypeCallCount = 0; - var speciesConstructor = Object.defineProperty(function(){}.bind(), "prototype", { - get: function() { - prototypeCallCount += 1; - return null; - } - }); - - var ta = new TA(0); - ta.buffer.constructor = bufferConstructor; - - assert.throws(TypeError, function() { - var targetType = TA !== Int32Array ? Int32Array : Uint32Array; - new targetType(ta); - }, "TypeError thrown for detached source buffer"); - - assert.sameValue(speciesCallCount, 1, "@@species getter called once"); - assert.sameValue(prototypeCallCount, 1, "prototype getter called once"); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js deleted file mode 100644 index f12a977abfbe..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-typedarray-typedarray -description: > - When a TypedArray is created from another TypedArray with the same element-type - and SpeciesConstructor detaches the source buffer, AllocateArrayBuffer is still - executed. -info: | - 22.2.4.3 TypedArray ( typedArray ) - - ... - 16. If IsSharedArrayBuffer(srcData) is false, then - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - 18. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset, byteLength, bufferConstructor). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor ) - - ... - 3. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, srcLength). - 4. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBufferPrototype%", - « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray, Symbol.species] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var speciesCallCount = 0; - var bufferConstructor = Object.defineProperty({}, Symbol.species, { - get: function() { - speciesCallCount += 1; - $DETACHBUFFER(ta.buffer); - return speciesConstructor; - } - }); - - var prototypeCallCount = 0; - var speciesConstructor = Object.defineProperty(function(){}.bind(), "prototype", { - get: function() { - prototypeCallCount += 1; - return null; - } - }); - - var ta = new TA(0); - ta.buffer.constructor = bufferConstructor; - - assert.throws(TypeError, function() { - new TA(ta); - }, "TypeError thrown for detached source buffer"); - - assert.sameValue(speciesCallCount, 1, "@@species getter called once"); - assert.sameValue(prototypeCallCount, 1, "prototype getter called once"); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js deleted file mode 100644 index 30800586d36b..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from getting typedArray argument's buffer.constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... -includes: [testTypedArray.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var OtherCtor = TA === Int8Array ? Int16Array : Int8Array; - var sample = new OtherCtor(); - - Object.defineProperty(sample.buffer, "constructor", { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js deleted file mode 100644 index 9747eb650a62..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Derive the ArrayBuffer prototype from the realm of the species constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 9.1.14 GetPrototypeFromConstructor - - ... - 3. Let proto be ? Get(constructor, "prototype"). - 4. If Type(proto) is not Object, then - a. Let realm be ? GetFunctionRealm(constructor). - b. Let proto be realm's intrinsic object named intrinsicDefaultProto. - ... -includes: [testTypedArray.js] -features: [cross-realm, Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); -var other = $262.createRealm().global; -var C = new other.Function(); -C.prototype = null; - - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = C; - - var typedArray = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), other.ArrayBuffer.prototype - ); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js deleted file mode 100644 index f977d715a3c9..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - var ctor = {}; - var called = 0; - var custom = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() { - called++; - }; - - ctor[Symbol.species].prototype = custom; - - var typedArray = new TA(sample); - assert.sameValue(Object.getPrototypeOf(typedArray.buffer), custom); - assert.sameValue(called, 0); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js deleted file mode 100644 index fea661afcfb8..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from typedArray argument's buffer.constructor's value -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... - 4. If Type(C) is not Object, throw a TypeError exception. - ... -includes: [testTypedArray.js] -features: [Symbol, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - - sample.buffer.constructor = 1; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = true; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = ""; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = null; - assert.throws(TypeError, function() { - new TA(sample); - }); - - var s = Symbol("1"); - sample.buffer.constructor = s; - assert.throws(TypeError, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js deleted file mode 100644 index a3fb4b2f4a23..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from getting typedArray argument's buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - var ctor = {}; - - sample.buffer.constructor = ctor; - Object.defineProperty(ctor, Symbol.species, { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js deleted file mode 100644 index 3aa44b2fa84b..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - 8. Throw a TypeError exception. -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -var ctor = function() { - throw new Test262Error(); -}; -var m = { m() {} }.m; -ctor[Symbol.species] = m; - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - - sample.buffer.constructor = ctor; - - assert.throws(TypeError, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-null.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-null.js deleted file mode 100644 index 2daaf495e6ae..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-null.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on null buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var OtherCtor = TA === Int8Array ? Int16Array : Int8Array; - var sample = new OtherCtor(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = null; - var typedArray = new TA(sample); - - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), - ArrayBuffer.prototype, - "buffer ctor is not called when species is null" - ); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js deleted file mode 100644 index 2e9b70cf66bc..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - ... - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, - "%ArrayBufferPrototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] » ) - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - var ctor = {}; - var called = 0; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() {called++;}.bind(null); - Object.defineProperty(ctor[Symbol.species], "prototype", { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); - assert.sameValue(called, 0); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-undefined.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-undefined.js deleted file mode 100644 index 3bffe47842bc..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-undefined.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var OtherCtor = TA === Int8Array ? Int16Array : Int8Array; - var sample = new OtherCtor(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = undefined; - var a = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(a.buffer), - ArrayBuffer.prototype, - "buffer ctor is not called when species is undefined" - ); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type.js deleted file mode 100644 index 6327254cffbf..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type.js +++ /dev/null @@ -1,83 +0,0 @@ -// |reftest| skip -- resizable-arraybuffer is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Error when a TypedArray is created from another TypedArray with a different - element-type and SpeciesConstructor causes the "source" array to go - out-of-bounds. -includes: [testTypedArray.js, compareArray.js] -features: [TypedArray, Symbol.species, resizable-arraybuffer] ----*/ - -// If the host chooses to throw as allowed by the specification, the observed -// behavior will be identical to the case where `ArrayBuffer.prototype.resize` -// has not been implemented. The following assertion prevents this test from -// passing in runtimes which have not implemented the method. -assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); - -testWithTypedArrayConstructors(function(TA) { - var BPE = TA.BYTES_PER_ELEMENT; - var TargetCtor = TA !== Int32Array ? Int32Array : Uint32Array; - var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); - var speciesConstructor = Object.defineProperty(function(){}.bind(), 'prototype', { - get: function() { - return null; - } - }); - var onGetSpecies; - ab.constructor = Object.defineProperty({}, Symbol.species, { - get: function() { - onGetSpecies(); - return speciesConstructor; - } - }); - var source = new TA(ab, BPE); - var expected = [10, 20, 30]; - - source[0] = 10; - source[1] = 20; - source[2] = 30; - - onGetSpecies = function() { - try { - ab.resize(BPE * 5); - expected = [10, 20, 30, 0]; - } catch (_) {} - }; - - assert(compareArray(new TargetCtor(source), expected), 'following grow'); - - onGetSpecies = function() { - try { - ab.resize(BPE * 3); - expected = [10, 20]; - } catch (_) {} - }; - - assert(compareArray(new TargetCtor(source), expected), 'following shrink (within bounds)'); - - // `assert.throws` cannot be used in this case because the expected error - // is derived only after the constructor is invoked. - var expectedError; - var actualError; - onGetSpecies = function() { - try { - ab.resize(BPE); - expectedError = TypeError; - } catch (_) { - expectedError = Test262Error; - } - }; - try { - new TargetCtor(source); - throw new Test262Error('the operation completed successfully'); - } catch (caught) { - actualError = caught; - } - - assert.sameValue(actualError.constructor, expectedError); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type.js deleted file mode 100644 index e4f5e7419b2d..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type.js +++ /dev/null @@ -1,83 +0,0 @@ -// |reftest| skip -- resizable-arraybuffer is not supported -// Copyright (C) 2021 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Error when a TypedArray is created from another TypedArray with the same - element-type and SpeciesConstructor causes the "source" array to go - out-of-bounds. -includes: [testTypedArray.js, compareArray.js] -features: [TypedArray, Symbol.species, resizable-arraybuffer] ----*/ - -// If the host chooses to throw as allowed by the specification, the observed -// behavior will be identical to the case where `ArrayBuffer.prototype.resize` -// has not been implemented. The following assertion prevents this test from -// passing in runtimes which have not implemented the method. -assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); - -testWithTypedArrayConstructors(function(TA) { - var BPE = TA.BYTES_PER_ELEMENT; - var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); - var speciesConstructor = Object.defineProperty(function(){}.bind(), 'prototype', { - get: function() { - return null; - } - }); - var onGetSpecies; - ab.constructor = Object.defineProperty({}, Symbol.species, { - get: function() { - onGetSpecies(); - return speciesConstructor; - } - }); - var source = new TA(ab, BPE); - var expected = [10, 20, 30]; - - source[0] = 10; - source[1] = 20; - source[2] = 30; - - onGetSpecies = function() { - try { - ab.resize(BPE * 5); - expected = [10, 20, 30, 0]; - } catch (_) {} - }; - - assert.sameValue((new TA(source)).join(','), expected.join(',')); - assert(compareArray(new TA(source), expected), 'following grow'); - - onGetSpecies = function() { - try { - ab.resize(BPE * 3); - expected = [10, 20]; - } catch (_) {} - }; - - assert(compareArray(new TA(source), expected), 'following shrink (within bounds)'); - - // `assert.throws` cannot be used in this case because the expected error - // is derived only after the constructor is invoked. - var expectedError; - var actualError; - onGetSpecies = function() { - try { - ab.resize(BPE); - expectedError = TypeError; - } catch (_) { - expectedError = Test262Error; - } - }; - try { - new TA(source); - throw new Test262Error('the operation completed successfully'); - } catch (caught) { - actualError = caught; - } - - assert.sameValue(actualError.constructor, expectedError); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js deleted file mode 100644 index f5f9b185cbf1..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from getting typedArray argument's buffer.constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... -includes: [testTypedArray.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - Object.defineProperty(sample.buffer, "constructor", { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js deleted file mode 100644 index e7b26cc9df0e..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Derive the ArrayBuffer prototype from the realm of the species constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... - - 9.1.14 GetPrototypeFromConstructor - - ... - 3. Let proto be ? Get(constructor, "prototype"). - 4. If Type(proto) is not Object, then - a. Let realm be ? GetFunctionRealm(constructor). - b. Let proto be realm's intrinsic object named intrinsicDefaultProto. - ... -includes: [testTypedArray.js] -features: [cross-realm, Symbol.species, TypedArray] ----*/ - -var other = $262.createRealm().global; -var C = new other.Function(); -C.prototype = null; - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = C; - - var typedArray = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), other.ArrayBuffer.prototype - ); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js deleted file mode 100644 index 099c755ed8b3..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - var called = 0; - var custom = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() { - called++; - }; - - ctor[Symbol.species].prototype = custom; - - var typedArray = new TA(sample); - assert.sameValue(Object.getPrototypeOf(typedArray.buffer), custom); - assert.sameValue(called, 0); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js deleted file mode 100644 index 6d84684bef01..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - 8. Throw a TypeError exception. -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - var m = { m() {} }; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = m; - - assert.throws(TypeError, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js deleted file mode 100644 index 39384f499d25..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - ... - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, - "%ArrayBufferPrototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] » ) - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function(){}.bind(null); - Object.defineProperty(ctor[Symbol.species], "prototype", { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js deleted file mode 100644 index 169f4de9122d..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from getting typedArray argument's buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - Object.defineProperty(ctor, Symbol.species, { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js deleted file mode 100644 index 28e86db03a33..000000000000 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from typedArray argument's buffer.constructor's value -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... - 4. If Type(C) is not Object, throw a TypeError exception. - ... -includes: [testTypedArray.js] -features: [Symbol, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - - sample.buffer.constructor = 1; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = true; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = ''; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = null; - assert.throws(TypeError, function() { - new TA(sample); - }); - - var s = Symbol('1'); - sample.buffer.constructor = s; - assert.throws(TypeError, function() { - new TA(sample); - }); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/shell.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/shell.js index 55abcab93595..1157ee53187d 100644 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/shell.js +++ b/js/src/tests/test262/built-ins/TypedArrayConstructors/ctors/typedarray-arg/shell.js @@ -1,22 +1,4 @@ // GENERATED, DO NOT EDIT -// file: detachArrayBuffer.js -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -description: | - A function used in the process of asserting correctness of TypedArray objects. - - $262.detachArrayBuffer is defined by a host. -defines: [$DETACHBUFFER] ----*/ - -function $DETACHBUFFER(buffer) { - if (!$262 || typeof $262.detachArrayBuffer !== "function") { - throw new Test262Error("No method available to detach an ArrayBuffer"); - } - $262.detachArrayBuffer(buffer); -} - // file: testBigIntTypedArray.js // Copyright (C) 2015 André Bargull. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/internals/HasProperty/resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/internals/HasProperty/resizable-array-buffer-auto.js index e8d759c8e811..223834ba20f8 100644 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/internals/HasProperty/resizable-array-buffer-auto.js +++ b/js/src/tests/test262/built-ins/TypedArrayConstructors/internals/HasProperty/resizable-array-buffer-auto.js @@ -51,6 +51,13 @@ testWithTypedArrayConstructors(function(TA) { expected = "false,false,false,false,false"; } catch (_) {} + assert.sameValue(inspect(array), expected, "following shrink (on boundary)"); + + try { + ab.resize(0); + expected = "false,false,false,false,false"; + } catch (_) {} + assert.sameValue(inspect(array), expected, "following shrink (out of bounds)"); }); diff --git a/js/src/tests/test262/built-ins/TypedArrayConstructors/internals/OwnPropertyKeys/integer-indexes-resizable-array-buffer-auto.js b/js/src/tests/test262/built-ins/TypedArrayConstructors/internals/OwnPropertyKeys/integer-indexes-resizable-array-buffer-auto.js index 8aa6df3d39ef..a2ae71b1717c 100644 --- a/js/src/tests/test262/built-ins/TypedArrayConstructors/internals/OwnPropertyKeys/integer-indexes-resizable-array-buffer-auto.js +++ b/js/src/tests/test262/built-ins/TypedArrayConstructors/internals/OwnPropertyKeys/integer-indexes-resizable-array-buffer-auto.js @@ -53,6 +53,15 @@ testWithTypedArrayConstructors(function(TA) { expected = ""; } catch (_) {} + assert.sameValue( + Reflect.ownKeys(array).join(","), expected, "following shrink (on boundary)" + ); + + try { + ab.resize(0); + expected = ""; + } catch (_) {} + assert.sameValue( Reflect.ownKeys(array).join(","), expected, "following shrink (out of bounds)" ); diff --git a/js/src/tests/test262/built-ins/WeakRef/prototype/deref/gc-cleanup-not-prevented-with-wr-deref.js b/js/src/tests/test262/built-ins/WeakRef/prototype/deref/gc-cleanup-not-prevented-with-wr-deref.js index f4bb7dfb3f9b..eacbad0129b6 100644 --- a/js/src/tests/test262/built-ins/WeakRef/prototype/deref/gc-cleanup-not-prevented-with-wr-deref.js +++ b/js/src/tests/test262/built-ins/WeakRef/prototype/deref/gc-cleanup-not-prevented-with-wr-deref.js @@ -14,7 +14,7 @@ info: | a. Perform ! KeepDuringJob(target). b. Return target. 6. Return undefined. -features: [FinalizationRegistry.prototype.cleanupSome, cleanupSome, WeakRef, host-gc-required] +features: [FinalizationRegistry.prototype.cleanupSome, WeakRef, host-gc-required] includes: [async-gc.js] flags: [async, non-deterministic] ---*/ diff --git a/js/src/tests/test262/built-ins/WeakRef/prototype/deref/shell.js b/js/src/tests/test262/built-ins/WeakRef/prototype/deref/shell.js index e48630f9c43f..085d0a65252a 100644 --- a/js/src/tests/test262/built-ins/WeakRef/prototype/deref/shell.js +++ b/js/src/tests/test262/built-ins/WeakRef/prototype/deref/shell.js @@ -5,7 +5,7 @@ /*--- description: > Collection of functions used to capture references cleanup from garbage collectors -features: [cleanupSome, FinalizationRegistry, Symbol, async-functions] +features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, Symbol, async-functions] flags: [non-deterministic] defines: [asyncGC, asyncGCDeref, resolveAsyncGC] ---*/ diff --git a/js/src/tests/test262/built-ins/decodeURI/S15.1.3.1_A2.1_T1.js b/js/src/tests/test262/built-ins/decodeURI/S15.1.3.1_A2.1_T1.js index 8e08fae73f94..bb1ebebae6ad 100644 --- a/js/src/tests/test262/built-ins/decodeURI/S15.1.3.1_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/decodeURI/S15.1.3.1_A2.1_T1.js @@ -8,28 +8,18 @@ description: Complex tests includes: [decimalToHexString.js] ---*/ -//CHECK -var errorCount = 0; -var count = 0; for (var indexI = 0; indexI <= 65535; indexI++) { if (indexI !== 0x25) { - var hex = decimalToHexString(indexI); try { var str = String.fromCharCode(indexI); - if (decodeURI(str) !== str) { - throw new Test262Error('#' + hex + ' '); - errorCount++; - } + var differs = decodeURI(str) !== str; } catch (e) { - throw new Test262Error('#' + hex + ' '); - errorCount++; + throw new Test262Error('#' + decimalToHexString(indexI) + ' throws'); + } + if (differs) { + throw new Test262Error('#' + decimalToHexString(indexI) + ' differs'); } - count++; } } -if (errorCount > 0) { - throw new Test262Error('Total error: ' + errorCount + ' bad Unicode character in ' + count); -} - reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/decodeURIComponent/S15.1.3.2_A2.1_T1.js b/js/src/tests/test262/built-ins/decodeURIComponent/S15.1.3.2_A2.1_T1.js index 44c511a3704a..203a206bdc64 100644 --- a/js/src/tests/test262/built-ins/decodeURIComponent/S15.1.3.2_A2.1_T1.js +++ b/js/src/tests/test262/built-ins/decodeURIComponent/S15.1.3.2_A2.1_T1.js @@ -8,28 +8,18 @@ description: Complex tests includes: [decimalToHexString.js] ---*/ -//CHECK -var errorCount = 0; -var count = 0; for (var indexI = 0; indexI <= 65535; indexI++) { if (indexI !== 0x25) { - var hex = decimalToHexString(indexI); try { var str = String.fromCharCode(indexI); - if (decodeURIComponent(str) !== str) { - throw new Test262Error('#' + hex + ' '); - errorCount++; - } + var differs = decodeURIComponent(str) !== str; } catch (e) { - throw new Test262Error('#' + hex + ' '); - errorCount++; + throw new Test262Error('#' + decimalToHexString(indexI) + ' throws'); + } + if (differs) { + throw new Test262Error('#' + decimalToHexString(indexI) + ' differs'); } - count++; } } -if (errorCount > 0) { - throw new Test262Error('Total error: ' + errorCount + ' bad Unicode character in ' + count); -} - reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.1_T1.js b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.1_T1.js index 5c828265ccc0..6f394634ba70 100644 --- a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.1_T1.js @@ -15,7 +15,6 @@ var indexO = 0; for (var index = 0xDC00; index <= 0xDFFF; index++) { count++; - var hex = decimalToHexString(index); try { encodeURI(String.fromCharCode(index)); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.1_T2.js b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.1_T2.js index dfff5211b34a..5d1cd70874f2 100644 --- a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.1_T2.js @@ -15,7 +15,6 @@ var indexO = 0; for (var index = 0xDC00; index <= 0xDFFF; index++) { count++; - var hex = decimalToHexString(index); try { encodeURI(String.fromCharCode(index, 0x0041)); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.2_T1.js b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.2_T1.js index 69f9c9779d51..c594546cb0a7 100644 --- a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.2_T1.js @@ -17,7 +17,6 @@ var indexO = 0; for (var index = 0xD800; index <= 0xDBFF; index++) { count++; - var hex = decimalToHexString(index); try { encodeURI(String.fromCharCode(index)); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.2_T2.js b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.2_T2.js index 7826be5f7ecd..2b58ea2d4e18 100644 --- a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.2_T2.js +++ b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.2_T2.js @@ -17,7 +17,6 @@ var indexO = 0; for (var index = 0xD800; index <= 0xDBFF; index++) { count++; - var hex = decimalToHexString(index); try { encodeURI(String.fromCharCode(0x0041, index)); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.3_T1.js b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.3_T1.js index f3c81108bf24..9435893ab7c1 100644 --- a/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.3_T1.js +++ b/js/src/tests/test262/built-ins/encodeURI/S15.1.3.3_A1.3_T1.js @@ -22,7 +22,6 @@ for (var index = 0xD800; index <= 0xDBFF; index++) { count++; var res = true; for (var indexC = 0; indexC < chars.length; indexC++) { - var hex = decimalToHexString(index); try { encodeURI(String.fromCharCode(index, chars[indexC])); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.1_T1.js b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.1_T1.js index 7e52518a22fa..93d3f3b9a1f7 100644 --- a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.1_T1.js +++ b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.1_T1.js @@ -15,7 +15,6 @@ var indexO = 0; for (var index = 0xDC00; index <= 0xDFFF; index++) { count++; - var hex = decimalToHexString(index); try { encodeURIComponent(String.fromCharCode(index)); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.1_T2.js b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.1_T2.js index 2dbe34741a88..ab8922ae797d 100644 --- a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.1_T2.js +++ b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.1_T2.js @@ -15,7 +15,6 @@ var indexO = 0; for (var index = 0xDC00; index <= 0xDFFF; index++) { count++; - var hex = decimalToHexString(index); try { encodeURIComponent(String.fromCharCode(index, 0x0041)); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.2_T1.js b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.2_T1.js index 331c3ee97299..4352614148b0 100644 --- a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.2_T1.js +++ b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.2_T1.js @@ -17,7 +17,6 @@ var indexO = 0; for (var index = 0xD800; index <= 0xDBFF; index++) { count++; - var hex = decimalToHexString(index); try { encodeURIComponent(String.fromCharCode(index)); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.2_T2.js b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.2_T2.js index d6ac91d12d0a..e66e83a7810e 100644 --- a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.2_T2.js +++ b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.2_T2.js @@ -17,7 +17,6 @@ var indexO = 0; for (var index = 0xD800; index <= 0xDBFF; index++) { count++; - var hex = decimalToHexString(index); try { encodeURIComponent(String.fromCharCode(0x0041, index)); } catch (e) { diff --git a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.3_T1.js b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.3_T1.js index 5ae9bc452b63..cec58ac0d2e8 100644 --- a/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.3_T1.js +++ b/js/src/tests/test262/built-ins/encodeURIComponent/S15.1.3.4_A1.3_T1.js @@ -22,7 +22,6 @@ for (var index = 0xD800; index <= 0xDBFF; index++) { count++; var res = true; for (var indexC = 0; indexC < chars.length; indexC++) { - var hex = decimalToHexString(index); try { encodeURIComponent(String.fromCharCode(index, chars[indexC])); } catch (e) { diff --git a/js/src/tests/test262/built-ins/isFinite/S15.1.2.5_A2.6.js b/js/src/tests/test262/built-ins/isFinite/S15.1.2.5_A2.6.js index 7677461ff6e4..ad528bb25039 100644 --- a/js/src/tests/test262/built-ins/isFinite/S15.1.2.5_A2.6.js +++ b/js/src/tests/test262/built-ins/isFinite/S15.1.2.5_A2.6.js @@ -6,10 +6,6 @@ info: The isFinite property has not prototype property esid: sec-isfinite-number description: Checking isFinite.prototype ---*/ - -//CHECK#1 -if (isFinite.prototype !== undefined) { - throw new Test262Error('#1: isFinite.prototype === undefined. Actual: ' + (isFinite.prototype)); -} +assert.sameValue(isFinite.prototype, undefined, 'The value of isFinite.prototype is expected to equal undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/isFinite/S15.1.2.5_A2.7.js b/js/src/tests/test262/built-ins/isFinite/S15.1.2.5_A2.7.js index 01bf342ce529..2ec5c31ed43a 100644 --- a/js/src/tests/test262/built-ins/isFinite/S15.1.2.5_A2.7.js +++ b/js/src/tests/test262/built-ins/isFinite/S15.1.2.5_A2.7.js @@ -9,14 +9,9 @@ description: > throw a TypeError exception ---*/ -//CHECK#1 - -try { +assert.throws(TypeError, () => { new isFinite(); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new isFinite() throw TypeError. Actual: ' + (e)); - } -} + throw new Test262Error(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/isNaN/S15.1.2.4_A2.6.js b/js/src/tests/test262/built-ins/isNaN/S15.1.2.4_A2.6.js index 7f31b53c7030..acb0f32cbec7 100644 --- a/js/src/tests/test262/built-ins/isNaN/S15.1.2.4_A2.6.js +++ b/js/src/tests/test262/built-ins/isNaN/S15.1.2.4_A2.6.js @@ -6,10 +6,6 @@ info: The isNaN property has not prototype property esid: sec-isnan-number description: Checking isNaN.prototype ---*/ - -//CHECK#1 -if (isNaN.prototype !== undefined) { - throw new Test262Error('#1: isNaN.prototype === undefined. Actual: ' + (isNaN.prototype)); -} +assert.sameValue(isNaN.prototype, undefined, 'The value of isNaN.prototype is expected to equal undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/isNaN/S15.1.2.4_A2.7.js b/js/src/tests/test262/built-ins/isNaN/S15.1.2.4_A2.7.js index 16564f4a4cbe..d258ef2f5438 100644 --- a/js/src/tests/test262/built-ins/isNaN/S15.1.2.4_A2.7.js +++ b/js/src/tests/test262/built-ins/isNaN/S15.1.2.4_A2.7.js @@ -9,14 +9,9 @@ description: > throw a TypeError exception ---*/ -//CHECK#1 - -try { +assert.throws(TypeError, () => { new isNaN(); -} catch (e) { - if ((e instanceof TypeError) !== true) { - throw new Test262Error('#1.2: new isNaN() throw TypeError. Actual: ' + (e)); - } -} + throw new Test262Error(); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/parseFloat/S15.1.2.3_A2_T10.js b/js/src/tests/test262/built-ins/parseFloat/S15.1.2.3_A2_T10.js index 6d2aa9559d34..d084a46b1a76 100644 --- a/js/src/tests/test262/built-ins/parseFloat/S15.1.2.3_A2_T10.js +++ b/js/src/tests/test262/built-ins/parseFloat/S15.1.2.3_A2_T10.js @@ -9,34 +9,19 @@ description: "StrWhiteSpaceChar :: USP" //CHECK# var n; -var count = 0; -var errorCount = 0; var uspU = ["\u1680", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006", "\u2007", "\u2008", "\u2009", "\u200A", "\u202F", "\u205F", "\u3000"]; var uspS = ["1680", "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "200A", "202F", "205F", "3000"]; for (var index = 0; index < uspU.length; index++) { - var result = true; - n = false; if (parseFloat(uspU[index] + "1.1") !== parseFloat("1.1")) { throw new Test262Error('#1.' + uspS[index] + ' '); - result = false; } if (parseFloat(uspU[index] + uspU[index] + uspU[index] + "1.1") !== parseFloat("1.1")) { throw new Test262Error('#2.' + uspS[index] + ' '); - result = false; } n = parseFloat(uspU[index]); if (!(n !== n)) { throw new Test262Error('#3.' + uspS[index] + ' '); - result = false; } - if (result !== true) { - errorCount++; - } - count++; -} - -if (errorCount > 0) { - throw new Test262Error('Total error: ' + errorCount + ' bad Unicode character in ' + count); } reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/parseFloat/S15.1.2.3_A6.js b/js/src/tests/test262/built-ins/parseFloat/S15.1.2.3_A6.js index ce14c0732d96..d75a847379c6 100644 --- a/js/src/tests/test262/built-ins/parseFloat/S15.1.2.3_A6.js +++ b/js/src/tests/test262/built-ins/parseFloat/S15.1.2.3_A6.js @@ -19,7 +19,6 @@ var indexP; var indexO = 0; for (var index = 0; index <= 65535; index++) { if ((index < 0x0030) || (index > 0x0039)) { - var hex = decimalToHexString(index); if (parseFloat("0.1e1" + String.fromCharCode(index)) !== 1) { if (indexO === 0) { indexO = index; diff --git a/js/src/tests/test262/built-ins/parseInt/S15.1.2.2_A8.js b/js/src/tests/test262/built-ins/parseInt/S15.1.2.2_A8.js index 9238a27ff5c1..dd1892a869f0 100644 --- a/js/src/tests/test262/built-ins/parseInt/S15.1.2.2_A8.js +++ b/js/src/tests/test262/built-ins/parseInt/S15.1.2.2_A8.js @@ -21,7 +21,6 @@ for (var index = 0; index <= 65535; index++) { if ((index < 0x0030) || (index > 0x0039) && (index < 0x0041) || (index > 0x005A) && (index < 0x0061) || (index > 0x007A)) { - var hex = decimalToHexString(index); if (parseInt("1Z" + String.fromCharCode(index), 36) !== 71) { if (indexO === 0) { indexO = index; diff --git a/js/src/tests/test262/harness/arrayContains.js b/js/src/tests/test262/harness/arrayContains.js deleted file mode 100644 index 95e13bdaaf8d..000000000000 --- a/js/src/tests/test262/harness/arrayContains.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2017 Rick Waldron. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -description: > - Assert that the contents of an array contains another array as a slice or sub-array -includes: [arrayContains.js] ----*/ - -const willMatch = [0, 1, 2]; - -assert(arrayContains([0, 1, 2, 3], willMatch)); -assert(arrayContains([null, 0, 1, 2, 3], willMatch)); -assert(arrayContains([undefined, 0, 1, 2, 3], willMatch)); -assert(arrayContains([false, 0, 1, 2, 3], willMatch)); -assert(arrayContains([NaN, 0, 1, 2, 3], willMatch)); - -const willNotMatch = [1, 0, 2]; - -assert(!arrayContains([1, /* intentional hole */, 2], willNotMatch), '[1, /* intentional hole */, 2], willNotMatch)'); -assert(!arrayContains([1, null, 2], willNotMatch), '[1, null, 2], willNotMatch)'); -assert(!arrayContains([1, undefined, 2], willNotMatch), '[1, undefined, 2], willNotMatch)'); -assert(!arrayContains([1, false, 2], willNotMatch), '[1, false, 2], willNotMatch)'); -assert(!arrayContains([1, NaN, 2], willNotMatch), '[1, NaN, 2], willNotMatch)'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/assert-throws-custom-typeerror.js b/js/src/tests/test262/harness/assert-throws-custom-typeerror.js new file mode 100644 index 000000000000..b49ae1b5a62e --- /dev/null +++ b/js/src/tests/test262/harness/assert-throws-custom-typeerror.js @@ -0,0 +1,60 @@ +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Functions that throw instances of the specified constructor function + satisfy the assertion, without collision with error constructors of the + same name. +---*/ + +var intrinsicTypeError = TypeError; +var threw = false; + +(function() { + function TypeError() {} + + assert.throws(TypeError, function() { + throw new TypeError(); + }, 'Throws an instance of the matching custom TypeError'); + + try { + assert.throws(intrinsicTypeError, function() { + throw new TypeError(); + }); + } catch (err) { + threw = true; + if (err.constructor !== Test262Error) { + throw new Error( + 'Expected a Test262Error but a "' + err.constructor.name + + '" was thrown.' + ); + } + } + + if (threw === false) { + throw new Error('Expected a Test262Error, but no error was thrown.'); + } + + threw = false; + + try { + assert.throws(TypeError, function() { + throw new intrinsicTypeError(); + }); + } catch (err) { + threw = true; + if (err.constructor !== Test262Error) { + throw new Error( + 'Expected a Test262Error but a "' + err.constructor.name + + '" was thrown.' + ); + } + } + + if (threw === false) { + throw new Error('Expected a Test262Error, but no error was thrown.'); + } +})(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/assert-throws-same-realm.js b/js/src/tests/test262/harness/assert-throws-same-realm.js new file mode 100644 index 000000000000..1cbaa3afaff0 --- /dev/null +++ b/js/src/tests/test262/harness/assert-throws-same-realm.js @@ -0,0 +1,32 @@ +// Copyright (C) 2021 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Functions that throw instances of the realm specified constructor function + satisfy the assertion, without cross realms collisions. +---*/ + +var intrinsicTypeError = TypeError; +var threw = false; +var realmGlobal = $262.createRealm().global; + +try { + assert.throws(TypeError, function() { + throw new realmGlobal.TypeError(); + }); +} catch (err) { + threw = true; + if (err.constructor !== Test262Error) { + throw new Error( + 'Expected a Test262Error but a "' + err.constructor.name + + '" was thrown.' + ); + } +} + +if (threw === false) { + throw new Error('Expected a Test262Error, but no error was thrown.'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-arguments.js b/js/src/tests/test262/harness/compare-array-arguments.js new file mode 100644 index 000000000000..cee5cedcfd56 --- /dev/null +++ b/js/src/tests/test262/harness/compare-array-arguments.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Accepts spreadable arguments +includes: [compareArray.js] +---*/ + +const fixture = [0, 'a', undefined]; + +function checkFormatOfAssertionMessage(func, errorMessage) { + var caught = false; + try { + func(); + } catch (error) { + caught = true; + assert.sameValue(error.constructor, Test262Error); + assert.sameValue(error.message, errorMessage); + } + + assert(caught, `Expected ${func} to throw, but it didn't.`); +} + +function f() { + assert.compareArray(arguments, fixture); + assert.compareArray(fixture, arguments); + + checkFormatOfAssertionMessage(() => { + assert.compareArray(arguments, [], 'arguments and []'); + }, 'Expected [0, a, undefined] and [] to have the same contents. arguments and []'); + + checkFormatOfAssertionMessage(() => { + assert.compareArray([], arguments, '[] and arguments'); + }, 'Expected [] and [0, a, undefined] to have the same contents. [] and arguments'); +} + +f(...fixture); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-arraylike.js b/js/src/tests/test262/harness/compare-array-arraylike.js new file mode 100644 index 000000000000..6f1ea8242bb6 --- /dev/null +++ b/js/src/tests/test262/harness/compare-array-arraylike.js @@ -0,0 +1,36 @@ +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Accepts spreadable arguments +includes: [compareArray.js] +---*/ + +function checkFormatOfAssertionMessage(func, errorMessage) { + var caught = false; + try { + func(); + } catch (error) { + caught = true; + assert.sameValue(error.constructor, Test262Error); + assert.sameValue(error.message, errorMessage); + } + + assert(caught, `Expected ${func} to throw, but it didn't.`); +} + +const fixture = { length: 3, 0: 0, 1: 'a', 2: undefined}; + +assert.compareArray(fixture, [0, 'a', undefined]); +assert.compareArray([0, 'a', undefined], fixture); + +checkFormatOfAssertionMessage(() => { + assert.compareArray(fixture, [], 'fixture and []'); +}, 'Expected [0, a, undefined] and [] to have the same contents. fixture and []'); + +checkFormatOfAssertionMessage(() => { + assert.compareArray([], fixture, '[] and fixture'); +}, 'Expected [] and [0, a, undefined] to have the same contents. [] and fixture'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-different-elements.js b/js/src/tests/test262/harness/compare-array-different-elements.js index 356ba3e9ae2d..6ff8fdf048fa 100644 --- a/js/src/tests/test262/harness/compare-array-different-elements.js +++ b/js/src/tests/test262/harness/compare-array-different-elements.js @@ -10,8 +10,8 @@ includes: [compareArray.js] var first = [0, 'a', undefined]; var second = [0, 'b', undefined]; -if (compareArray(first, second) !== false) { - throw new Error('Arrays containing different elements are not equivalent.'); -} +assert.throws(Test262Error, () => { + assert.compareArray(first, second); +}, 'Arrays containing different elements are not equivalent.'); reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-different-length.js b/js/src/tests/test262/harness/compare-array-different-length.js index db572b443d2c..87e296ed8c02 100644 --- a/js/src/tests/test262/harness/compare-array-different-length.js +++ b/js/src/tests/test262/harness/compare-array-different-length.js @@ -7,12 +7,13 @@ description: > includes: [compareArray.js] ---*/ -if (compareArray([], [undefined]) !== false) { - throw new Error('Arrays of differing lengths are not equivalent.'); -} -if (compareArray([undefined], []) !== false) { - throw new Error('Arrays of differing lengths are not equivalent.'); -} +assert.throws(Test262Error, () => { + assert.compareArray([], [undefined]); +}, 'Arrays of differing lengths are not equivalent.'); + +assert.throws(Test262Error, () => { + assert.compareArray([undefined], []); +}, 'Arrays of differing lengths are not equivalent.'); reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-empty.js b/js/src/tests/test262/harness/compare-array-empty.js index c4961be2d883..b5be3531c218 100644 --- a/js/src/tests/test262/harness/compare-array-empty.js +++ b/js/src/tests/test262/harness/compare-array-empty.js @@ -7,8 +7,6 @@ description: > includes: [compareArray.js] ---*/ -if (compareArray([], []) !== true) { - throw new Error('Empty arrays are equivalent.'); -} +assert.compareArray([], [], 'Empty arrays are equivalent.'); reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-message.js b/js/src/tests/test262/harness/compare-array-message.js new file mode 100644 index 000000000000..ae2233761a6f --- /dev/null +++ b/js/src/tests/test262/harness/compare-array-message.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + compareArray can handle any value in message arg +includes: [compareArray.js] +features: [BigInt, Symbol] +---*/ + +assert.compareArray([], [], true); +assert.compareArray([], [], 1); +assert.compareArray([], [], 1n); +assert.compareArray([], [], () => {}); +assert.compareArray([], [], "test262"); +assert.compareArray([], [], Symbol("1")); +assert.compareArray([], [], {}); +assert.compareArray([], [], []); +assert.compareArray([], [], -1); +assert.compareArray([], [], Infinity); +assert.compareArray([], [], -Infinity); +assert.compareArray([], [], 0.1); +assert.compareArray([], [], -0.1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-same-elements-different-order.js b/js/src/tests/test262/harness/compare-array-same-elements-different-order.js index cdc69e4bc666..51e1506eede1 100644 --- a/js/src/tests/test262/harness/compare-array-same-elements-different-order.js +++ b/js/src/tests/test262/harness/compare-array-same-elements-different-order.js @@ -11,8 +11,8 @@ var obj = {}; var first = [0, 1, '', 's', null, undefined, obj]; var second = [0, 1, '', 's', undefined, null, obj]; -if (compareArray(first, second) !== false) { - throw new Error('Arrays containing the same elements in different order are not equivalent.'); -} +assert.throws(Test262Error, () => { + assert.compareArray(first, second); +}, 'Arrays containing the same elements in different order are not equivalent.'); reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-same-elements-same-order.js b/js/src/tests/test262/harness/compare-array-same-elements-same-order.js index b2fe1d9e27a1..fd2d25b5b939 100644 --- a/js/src/tests/test262/harness/compare-array-same-elements-same-order.js +++ b/js/src/tests/test262/harness/compare-array-same-elements-same-order.js @@ -11,8 +11,6 @@ var obj = {}; var first = [0, 1, '', 's', undefined, null, obj]; var second = [0, 1, '', 's', undefined, null, obj]; -if (compareArray(first, second) !== true) { - throw new Error('Arrays containing the same elements in the same order are equivalent.'); -} +assert.compareArray(first, second, 'Arrays containing the same elements in the same order are equivalent.'); reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-samevalue.js b/js/src/tests/test262/harness/compare-array-samevalue.js index 7c91fcaa95f3..7a17aea81c9c 100644 --- a/js/src/tests/test262/harness/compare-array-samevalue.js +++ b/js/src/tests/test262/harness/compare-array-samevalue.js @@ -7,7 +7,9 @@ description: > includes: [compareArray.js] ---*/ -assert(compareArray([NaN], [NaN])); -assert(!compareArray([0], [-0])); +assert.compareArray([NaN], [NaN]); +assert.throws(Test262Error, () => { + assert.compareArray([0], [-0]); +}); reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-sparse.js b/js/src/tests/test262/harness/compare-array-sparse.js index 2e30f7d05165..cbfa79d42563 100644 --- a/js/src/tests/test262/harness/compare-array-sparse.js +++ b/js/src/tests/test262/harness/compare-array-sparse.js @@ -7,24 +7,19 @@ description: > includes: [compareArray.js] ---*/ -if (compareArray([,], [,]) !== true) { - throw new Error('Sparse arrays of the same length are equivalent.'); -} -if (compareArray([,], [,,]) !== false) { - throw new Error('Sparse arrays of differing lengths are not equivalent.'); -} - -if (compareArray([,,], [,]) !== false) { - throw new Error('Sparse arrays of differing lengths are not equivalent.'); -} - -if (compareArray([,], []) !== false) { - throw new Error('Sparse arrays are not equivalent to empty arrays.'); -} - -if (compareArray([], [,]) !== false) { - throw new Error('Sparse arrays are not equivalent to empty arrays.'); -} +assert.compareArray([,], [,], 'Sparse arrays of the same length are equivalent.'); +assert.throws(Test262Error, () => { + assert.compareArray([,], [,,]); +}, 'Sparse arrays of differing lengths are not equivalent.'); +assert.throws(Test262Error, () => { + assert.compareArray([,,], [,]); +}, 'Sparse arrays of differing lengths are not equivalent.'); +assert.throws(Test262Error, () => { + assert.compareArray([,], []); +}, 'Sparse arrays are not equivalent to empty arrays.'); +assert.throws(Test262Error, () => { + assert.compareArray([], [,]); +}, 'Sparse arrays are not equivalent to empty arrays.'); reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/compare-array-symbol.js b/js/src/tests/test262/harness/compare-array-symbol.js index a1fd2c8fd7ad..24108342a110 100644 --- a/js/src/tests/test262/harness/compare-array-symbol.js +++ b/js/src/tests/test262/harness/compare-array-symbol.js @@ -11,7 +11,7 @@ features: [Symbol] var threw = false; try { - assert.compareArray([Symbol()], [Symbol('desc')]); + assert.compareArray([Symbol()], [Symbol('desc')]); } catch (err) { threw = true; diff --git a/js/src/tests/test262/harness/shell.js b/js/src/tests/test262/harness/shell.js index 118a435cf3a1..68be365f54ec 100644 --- a/js/src/tests/test262/harness/shell.js +++ b/js/src/tests/test262/harness/shell.js @@ -1,35 +1,4 @@ // GENERATED, DO NOT EDIT -// file: arrayContains.js -// Copyright (C) 2017 Ecma International. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -description: | - Verify that a subArray is contained within an array. -defines: [arrayContains] ----*/ - -/** - * @param {Array} array - * @param {Array} subArray - */ - -function arrayContains(array, subArray) { - var found; - for (var i = 0; i < subArray.length; i++) { - found = false; - for (var j = 0; j < array.length; j++) { - if (subArray[i] === array[j]) { - found = true; - break; - } - } - if (!found) { - return false; - } - } - return true; -} - // file: assertRelativeDateMs.js // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. @@ -1316,6 +1285,1504 @@ defines: [$MAX_ITERATIONS] var $MAX_ITERATIONS = 100000; +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; + // file: testTypedArray.js // Copyright (C) 2015 André Bargull. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/tests/test262/harness/temporalHelpers-one-shift-time-zone.js b/js/src/tests/test262/harness/temporalHelpers-one-shift-time-zone.js new file mode 100644 index 000000000000..0452d30111e1 --- /dev/null +++ b/js/src/tests/test262/harness/temporalHelpers-one-shift-time-zone.js @@ -0,0 +1,83 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Verify the time zone arithmetic used in TemporalHelpers.oneShiftTimeZone() + against known cases in the implementation's time zone database +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +function checkTimeZoneArithmetic(shiftInstant, shiftNs, realTimeZoneName, shiftWallTime) { + // No need to test this on hosts that don't provide an Intl object. It's + // sufficient that the logic is tested on at least one host. + if (typeof globalThis.Intl === "undefined") + return; + + const tz = TemporalHelpers.oneShiftTimeZone(shiftInstant, shiftNs); + const realTz = new Temporal.TimeZone(realTimeZoneName); + + assert.sameValue( + tz.getOffsetNanosecondsFor(shiftInstant), + realTz.getOffsetNanosecondsFor(shiftInstant), + 'offset at shift instant' + ); + const minus1 = shiftInstant.subtract({ hours: 1 }); + assert.sameValue( + tz.getOffsetNanosecondsFor(minus1), + realTz.getOffsetNanosecondsFor(minus1), + 'offset at 1 hour before shift' + ); + const plus1 = shiftInstant.add({ hours: 1 }); + assert.sameValue( + tz.getOffsetNanosecondsFor(plus1), + realTz.getOffsetNanosecondsFor(plus1), + 'offset at 1 hour after shift' + ); + + assert.compareArray( + tz.getPossibleInstantsFor(shiftWallTime).map((i) => i.epochNanoseconds), + realTz.getPossibleInstantsFor(shiftWallTime).map((i) => i.epochNanoseconds), + 'possible instants for wall time' + ); + const before1 = shiftWallTime.subtract({ hours: 1 }); + assert.compareArray( + tz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds), + realTz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds), + 'possible instants for 1 hour before wall time' + ); + const after1 = shiftWallTime.add({ hours: 1 }); + assert.compareArray( + tz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds), + realTz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds), + 'possible instants for 1 hour after wall time' + ); +} + +// Check a positive DST shift from +00:00 to +01:00 +checkTimeZoneArithmetic( + new Temporal.Instant(1616893200000000000n), + 3600e9, + 'Europe/London', + new Temporal.PlainDateTime(2021, 3, 28, 1) +); + +// Check a negative DST shift from +00:00 to -01:00 +checkTimeZoneArithmetic( + new Temporal.Instant(1635642000000000000n), + -3600e9, + 'Atlantic/Azores', + new Temporal.PlainDateTime(2021, 10, 31, 1) +); + +// Check the no-shift case +checkTimeZoneArithmetic( + new Temporal.Instant(0n), + 0, + 'UTC', + new Temporal.PlainDateTime(1970, 1, 1) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/harness/testTypedArray.js b/js/src/tests/test262/harness/testTypedArray.js index 30af2d2c6b71..1c7bfb7303ff 100644 --- a/js/src/tests/test262/harness/testTypedArray.js +++ b/js/src/tests/test262/harness/testTypedArray.js @@ -10,34 +10,16 @@ description: > testWithTypedArrayConstructors() testTypedArrayConversions() -includes: [testTypedArray.js,arrayContains.js] +includes: [testTypedArray.js] features: [TypedArray] ---*/ -var TAConstructors = [ - Float64Array, - Float32Array, - Int32Array, - Int16Array, - Int8Array, - Uint32Array, - Uint16Array, - Uint8Array, - Uint8ClampedArray -]; -var length = TAConstructors.length; - -assert( - arrayContains(typedArrayConstructors, TAConstructors), - "All TypedArray constructors are accounted for" -); assert(typeof TypedArray === "function"); assert.sameValue(TypedArray, Object.getPrototypeOf(Uint8Array)); - var callCount = 0; testWithTypedArrayConstructors(() => callCount++); -assert.sameValue(callCount, length); +assert.sameValue(callCount, 9); assert.sameValue(typedArrayConstructors[0], Float64Array); assert.sameValue(typedArrayConstructors[1], Float32Array); @@ -49,14 +31,4 @@ assert.sameValue(typedArrayConstructors[6], Uint16Array); assert.sameValue(typedArrayConstructors[7], Uint8Array); assert.sameValue(typedArrayConstructors[8], Uint8ClampedArray); -assert.sameValue(typedArrayConstructors[0], TAConstructors[0]); -assert.sameValue(typedArrayConstructors[1], TAConstructors[1]); -assert.sameValue(typedArrayConstructors[2], TAConstructors[2]); -assert.sameValue(typedArrayConstructors[3], TAConstructors[3]); -assert.sameValue(typedArrayConstructors[4], TAConstructors[4]); -assert.sameValue(typedArrayConstructors[5], TAConstructors[5]); -assert.sameValue(typedArrayConstructors[6], TAConstructors[6]); -assert.sameValue(typedArrayConstructors[7], TAConstructors[7]); -assert.sameValue(typedArrayConstructors[8], TAConstructors[8]); - reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/basic.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/basic.js index 7f6f5ba6041b..eb59055e2867 100644 --- a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/basic.js +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/basic.js @@ -15,29 +15,7 @@ var actual = new Intl.Collator().resolvedOptions(); var actual2 = new Intl.Collator().resolvedOptions(); assert.notSameValue(actual2, actual, "resolvedOptions returned the same object twice."); -// source: CLDR file common/bcp47/collation.xml; version CLDR 32. -var collations = [ - "default", // added - "big5han", - "compat", - "dict", - "direct", - "ducet", - "emoji", - "eor", - "gb2312", - "phonebk", - "phonetic", - "pinyin", - "reformed", - // "search", // excluded - "searchjl", - // "standard", // excluded - "stroke", - "trad", - "unihan", - "zhuyin", -]; +var collations = ["default", ...allCollations()]; // this assumes the default values where the specification provides them assert(isCanonicalizedStructurallyValidLanguageTag(actual.locale), @@ -45,6 +23,8 @@ assert(isCanonicalizedStructurallyValidLanguageTag(actual.locale), assert.sameValue(actual.usage, "sort"); assert.sameValue(actual.sensitivity, "variant"); assert.sameValue(actual.ignorePunctuation, false); +assert.notSameValue(actual.collation, "search"); +assert.notSameValue(actual.collation, "standard"); assert.notSameValue(collations.indexOf(actual.collation), -1, "Invalid collation: " + actual.collation); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/order.js index 7e63a9739d70..edc6adbc2917 100644 --- a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/order.js +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/order.js @@ -4,7 +4,6 @@ /*--- esid: sec-intl.collator.prototype.resolvedoptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [compareArray.js] ---*/ const options = new Intl.Collator([], { @@ -18,16 +17,18 @@ const expected = [ "sensitivity", "ignorePunctuation", "collation", + "numeric", + "caseFirst" ]; -if ("numeric" in options) { - expected.push("numeric"); -} +const actual = Object.getOwnPropertyNames(options); -if ("caseFirst" in options) { - expected.push("caseFirst"); +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); } -assert.compareArray(Object.getOwnPropertyNames(options), expected); - reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/temporal-objects-resolved-time-zone.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/temporal-objects-resolved-time-zone.js new file mode 100644 index 000000000000..455291454668 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/temporal-objects-resolved-time-zone.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-datetime-format-functions +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +features: [Temporal] +---*/ + +const formatter = new Intl.DateTimeFormat("en", { timeZone: "Pacific/Apia" }); + +const date = new Temporal.PlainDate(2021, 8, 4); +const dateResult = formatter.format(date); +assert.sameValue(dateResult, "8/4/2021", "plain date"); + +const datetime1 = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const datetimeResult1 = formatter.format(datetime1); +assert.sameValue(datetimeResult1, "8/4/2021, 12:30:45 AM", "plain datetime close to beginning of day"); +const datetime2 = new Temporal.PlainDateTime(2021, 8, 4, 23, 30, 45, 123, 456, 789); +const datetimeResult2 = formatter.format(datetime2); +assert.sameValue(datetimeResult2, "8/4/2021, 11:30:45 PM", "plain datetime close to end of day"); + +const monthDay = new Temporal.PlainMonthDay(8, 4, "gregory"); +const monthDayResult = formatter.format(monthDay); +assert.sameValue(monthDayResult, "8/4", "plain month-day"); + +const time1 = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const timeResult1 = formatter.format(time1); +assert.sameValue(timeResult1, "12:30:45 AM", "plain time close to beginning of day"); +const time2 = new Temporal.PlainTime(23, 30, 45, 123, 456, 789); +const timeResult2 = formatter.format(time2); +assert.sameValue(timeResult2, "11:30:45 PM", "plain time close to end of day"); + +const month = new Temporal.PlainYearMonth(2021, 8, "gregory"); +const monthResult = formatter.format(month); +assert.sameValue(monthResult, "8/2021", "plain year-month"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..6530bdf031b8 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,52 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-datetime-format-functions +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [Temporal] +---*/ + +const formatter = new Intl.DateTimeFormat(undefined, { calendar: "iso8601" }); +const date = new Temporal.PlainDate(2021, 8, 4); +const datetime = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const monthDay = new Temporal.PlainMonthDay(8, 4); +const time = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const month = new Temporal.PlainYearMonth(2021, 8); + +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + + assert.throws( + TypeError, + () => formatter.format(date), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainDate case)" + ); + assert.throws( + TypeError, + () => formatter.format(datetime), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainDateTime case)" + ); + assert.throws( + TypeError, + () => formatter.format(monthDay), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainMonthDay case)" + ); + assert.throws( + TypeError, + () => formatter.format(time), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainTime case)" + ); + assert.throws( + TypeError, + () => formatter.format(month), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainYearMonth case)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/temporal-objects-resolved-time-zone.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/temporal-objects-resolved-time-zone.js new file mode 100644 index 000000000000..89a59c3f17e2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/temporal-objects-resolved-time-zone.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-datetime-format-functions +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +features: [Temporal, Intl.DateTimeFormat-formatRange] +---*/ + +const formatter = new Intl.DateTimeFormat("en", { timeZone: "Pacific/Apia" }); + +const date1 = new Temporal.PlainDate(2021, 8, 4); +const date2 = new Temporal.PlainDate(2021, 8, 5); +const dateResult = formatter.formatRange(date1, date2); +assert.sameValue(dateResult, "8/4/2021 – 8/5/2021", "plain dates"); + +const datetime1 = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const datetime2 = new Temporal.PlainDateTime(2021, 8, 4, 23, 30, 45, 123, 456, 789); +const datetimeResult = formatter.formatRange(datetime1, datetime2); +assert.sameValue(datetimeResult, "8/4/2021, 12:30:45 AM – 11:30:45 PM", "plain datetimes"); + +const monthDay1 = new Temporal.PlainMonthDay(8, 4, "gregory"); +const monthDay2 = new Temporal.PlainMonthDay(8, 5, "gregory"); +const monthDayResult = formatter.formatRange(monthDay1, monthDay2); +assert.sameValue(monthDayResult, "8/4 – 8/5", "plain month-days"); + +const time1 = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const time2 = new Temporal.PlainTime(23, 30, 45, 123, 456, 789); +const timeResult = formatter.formatRange(time1, time2); +assert.sameValue(timeResult, "12:30:45 AM – 11:30:45 PM", "plain times"); + +const month1 = new Temporal.PlainYearMonth(2021, 8, "gregory"); +const month2 = new Temporal.PlainYearMonth(2021, 9, "gregory"); +const monthResult = formatter.formatRange(month1, month2); +assert.sameValue(monthResult, "8/2021 – 9/2021", "plain year-months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..0fa3c6b76b85 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.formatRange +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [Temporal] +---*/ + +const formatter = new Intl.DateTimeFormat(undefined, { calendar: "iso8601" }); +const date1 = new Temporal.PlainDate(2021, 8, 4); +const date2 = new Temporal.PlainDate(2021, 9, 4); +const datetime1 = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const datetime2 = new Temporal.PlainDateTime(2021, 9, 4, 0, 30, 45, 123, 456, 789); +const monthDay1 = new Temporal.PlainMonthDay(8, 4); +const monthDay2 = new Temporal.PlainMonthDay(9, 4); +const time1 = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const time2 = new Temporal.PlainTime(1, 30, 45, 123, 456, 789); +const month1 = new Temporal.PlainYearMonth(2021, 8); +const month2 = new Temporal.PlainYearMonth(2022, 8); + +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + + assert.throws( + TypeError, + () => formatter.formatRange(date1, date2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainDate case)" + ); + assert.throws( + TypeError, + () => formatter.formatRange(datetime1, datetime2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainDateTime case)" + ); + assert.throws( + TypeError, + () => formatter.formatRange(monthDay1, monthDay2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainMonthDay case)" + ); + assert.throws( + TypeError, + () => formatter.formatRange(time1, time2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainTime case)" + ); + assert.throws( + TypeError, + () => formatter.formatRange(month1, month2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainYearMonth case)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/pattern-on-calendar.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/pattern-on-calendar.js index 5a62a7c0e758..21c41b3073e6 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/pattern-on-calendar.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/pattern-on-calendar.js @@ -6,29 +6,12 @@ esid: sec-initializedatetimeformat description: > Checks the DateTimeFormat choose different patterns based on calendar. +includes: [testIntl.js] features: [Intl.DateTimeFormat-formatRange] locale: [en] ---*/ -let calendars = [ - "buddhist", - "chinese", - "coptic", - "dangi", - "ethiopic", - "ethioaa", - "gregory", - "hebrew", - "indian", - "islamic", - "islamic-civil", - "islamic-rgsa", - "islamic-tbla", - "islamic-umalqura", - "japanese", - "persian", - "roc" -]; +let calendars = allCalendars(); let date1 = new Date(2017, 3, 12); let date2 = new Date(); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/shell.js index a96394ce8652..8fe6aaec148a 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/shell.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/shell.js @@ -30,6 +30,335 @@ var date_2100_start = 4102444800000; var start_of_time = -8.64e15; var end_of_time = 8.64e15; +// file: deepEqual.js +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Compare two values structurally +defines: [assert.deepEqual] +---*/ + +assert.deepEqual = function(actual, expected, message) { + var format = assert.deepEqual.format; + assert( + assert.deepEqual._compare(actual, expected), + `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}` + ); +}; + +assert.deepEqual.format = function(value, seen) { + switch (typeof value) { + case 'string': + return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`; + case 'number': + case 'boolean': + case 'symbol': + case 'bigint': + return value.toString(); + case 'undefined': + return 'undefined'; + case 'function': + return `[Function${value.name ? `: ${value.name}` : ''}]`; + case 'object': + if (value === null) return 'null'; + if (value instanceof Date) return `Date "${value.toISOString()}"`; + if (value instanceof RegExp) return value.toString(); + if (!seen) { + seen = { + counter: 0, + map: new Map() + }; + } + + let usage = seen.map.get(value); + if (usage) { + usage.used = true; + return `[Ref: #${usage.id}]`; + } + + usage = { id: ++seen.counter, used: false }; + seen.map.set(value, usage); + + if (typeof Set !== "undefined" && value instanceof Set) { + return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (typeof Map !== "undefined" && value instanceof Map) { + return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (Array.isArray ? Array.isArray(value) : value instanceof Array) { + return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`; + } + let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object'; + if (tag === 'Object' && Object.getPrototypeOf(value) === null) { + tag = '[Object: null prototype]'; + } + return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`; + default: + return typeof value; + } +}; + +assert.deepEqual._compare = (function () { + var EQUAL = 1; + var NOT_EQUAL = -1; + var UNKNOWN = 0; + + function deepEqual(a, b) { + return compareEquality(a, b) === EQUAL; + } + + function compareEquality(a, b, cache) { + return compareIf(a, b, isOptional, compareOptionality) + || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality) + || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache) + || NOT_EQUAL; + } + + function compareIf(a, b, test, compare, cache) { + return !test(a) + ? !test(b) ? UNKNOWN : NOT_EQUAL + : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache); + } + + function tryCompareStrictEquality(a, b) { + return a === b ? EQUAL : UNKNOWN; + } + + function tryCompareTypeOfEquality(a, b) { + return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN; + } + + function tryCompareToStringTagEquality(a, b) { + var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined; + var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined; + return aTag !== bTag ? NOT_EQUAL : UNKNOWN; + } + + function isOptional(value) { + return value === undefined + || value === null; + } + + function compareOptionality(a, b) { + return tryCompareStrictEquality(a, b) + || NOT_EQUAL; + } + + function isPrimitiveEquatable(value) { + switch (typeof value) { + case 'string': + case 'number': + case 'bigint': + case 'boolean': + case 'symbol': + return true; + default: + return isBoxed(value); + } + } + + function comparePrimitiveEquality(a, b) { + if (isBoxed(a)) a = a.valueOf(); + if (isBoxed(b)) b = b.valueOf(); + return tryCompareStrictEquality(a, b) + || tryCompareTypeOfEquality(a, b) + || compareIf(a, b, isNaNEquatable, compareNaNEquality) + || NOT_EQUAL; + } + + function isNaNEquatable(value) { + return typeof value === 'number'; + } + + function compareNaNEquality(a, b) { + return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL; + } + + function isObjectEquatable(value) { + return typeof value === 'object'; + } + + function compareObjectEquality(a, b, cache) { + if (!cache) cache = new Map(); + return getCache(cache, a, b) + || setCache(cache, a, b, EQUAL) // consider equal for now + || cacheComparison(a, b, tryCompareStrictEquality, cache) + || cacheComparison(a, b, tryCompareToStringTagEquality, cache) + || compareIf(a, b, isValueOfEquatable, compareValueOfEquality) + || compareIf(a, b, isToStringEquatable, compareToStringEquality) + || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache) + || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache) + || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || cacheComparison(a, b, fail, cache); + } + + function isBoxed(value) { + return value instanceof String + || value instanceof Number + || value instanceof Boolean + || typeof Symbol === 'function' && value instanceof Symbol + || typeof BigInt === 'function' && value instanceof BigInt; + } + + function isValueOfEquatable(value) { + return value instanceof Date; + } + + function compareValueOfEquality(a, b) { + return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isToStringEquatable(value) { + return value instanceof RegExp; + } + + function compareToStringEquality(a, b) { + return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isArrayLikeEquatable(value) { + return (Array.isArray ? Array.isArray(value) : value instanceof Array) + || (typeof Uint8Array === 'function' && value instanceof Uint8Array) + || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray) + || (typeof Uint16Array === 'function' && value instanceof Uint16Array) + || (typeof Uint32Array === 'function' && value instanceof Uint32Array) + || (typeof Int8Array === 'function' && value instanceof Int8Array) + || (typeof Int16Array === 'function' && value instanceof Int16Array) + || (typeof Int32Array === 'function' && value instanceof Int32Array) + || (typeof Float32Array === 'function' && value instanceof Float32Array) + || (typeof Float64Array === 'function' && value instanceof Float64Array) + || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array) + || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array); + } + + function compareArrayLikeEquality(a, b, cache) { + if (a.length !== b.length) return NOT_EQUAL; + for (var i = 0; i < a.length; i++) { + if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + return EQUAL; + } + + function isStructurallyEquatable(value) { + return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference + || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference + || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference + || typeof Map === 'function' && value instanceof Map // comparable via @@iterator + || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator + } + + function compareStructuralEquality(a, b, cache) { + var aKeys = []; + for (var key in a) aKeys.push(key); + + var bKeys = []; + for (var key in b) bKeys.push(key); + + if (aKeys.length !== bKeys.length) { + return NOT_EQUAL; + } + + aKeys.sort(); + bKeys.sort(); + + for (var i = 0; i < aKeys.length; i++) { + var aKey = aKeys[i]; + var bKey = bKeys[i]; + if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + + return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || EQUAL; + } + + function isIterableEquatable(value) { + return typeof Symbol === 'function' + && typeof value[Symbol.iterator] === 'function'; + } + + function compareIteratorEquality(a, b, cache) { + if (typeof Map === 'function' && a instanceof Map && b instanceof Map || + typeof Set === 'function' && a instanceof Set && b instanceof Set) { + if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size + } + + var ar, br; + while (true) { + ar = a.next(); + br = b.next(); + if (ar.done) { + if (br.done) return EQUAL; + if (b.return) b.return(); + return NOT_EQUAL; + } + if (br.done) { + if (a.return) a.return(); + return NOT_EQUAL; + } + if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) { + if (a.return) a.return(); + if (b.return) b.return(); + return NOT_EQUAL; + } + } + } + + function compareIterableEquality(a, b, cache) { + return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache); + } + + function cacheComparison(a, b, compare, cache) { + var result = compare(a, b, cache); + if (cache && (result === EQUAL || result === NOT_EQUAL)) { + setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result)); + } + return result; + } + + function fail() { + return NOT_EQUAL; + } + + function setCache(cache, left, right, result) { + var otherCache; + + otherCache = cache.get(left); + if (!otherCache) cache.set(left, otherCache = new Map()); + otherCache.set(right, result); + + otherCache = cache.get(right); + if (!otherCache) cache.set(right, otherCache = new Map()); + otherCache.set(left, result); + } + + function getCache(cache, left, right) { + var otherCache; + var result; + + otherCache = cache.get(left); + result = otherCache && otherCache.get(right); + if (result) return result; + + otherCache = cache.get(right); + result = otherCache && otherCache.get(left); + if (result) return result; + + return UNKNOWN; + } + + return deepEqual; +})(); + // file: isConstructor.js // Copyright (C) 2017 André Bargull. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-resolved-time-zone.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-resolved-time-zone.js new file mode 100644 index 000000000000..288483bee9cf --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-resolved-time-zone.js @@ -0,0 +1,106 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-datetime-format-functions +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +includes: [deepEqual.js] +features: [Temporal, Intl.DateTimeFormat-formatRange] +---*/ + +const formatter = new Intl.DateTimeFormat("en", { timeZone: "Pacific/Apia" }); + +const date1 = new Temporal.PlainDate(2021, 8, 4); +const date2 = new Temporal.PlainDate(2021, 8, 5); +const dateResult = formatter.formatRangeToParts(date1, date2); +assert.deepEqual(dateResult, [ + { type: "month", value: "8", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "day", value: "4", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "year", value: "2021", source: "startRange" }, + { type: "literal", value: " – ", source: "shared" }, + { type: "month", value: "8", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "day", value: "5", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "year", value: "2021", source: "endRange" }, +], "plain dates"); + +const datetime1 = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const datetime2 = new Temporal.PlainDateTime(2021, 8, 4, 23, 30, 45, 123, 456, 789); +const datetimeResult = formatter.formatRangeToParts(datetime1, datetime2); +assert.deepEqual(datetimeResult, [ + { type: "month", value: "8", source: "shared" }, + { type: "literal", value: "/", source: "shared" }, + { type: "day", value: "4", source: "shared" }, + { type: "literal", value: "/", source: "shared" }, + { type: "year", value: "2021", source: "shared" }, + { type: "literal", value: ", ", source: "shared" }, + { type: "hour", value: "12", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "minute", value: "30", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "45", source: "startRange" }, + { type: "literal", value: " ", source: "startRange" }, + { type: "dayPeriod", value: "AM", source: "startRange" }, + { type: "literal", value: " – ", source: "shared" }, + { type: "hour", value: "11", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "minute", value: "30", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "45", source: "endRange" }, + { type: "literal", value: " ", source: "endRange" }, + { type: "dayPeriod", value: "PM", source: "endRange" }, +], "plain datetimes"); + +const monthDay1 = new Temporal.PlainMonthDay(8, 4, "gregory"); +const monthDay2 = new Temporal.PlainMonthDay(8, 5, "gregory"); +const monthDayResult = formatter.formatRangeToParts(monthDay1, monthDay2); +assert.deepEqual(monthDayResult, [ + { type: "month", value: "8", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "day", value: "4", source: "startRange" }, + { type: "literal", value: " – ", source: "shared" }, + { type: "month", value: "8", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "day", value: "5", source: "endRange" }, +], "plain month-days"); + +const time1 = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const time2 = new Temporal.PlainTime(23, 30, 45, 123, 456, 789); +const timeResult = formatter.formatRangeToParts(time1, time2); +assert.deepEqual(timeResult, [ + { type: "hour", value: "12", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "minute", value: "30", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "45", source: "startRange" }, + { type: "literal", value: " ", source: "startRange" }, + { type: "dayPeriod", value: "AM", source: "startRange" }, + { type: "literal", value: " – ", source: "shared" }, + { type: "hour", value: "11", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "minute", value: "30", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "45", source: "endRange" }, + { type: "literal", value: " ", source: "endRange" }, + { type: "dayPeriod", value: "PM", source: "endRange" }, +], "plain times"); + +const month1 = new Temporal.PlainYearMonth(2021, 8, "gregory"); +const month2 = new Temporal.PlainYearMonth(2021, 9, "gregory"); +const monthResult = formatter.formatRangeToParts(month1, month2); +assert.deepEqual(monthResult, [ + { type: "month", value: "8", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "year", value: "2021", source: "startRange" }, + { type: "literal", value: " – ", source: "shared" }, + { type: "month", value: "9", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "year", value: "2021", source: "endRange" }, +], "plain year-months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..34ece4e581cc --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.formatRangeToParts +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [Temporal] +---*/ + +const formatter = new Intl.DateTimeFormat(undefined, { calendar: "iso8601" }); +const date1 = new Temporal.PlainDate(2021, 8, 4); +const date2 = new Temporal.PlainDate(2021, 9, 4); +const datetime1 = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const datetime2 = new Temporal.PlainDateTime(2021, 9, 4, 0, 30, 45, 123, 456, 789); +const monthDay1 = new Temporal.PlainMonthDay(8, 4); +const monthDay2 = new Temporal.PlainMonthDay(9, 4); +const time1 = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const time2 = new Temporal.PlainTime(1, 30, 45, 123, 456, 789); +const month1 = new Temporal.PlainYearMonth(2021, 8); +const month2 = new Temporal.PlainYearMonth(2022, 8); + +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + + assert.throws( + TypeError, + () => formatter.formatRangeToParts(date1, date2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainDate case)" + ); + assert.throws( + TypeError, + () => formatter.formatRangeToParts(datetime1, datetime2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainDateTime case)" + ); + assert.throws( + TypeError, + () => formatter.formatRangeToParts(monthDay1, monthDay2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainMonthDay case)" + ); + assert.throws( + TypeError, + () => formatter.formatRangeToParts(time1, time2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainTime case)" + ); + assert.throws( + TypeError, + () => formatter.formatRangeToParts(month1, month2), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainYearMonth case)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/pattern-on-calendar.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/pattern-on-calendar.js index 9a87da8dbc2a..7f93a27f1133 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/pattern-on-calendar.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/pattern-on-calendar.js @@ -6,28 +6,11 @@ esid: sec-initializedatetimeformat description: > Checks the DateTimeFormat choose different patterns based on calendar. +includes: [testIntl.js] locale: [en] ---*/ -let calendars = [ - "buddhist", - "chinese", - "coptic", - "dangi", - "ethiopic", - "ethioaa", - "gregory", - "hebrew", - "indian", - "islamic", - "islamic-civil", - "islamic-rgsa", - "islamic-tbla", - "islamic-umalqura", - "japanese", - "persian", - "roc" -]; +let calendars = allCalendars(); let date = new Date(); // serialize parts to a string by considering only the type and literal. diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/shell.js index 62c6315a7037..cce6b3c2a36e 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/shell.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/shell.js @@ -29,3 +29,332 @@ var date_2100_start = 4102444800000; var start_of_time = -8.64e15; var end_of_time = 8.64e15; + +// file: deepEqual.js +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Compare two values structurally +defines: [assert.deepEqual] +---*/ + +assert.deepEqual = function(actual, expected, message) { + var format = assert.deepEqual.format; + assert( + assert.deepEqual._compare(actual, expected), + `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}` + ); +}; + +assert.deepEqual.format = function(value, seen) { + switch (typeof value) { + case 'string': + return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`; + case 'number': + case 'boolean': + case 'symbol': + case 'bigint': + return value.toString(); + case 'undefined': + return 'undefined'; + case 'function': + return `[Function${value.name ? `: ${value.name}` : ''}]`; + case 'object': + if (value === null) return 'null'; + if (value instanceof Date) return `Date "${value.toISOString()}"`; + if (value instanceof RegExp) return value.toString(); + if (!seen) { + seen = { + counter: 0, + map: new Map() + }; + } + + let usage = seen.map.get(value); + if (usage) { + usage.used = true; + return `[Ref: #${usage.id}]`; + } + + usage = { id: ++seen.counter, used: false }; + seen.map.set(value, usage); + + if (typeof Set !== "undefined" && value instanceof Set) { + return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (typeof Map !== "undefined" && value instanceof Map) { + return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (Array.isArray ? Array.isArray(value) : value instanceof Array) { + return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`; + } + let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object'; + if (tag === 'Object' && Object.getPrototypeOf(value) === null) { + tag = '[Object: null prototype]'; + } + return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`; + default: + return typeof value; + } +}; + +assert.deepEqual._compare = (function () { + var EQUAL = 1; + var NOT_EQUAL = -1; + var UNKNOWN = 0; + + function deepEqual(a, b) { + return compareEquality(a, b) === EQUAL; + } + + function compareEquality(a, b, cache) { + return compareIf(a, b, isOptional, compareOptionality) + || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality) + || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache) + || NOT_EQUAL; + } + + function compareIf(a, b, test, compare, cache) { + return !test(a) + ? !test(b) ? UNKNOWN : NOT_EQUAL + : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache); + } + + function tryCompareStrictEquality(a, b) { + return a === b ? EQUAL : UNKNOWN; + } + + function tryCompareTypeOfEquality(a, b) { + return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN; + } + + function tryCompareToStringTagEquality(a, b) { + var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined; + var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined; + return aTag !== bTag ? NOT_EQUAL : UNKNOWN; + } + + function isOptional(value) { + return value === undefined + || value === null; + } + + function compareOptionality(a, b) { + return tryCompareStrictEquality(a, b) + || NOT_EQUAL; + } + + function isPrimitiveEquatable(value) { + switch (typeof value) { + case 'string': + case 'number': + case 'bigint': + case 'boolean': + case 'symbol': + return true; + default: + return isBoxed(value); + } + } + + function comparePrimitiveEquality(a, b) { + if (isBoxed(a)) a = a.valueOf(); + if (isBoxed(b)) b = b.valueOf(); + return tryCompareStrictEquality(a, b) + || tryCompareTypeOfEquality(a, b) + || compareIf(a, b, isNaNEquatable, compareNaNEquality) + || NOT_EQUAL; + } + + function isNaNEquatable(value) { + return typeof value === 'number'; + } + + function compareNaNEquality(a, b) { + return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL; + } + + function isObjectEquatable(value) { + return typeof value === 'object'; + } + + function compareObjectEquality(a, b, cache) { + if (!cache) cache = new Map(); + return getCache(cache, a, b) + || setCache(cache, a, b, EQUAL) // consider equal for now + || cacheComparison(a, b, tryCompareStrictEquality, cache) + || cacheComparison(a, b, tryCompareToStringTagEquality, cache) + || compareIf(a, b, isValueOfEquatable, compareValueOfEquality) + || compareIf(a, b, isToStringEquatable, compareToStringEquality) + || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache) + || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache) + || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || cacheComparison(a, b, fail, cache); + } + + function isBoxed(value) { + return value instanceof String + || value instanceof Number + || value instanceof Boolean + || typeof Symbol === 'function' && value instanceof Symbol + || typeof BigInt === 'function' && value instanceof BigInt; + } + + function isValueOfEquatable(value) { + return value instanceof Date; + } + + function compareValueOfEquality(a, b) { + return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isToStringEquatable(value) { + return value instanceof RegExp; + } + + function compareToStringEquality(a, b) { + return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isArrayLikeEquatable(value) { + return (Array.isArray ? Array.isArray(value) : value instanceof Array) + || (typeof Uint8Array === 'function' && value instanceof Uint8Array) + || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray) + || (typeof Uint16Array === 'function' && value instanceof Uint16Array) + || (typeof Uint32Array === 'function' && value instanceof Uint32Array) + || (typeof Int8Array === 'function' && value instanceof Int8Array) + || (typeof Int16Array === 'function' && value instanceof Int16Array) + || (typeof Int32Array === 'function' && value instanceof Int32Array) + || (typeof Float32Array === 'function' && value instanceof Float32Array) + || (typeof Float64Array === 'function' && value instanceof Float64Array) + || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array) + || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array); + } + + function compareArrayLikeEquality(a, b, cache) { + if (a.length !== b.length) return NOT_EQUAL; + for (var i = 0; i < a.length; i++) { + if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + return EQUAL; + } + + function isStructurallyEquatable(value) { + return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference + || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference + || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference + || typeof Map === 'function' && value instanceof Map // comparable via @@iterator + || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator + } + + function compareStructuralEquality(a, b, cache) { + var aKeys = []; + for (var key in a) aKeys.push(key); + + var bKeys = []; + for (var key in b) bKeys.push(key); + + if (aKeys.length !== bKeys.length) { + return NOT_EQUAL; + } + + aKeys.sort(); + bKeys.sort(); + + for (var i = 0; i < aKeys.length; i++) { + var aKey = aKeys[i]; + var bKey = bKeys[i]; + if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + + return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || EQUAL; + } + + function isIterableEquatable(value) { + return typeof Symbol === 'function' + && typeof value[Symbol.iterator] === 'function'; + } + + function compareIteratorEquality(a, b, cache) { + if (typeof Map === 'function' && a instanceof Map && b instanceof Map || + typeof Set === 'function' && a instanceof Set && b instanceof Set) { + if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size + } + + var ar, br; + while (true) { + ar = a.next(); + br = b.next(); + if (ar.done) { + if (br.done) return EQUAL; + if (b.return) b.return(); + return NOT_EQUAL; + } + if (br.done) { + if (a.return) a.return(); + return NOT_EQUAL; + } + if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) { + if (a.return) a.return(); + if (b.return) b.return(); + return NOT_EQUAL; + } + } + } + + function compareIterableEquality(a, b, cache) { + return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache); + } + + function cacheComparison(a, b, compare, cache) { + var result = compare(a, b, cache); + if (cache && (result === EQUAL || result === NOT_EQUAL)) { + setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result)); + } + return result; + } + + function fail() { + return NOT_EQUAL; + } + + function setCache(cache, left, right, result) { + var otherCache; + + otherCache = cache.get(left); + if (!otherCache) cache.set(left, otherCache = new Map()); + otherCache.set(right, result); + + otherCache = cache.get(right); + if (!otherCache) cache.set(right, otherCache = new Map()); + otherCache.set(left, result); + } + + function getCache(cache, left, right) { + var otherCache; + var result; + + otherCache = cache.get(left); + result = otherCache && otherCache.get(right); + if (result) return result; + + otherCache = cache.get(right); + result = otherCache && otherCache.get(left); + if (result) return result; + + return UNKNOWN; + } + + return deepEqual; +})(); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-resolved-time-zone.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-resolved-time-zone.js new file mode 100644 index 000000000000..73cbdac122b7 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-resolved-time-zone.js @@ -0,0 +1,99 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.formatToParts +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +includes: [deepEqual.js] +features: [Temporal] +---*/ + +const formatter = new Intl.DateTimeFormat("en", { timeZone: "Pacific/Apia" }); + +const date = new Temporal.PlainDate(2021, 8, 4); +const dateResult = formatter.formatToParts(date); +assert.deepEqual(dateResult, [ + { type: "month", value: "8" }, + { type: "literal", value: "/" }, + { type: "day", value: "4" }, + { type: "literal", value: "/" }, + { type: "year", value: "2021" }, +], "plain date"); + +const datetime1 = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const datetimeResult1 = formatter.formatToParts(datetime1); +assert.deepEqual(datetimeResult1, [ + { type: "month", value: "8" }, + { type: "literal", value: "/" }, + { type: "day", value: "4" }, + { type: "literal", value: "/" }, + { type: "year", value: "2021" }, + { type: "literal", value: ", " }, + { type: "hour", value: "12" }, + { type: "literal", value: ":" }, + { type: "minute", value: "30" }, + { type: "literal", value: ":" }, + { type: "second", value: "45" }, + { type: "literal", value: " " }, + { type: "dayPeriod", value: "AM" }, +], "plain datetime close to beginning of day"); +const datetime2 = new Temporal.PlainDateTime(2021, 8, 4, 23, 30, 45, 123, 456, 789); +const datetimeResult2 = formatter.formatToParts(datetime2); +assert.deepEqual(datetimeResult2, [ + { type: "month", value: "8" }, + { type: "literal", value: "/" }, + { type: "day", value: "4" }, + { type: "literal", value: "/" }, + { type: "year", value: "2021" }, + { type: "literal", value: ", " }, + { type: "hour", value: "11" }, + { type: "literal", value: ":" }, + { type: "minute", value: "30" }, + { type: "literal", value: ":" }, + { type: "second", value: "45" }, + { type: "literal", value: " " }, + { type: "dayPeriod", value: "PM" }, +], "plain datetime close to end of day"); + +const monthDay = new Temporal.PlainMonthDay(8, 4, "gregory"); +const monthDayResult = formatter.formatToParts(monthDay); +assert.deepEqual(monthDayResult, [ + { type: "month", value: "8" }, + { type: "literal", value: "/" }, + { type: "day", value: "4" }, +], "plain month-day"); + +const time1 = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const timeResult1 = formatter.formatToParts(time1); +assert.deepEqual(timeResult1, [ + { type: "hour", value: "12" }, + { type: "literal", value: ":" }, + { type: "minute", value: "30" }, + { type: "literal", value: ":" }, + { type: "second", value: "45" }, + { type: "literal", value: " " }, + { type: "dayPeriod", value: "AM" }, +], "plain time close to beginning of day"); +const time2 = new Temporal.PlainTime(23, 30, 45, 123, 456, 789); +const timeResult2 = formatter.formatToParts(time2); +assert.deepEqual(timeResult2, [ + { type: "hour", value: "11" }, + { type: "literal", value: ":" }, + { type: "minute", value: "30" }, + { type: "literal", value: ":" }, + { type: "second", value: "45" }, + { type: "literal", value: " " }, + { type: "dayPeriod", value: "PM" }, +], "plain time close to end of day"); + +const month = new Temporal.PlainYearMonth(2021, 8, "gregory"); +const monthResult = formatter.formatToParts(month); +assert.deepEqual(monthResult, [ + { type: "month", value: "8" }, + { type: "literal", value: "/" }, + { type: "year", value: "2021" }, +], "plain year-month"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..97f72c361c64 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,52 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.formatToParts +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [Temporal] +---*/ + +const formatter = new Intl.DateTimeFormat(undefined, { calendar: "iso8601" }); +const date = new Temporal.PlainDate(2021, 8, 4); +const datetime = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const monthDay = new Temporal.PlainMonthDay(8, 4); +const time = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const month = new Temporal.PlainYearMonth(2021, 8); + +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + + assert.throws( + TypeError, + () => formatter.formatToParts(date), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainDate case)" + ); + assert.throws( + TypeError, + () => formatter.formatToParts(datetime), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainDateTime case)" + ); + assert.throws( + TypeError, + () => formatter.formatToParts(monthDay), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainMonthDay case)" + ); + assert.throws( + TypeError, + () => formatter.formatToParts(time), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainTime case)" + ); + assert.throws( + TypeError, + () => formatter.formatToParts(month), + "Uncallable getOffsetNanosecondsFor should throw TypeError (PlainYearMonth case)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/basic.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/basic.js index 294b8f4d80e9..4ca918bb63b1 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/basic.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/basic.js @@ -16,29 +16,7 @@ var actual = new Intl.DateTimeFormat().resolvedOptions(); var actual2 = new Intl.DateTimeFormat().resolvedOptions(); assert.notSameValue(actual2, actual, "resolvedOptions returned the same object twice."); -// source: CLDR file common/bcp47/calendar.xml; version CLDR 32. -var calendars = [ - "buddhist", - "chinese", - "coptic", - "dangi", - "ethioaa", - "ethiopic-amete-alem", - "ethiopic", - "gregory", - "hebrew", - "indian", - "islamic", - "islamic-umalqura", - "islamic-tbla", - "islamic-civil", - "islamic-rgsa", - "iso8601", - "japanese", - "persian", - "roc", - "islamicc", -]; +var calendars = allCalendars(); // this assumes the default values where the specification provides them assert(isCanonicalizedStructurallyValidLanguageTag(actual.locale), diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-dayPeriod.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-dayPeriod.js index 475b3f9e3bff..971ba2ac422a 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-dayPeriod.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-dayPeriod.js @@ -4,7 +4,6 @@ /*--- esid: sec-intl.datetimeformat.prototype.resolvedoptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [arrayContains.js] features: [Intl.DateTimeFormat-dayPeriod] ---*/ @@ -30,10 +29,10 @@ let actual = Object.getOwnPropertyNames(options); // Ensure all expected items are in actual and also allow other properties // implemented in new proposals. -assert(arrayContains(actual, expected)); +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); for (var i = 1; i < expected.length; i++) { // Ensure the order as expected but allow additional new property in between - assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i])); + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); } reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-fractionalSecondDigits.js index a5160bb3c88b..2fc022b0dabe 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-fractionalSecondDigits.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-fractionalSecondDigits.js @@ -4,7 +4,6 @@ /*--- esid: sec-intl.datetimeformat.prototype.resolvedoptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [arrayContains.js] features: [Intl.DateTimeFormat-fractionalSecondDigits] ---*/ @@ -28,10 +27,10 @@ let actual = Object.getOwnPropertyNames(options); // Ensure all expected items are in actual and also allow other properties // implemented in new proposals. -assert(arrayContains(actual, expected)); +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); for (var i = 1; i < expected.length; i++) { // Ensure the order as expected but allow additional new property in between - assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i])); + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); } reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-style.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-style.js index 338701c4de49..2546b1b7466f 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-style.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-style.js @@ -4,7 +4,6 @@ /*--- esid: sec-intl.datetimeformat.prototype.resolvedoptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [arrayContains.js] features: [Intl.DateTimeFormat-datetimestyle] ---*/ @@ -34,10 +33,10 @@ let actual = Object.getOwnPropertyNames(options); // Ensure all expected items are in actual and also allow other properties // implemented in new proposals. -assert(arrayContains(actual, expected)); +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); for (var i = 1; i < expected.length; i++) { // Ensure the order as expected but allow additional new property in between - assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i])); + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); } reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js index 8f50b76b2dc4..13b318c5e442 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js @@ -4,7 +4,6 @@ /*--- esid: sec-intl.datetimeformat.prototype.resolvedoptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [arrayContains.js] ---*/ const options = new Intl.DateTimeFormat([], { @@ -42,10 +41,10 @@ let actual = Object.getOwnPropertyNames(options); // Ensure all expected items are in actual and also allow other properties // implemented in new proposals. -assert(arrayContains(actual, expected)); +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); for (var i = 1; i < expected.length; i++) { // Ensure the order as expected but allow additional new property in between - assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i])); + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); } reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/shell.js index 857452379f05..54371b778989 100644 --- a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/shell.js +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/shell.js @@ -1,35 +1,4 @@ // GENERATED, DO NOT EDIT -// file: arrayContains.js -// Copyright (C) 2017 Ecma International. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -description: | - Verify that a subArray is contained within an array. -defines: [arrayContains] ----*/ - -/** - * @param {Array} array - * @param {Array} subArray - */ - -function arrayContains(array, subArray) { - var found; - for (var i = 0; i < subArray.length; i++) { - found = false; - for (var j = 0; j < array.length; j++) { - if (subArray[i] === array[j]) { - found = true; - break; - } - } - if (!found) { - return false; - } - } - return true; -} - // file: isConstructor.js // Copyright (C) 2017 André Bargull. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/of/type-calendar-invalid.js b/js/src/tests/test262/intl402/DisplayNames/prototype/of/type-calendar-invalid.js index e90b2af937c2..1d7fc9ff430a 100644 --- a/js/src/tests/test262/intl402/DisplayNames/prototype/of/type-calendar-invalid.js +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/of/type-calendar-invalid.js @@ -44,4 +44,20 @@ assert.throws(RangeError, function() { displayNames.of('abc def'); }, 'interstitial space'); +assert.throws(RangeError, function() { + displayNames.of('123_abc'); +}, '2 segments, minimum length, underscore'); + +assert.throws(RangeError, function() { + displayNames.of('12345678_abcdefgh'); +}, '2 segments, maximum length, underscore'); + +assert.throws(RangeError, function() { + displayNames.of('123_abc_ABC'); +}, '3 segments, minimum length, underscore'); + +assert.throws(RangeError, function() { + displayNames.of('12345678_abcdefgh_ABCDEFGH'); +}, '3 segments, maximum length, underscore'); + reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/of/type-calendar-valid.js b/js/src/tests/test262/intl402/DisplayNames/prototype/of/type-calendar-valid.js index 5adbcd5c2439..9f6bb2a8d17c 100644 --- a/js/src/tests/test262/intl402/DisplayNames/prototype/of/type-calendar-valid.js +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/of/type-calendar-valid.js @@ -26,9 +26,4 @@ assert.sameValue(typeof displayNames.of('12345678-abcdefgh'), 'string', '2 segme assert.sameValue(typeof displayNames.of('123-abc-ABC'), 'string', '3 segments, minimum length, dash'); assert.sameValue(typeof displayNames.of('12345678-abcdefgh-ABCDEFGH'), 'string', '3 segments, maximum length, dash'); -assert.sameValue(typeof displayNames.of('123_abc'), 'string', '2 segments, minimum length, underscore'); -assert.sameValue(typeof displayNames.of('12345678_abcdefgh'), 'string', '2 segments, maximum length, underscore'); -assert.sameValue(typeof displayNames.of('123_abc_ABC'), 'string', '3 segments, minimum length, underscore'); -assert.sameValue(typeof displayNames.of('12345678_abcdefgh_ABCDEFGH'), 'string', '3 segments, maximum length, underscore'); - reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/browser.js b/js/src/tests/test262/intl402/DurationFormat/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/instance/browser.js b/js/src/tests/test262/intl402/DurationFormat/instance/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/instance/extensibility.js b/js/src/tests/test262/intl402/DurationFormat/instance/extensibility.js new file mode 100644 index 000000000000..f0d7dcc55429 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/instance/extensibility.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat +description: Intl.DurationFormat instance object extensibility +info: | + 17 ECMAScript Standard Built-in Objects: + + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. + +features: [Intl.DurationFormat] +---*/ + +assert.sameValue( + Object.isExtensible(new Intl.DurationFormat()), + true, + "Object.isExtensible(new Intl.DurationFormat()) returns true" +); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/instance/length.js b/js/src/tests/test262/intl402/DurationFormat/instance/length.js new file mode 100644 index 000000000000..f59faedd8836 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/instance/length.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat +description: > + Intl.DurationFormat.length is 0. +info: | + Intl.DurationFormat ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + Every built-in function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which + are shown using the form «...name») are not included in the default + argument count. + Unless otherwise specified, the length property of a built-in function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. + +features: [Intl.DurationFormat] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.DurationFormat, 'length', { + value: 0, + enumerable: false, + writable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/instance/name.js b/js/src/tests/test262/intl402/DurationFormat/instance/name.js new file mode 100644 index 000000000000..1dd1d72c2da9 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/instance/name.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat +description: > + Intl.DurationFormat.name is "DurationFormat". +info: | + Intl.DurationFormat ([ locales [ , options ]]) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. + +features: [Intl.DurationFormat] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.DurationFormat, 'name', { + value: 'DurationFormat', + enumerable: false, + writable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/instance/prop-desc.js b/js/src/tests/test262/intl402/DurationFormat/instance/prop-desc.js new file mode 100644 index 000000000000..4f5ad92f2518 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/instance/prop-desc.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat +description: > + "DurationFormat" property of Intl. +info: | + Intl.DurationFormat ([ locales [ , options ]]) + + 7 Requirements for Standard Built-in ECMAScript Objects + + Unless specified otherwise in this document, the objects, functions, and constructors + described in this standard are subject to the generic requirements and restrictions + specified for standard built-in ECMAScript objects in the ECMAScript 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + Every other data property described in clauses 18 through 26 and in Annex B.2 has the + attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } + unless otherwise specified. + +features: [Intl.DurationFormat] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl, 'DurationFormat', { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/instance/prototype.js b/js/src/tests/test262/intl402/DurationFormat/instance/prototype.js new file mode 100644 index 000000000000..69ba3ef08540 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/instance/prototype.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat +description: Intl.DurationFormat instance object is created from %DurationFormatPrototype%. +info: | + Intl.DurationFormat ([ locales [ , options ]]) + + 2. Let durationFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%DurationFormatPrototype%", « [[InitializedDurationFormat]], [[Locale]], [[DataLocale]], [[NumberingSystem]], [[Style]], [[YearsStyle]], [[YearsDisplay]], [[MonthsStyle]], [[MonthsDisplay]] , [[WeeksStyle]], [[WeeksDisplay]] , [[DaysStyle]], [[DaysDisplay]] , [[HoursStyle]], [[HoursDisplay]] , [[MinutesStyle]], [[MinutesDisplay]] , [[SecondsStyle]], [[SecondsDisplay]] , [[MillisecondsStyle]], [[MillisecondsDisplay]] , [[MicrosecondsStyle]], [[MicrosecondsDisplay]] , [[NanosecondsStyle]], [[NanosecondsDisplay]], [[FractionalDigits]] »). + +features: [Intl.DurationFormat] +---*/ + +const value = new Intl.DurationFormat(); +assert.sameValue( + Object.getPrototypeOf(value), + Intl.DurationFormat.prototype, + "Object.getPrototypeOf(value) equals the value of Intl.DurationFormat.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/instance/shell.js b/js/src/tests/test262/intl402/DurationFormat/instance/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/browser.js b/js/src/tests/test262/intl402/DurationFormat/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/browser.js b/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/prop-desc.js new file mode 100644 index 000000000000..70187debfcce --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/prop-desc.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat +description: > + "constructor" property of Intl.DurationFormat.prototype. +info: | + Intl.DurationFormat.prototype.constructor + + 7 Requirements for Standard Built-in ECMAScript Objects + + Unless specified otherwise in this document, the objects, functions, and constructors + described in this standard are subject to the generic requirements and restrictions + specified for standard built-in ECMAScript objects in the ECMAScript 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + Every other data property described in clauses 18 through 26 and in Annex B.2 has the + attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } + unless otherwise specified. + +features: [Intl.DurationFormat] +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.DurationFormat.prototype, "constructor"); +verifyWritable(Intl.DurationFormat.prototype, "constructor"); +verifyConfigurable(Intl.DurationFormat.prototype, "constructor"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/shell.js b/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/value.js b/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/value.js new file mode 100644 index 000000000000..c984b7829e20 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/constructor/value.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat +description: > + Tests that Intl.DurationFormat.prototype.constructor is the Intl.DurationFormat. + +features: [Intl.DurationFormat] +---*/ + +assert.sameValue(Intl.DurationFormat.prototype.constructor, Intl.DurationFormat, "Intl.DurationFormat.prototype.constructor is not the same as Intl.DurationFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/format/browser.js b/js/src/tests/test262/intl402/DurationFormat/prototype/format/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/format/length.js b/js/src/tests/test262/intl402/DurationFormat/prototype/format/length.js new file mode 100644 index 000000000000..6ff73b9e02aa --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/format/length.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.format +description: > + Intl.DateTimeFormat.prototype.format.length is 1. +info: | + Intl.DurationFormat.prototype.format ( duration ) + + 17 ECMAScript Standard Built-in Objects: + + Every built-in function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which + are shown using the form «...name») are not included in the default + argument count. + Unless otherwise specified, the length property of a built-in function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. + +features: [Intl.DurationFormat] +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DateTimeFormat.prototype.format.length, 1); + +verifyProperty(Intl.DurationFormat.prototype.format, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/format/name.js b/js/src/tests/test262/intl402/DurationFormat/prototype/format/name.js new file mode 100644 index 000000000000..57a2250fd2e3 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/format/name.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat.prototype.format +description: Checks the "name" property of Intl.DurationFormat.prototype.format(). +info: | + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. + +includes: [propertyHelper.js] +features: [Intl.DurationFormat] +---*/ + +verifyProperty(Intl.DurationFormat.prototype.format, "name", { + value: "format", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/format/prop-desc.js b/js/src/tests/test262/intl402/DurationFormat/prototype/format/prop-desc.js new file mode 100644 index 000000000000..ebb842ae8309 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/format/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat.prototype.format +description: Property descriptor of Intl.DurationFormat.prototype.format +includes: [propertyHelper.js] +features: [Intl.DurationFormat] +---*/ + +assert.sameValue( + typeof Intl.DurationFormat.prototype.format, + 'function', + '`typeof Intl.DurationFormat.prototype.format` is `function`' +); + +verifyProperty(Intl.DurationFormat.prototype, 'format', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/format/shell.js b/js/src/tests/test262/intl402/DurationFormat/prototype/format/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/format/throw-invoked-as-func.js b/js/src/tests/test262/intl402/DurationFormat/prototype/format/throw-invoked-as-func.js new file mode 100644 index 000000000000..7031bf2e115d --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/format/throw-invoked-as-func.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat.prototype.format +description: basic tests internal slot initialization and call receiver errors +info: | + Intl.DurationFormat.prototype.format ( duration ) + (...) + 2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]). +features: [Intl.DurationFormat] +---*/ + +const df = new Intl.DurationFormat(); + +// Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]). +let f = df['format']; + +assert.sameValue(typeof f, 'function'); +assert.throws(TypeError, () => { f('PT12.3456S') }); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/browser.js b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/length.js b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/length.js new file mode 100644 index 000000000000..c131c7e239b0 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/length.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.formatToParts +description: > + Intl.DateTimeFormat.prototype.formatToParts.length is 1. +info: | + Intl.DateTimeFormat.prototype.formatToParts ( date ) + + 17 ECMAScript Standard Built-in Objects: + + Every built-in function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which + are shown using the form «...name») are not included in the default + argument count. + Unless otherwise specified, the length property of a built-in function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. + +features: [Intl.DurationFormat] +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DateTimeFormat.prototype.formatToParts.length, 1); + +verifyProperty(Intl.DurationFormat.prototype.formatToParts, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/name.js b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/name.js new file mode 100644 index 000000000000..dc219104627f --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/name.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat.prototype.formatToParts +description: Checks the "name" property of Intl.DurationFormat.prototype.formatToParts(). +info: | + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. + +includes: [propertyHelper.js] +features: [Intl.DurationFormat] +---*/ + +verifyProperty(Intl.DurationFormat.prototype.formatToParts, "name", { + value: "formatToParts", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/prop-desc.js b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/prop-desc.js new file mode 100644 index 000000000000..3c32931386e7 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat.prototype.formatToParts +description: Property descriptor of Intl.DurationFormat.prototype.formatToParts +includes: [propertyHelper.js] +features: [Intl.DurationFormat] +---*/ + +assert.sameValue( + typeof Intl.DurationFormat.prototype.formatToParts, + 'function', + '`typeof Intl.DurationFormat.prototype.formatToParts` is `function`' +); + +verifyProperty(Intl.DurationFormat.prototype, 'formatToParts', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/shell.js b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/throw-invoked-as-func.js b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/throw-invoked-as-func.js new file mode 100644 index 000000000000..cecb81b55198 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/formatToParts/throw-invoked-as-func.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat.prototype.format +description: basic tests internal slot initialization and call receiver errors +info: | + Intl.DurationFormat.prototype.formatToParts ( duration ) + (...) + 2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]). +features: [Intl.DurationFormat] +---*/ + +const df = new Intl.DurationFormat(); + +// Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]). +let f = df['formatToParts']; + +assert.sameValue(typeof f, 'function'); +assert.throws(TypeError, () => { f('PT12.3456S') }); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/prototype_attributes.js b/js/src/tests/test262/intl402/DurationFormat/prototype/prototype_attributes.js new file mode 100644 index 000000000000..459541e7cdee --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/prototype_attributes.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright (C) 2021 Nikhil Singhal. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat.prototype +description: Prototype attributes verification +info: | + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. +features: [Intl.DurationFormat] +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.DurationFormat, "prototype"); +verifyNotWritable(Intl.DurationFormat, "prototype"); +verifyNotConfigurable(Intl.DurationFormat, "prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/length.js new file mode 100644 index 000000000000..f59ec0500f45 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/length.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat.prototype.resolvedoptions +description: > + Intl.DurationFormat.prototype.resolvedOptions.length is 0. +info: | + Intl.DurationFormat.prototype.resolvedOptions () + + 17 ECMAScript Standard Built-in Objects: + + Every built-in function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which + are shown using the form «...name») are not included in the default + argument count. + Unless otherwise specified, the length property of a built-in function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. + +features: [Intl.DurationFormat] +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DurationFormat.prototype.resolvedOptions.length, 0); + +verifyProperty(Intl.DurationFormat.prototype.resolvedOptions, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/name.js new file mode 100644 index 000000000000..dbab5aaa2bed --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/name.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat.prototype.resolvedOptions +description: Checks the "name" property of Intl.DurationFormat.prototype.resolvedOptions(). +info: | + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. + +includes: [propertyHelper.js] +features: [Intl.DurationFormat] +---*/ + +verifyProperty(Intl.DurationFormat.prototype.resolvedOptions, "name", { + value: "resolvedOptions", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 000000000000..1b667908c42d --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DurationFormat.prototype.resolvedOptions +description: Property descriptor of Intl.DurationFormat.prototype.resolvedOptions +includes: [propertyHelper.js] +features: [Intl.DurationFormat] +---*/ + +assert.sameValue( + typeof Intl.DurationFormat.prototype.resolvedOptions, + 'function', + '`typeof Intl.DurationFormat.prototype.resolvedOptions` is `function`' +); + +verifyProperty(Intl.DurationFormat.prototype, 'resolvedOptions', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/throw-invoked-as-func.js b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/throw-invoked-as-func.js new file mode 100644 index 000000000000..a75c9f2bb425 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/resolvedOptions/throw-invoked-as-func.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat.prototype.resolvedOptions +description: basic tests internal slot initialization and call receiver errors +info: | + Intl.DurationFormat.prototype.resolvedOptions ( ) + (...) + 2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]). +features: [Intl.DurationFormat] +---*/ + +const df = new Intl.DurationFormat(); + +// Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]). +let f = df['resolvedOptions']; + +assert.sameValue(typeof f, 'function'); +assert.throws(TypeError, () => { f() }); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/shell.js b/js/src/tests/test262/intl402/DurationFormat/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/toString.js b/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/toString.js new file mode 100644 index 000000000000..b02fe5396729 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/toString.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DurationFormat.prototype-@@tostringtag +description: > + Object.prototype.toString utilizes Intl.DurationFormat.prototype[@@toStringTag]. +info: | + Intl.DurationFormat.prototype [ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.DurationFormat". + +features: [Intl.DurationFormat, Symbol.toStringTag] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.DurationFormat.prototype), "[object Intl.DurationFormat]"); +assert.sameValue(Object.prototype.toString.call(new Intl.DurationFormat()), "[object Intl.DurationFormat]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/toStringTag.js new file mode 100644 index 000000000000..f8cd2882d255 --- /dev/null +++ b/js/src/tests/test262/intl402/DurationFormat/prototype/toStringTag/toStringTag.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Intl.DurationFormat is not supported +// Copyright (C) 2021 Nikhil Singhal. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +// Copyright 2022 Igalia, S.L. All rights reserved. + +/*--- +esid: sec-intl.DurationFormat.prototype-@@tostringtag +description: > + Property descriptor of Intl.DurationFormat.prototype[@@toStringTag]. +info: | + Intl.DurationFormat.prototype [ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.DurationFormat". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. + +features: [Intl.DurationFormat, Symbol.toStringTag] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.DurationFormat.prototype, Symbol.toStringTag, { + value: "Intl.DurationFormat", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DurationFormat/shell.js b/js/src/tests/test262/intl402/DurationFormat/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/browser.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/browser.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/browser.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/fails-on-distinct-temporal-types.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/fails-on-distinct-temporal-types.js new file mode 100644 index 000000000000..46c5f25a92de --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/fails-on-distinct-temporal-types.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.formatRange +description: formatRange fails if given arguments of different Temporal types +features: [Temporal] +---*/ + +const us = new Intl.DateTimeFormat('en-US'); + +const instances = { + date: new Date(1580527800000), + instant: new Temporal.Instant(0n), + plaindate: new Temporal.PlainDate(2000, 5, 2), + plaindatetime: new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321), + plainmonthday: new Temporal.PlainMonthDay(5, 2), + plaintime: new Temporal.PlainTime(13, 37), + plainyearmonth: new Temporal.PlainYearMonth(2019, 6), + zoneddatetime: new Temporal.ZonedDateTime(0n, 'America/Kentucky/Louisville') +}; + +Object.entries(instances).forEach(([typeName, instance]) => { + Object.entries(instances).forEach(([anotherTypeName, anotherInstance]) => { + if (typeName !== anotherTypeName) { + assert.throws( + TypeError, + () => { us.formatRange(instance, anotherInstance); }, + 'formatRange: bad arguments (' + typeName + ' and ' + anotherTypeName + ')' + ); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/shell.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRange/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/browser.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/fails-on-distinct-temporal-types.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/fails-on-distinct-temporal-types.js new file mode 100644 index 000000000000..ca195d6fdf1d --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/fails-on-distinct-temporal-types.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.formatRangeToParts +description: formatRange fails if given arguments of different Temporal types +features: [Temporal] +---*/ + +const us = new Intl.DateTimeFormat('en-US'); + +const instances = { + date: new Date(1580527800000), + instant: new Temporal.Instant(0n), + plaindate: new Temporal.PlainDate(2000, 5, 2), + plaindatetime: new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321), + plainmonthday: new Temporal.PlainMonthDay(5, 2), + plaintime: new Temporal.PlainTime(13, 37), + plainyearmonth: new Temporal.PlainYearMonth(2019, 6), + zoneddatetime: new Temporal.ZonedDateTime(0n, 'America/Kentucky/Louisville') +}; + +Object.entries(instances).forEach(([typeName, instance]) => { + Object.entries(instances).forEach(([anotherTypeName, anotherInstance]) => { + if (typeName !== anotherTypeName) { + assert.throws( + TypeError, + () => { us.formatRangeToParts(instance, anotherInstance); }, + 'formatRange: bad arguments (' + typeName + ' and ' + anotherTypeName + ')' + ); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/shell.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/shell.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/DateTimeFormat/shell.js b/js/src/tests/test262/intl402/Intl/DateTimeFormat/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/duplicates.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/duplicates.js index 3f0b9e93fc0e..a3697544c059 100644 --- a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/duplicates.js +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/duplicates.js @@ -11,11 +11,10 @@ info: | includes: [compareArray.js] ---*/ -assert(compareArray( - Intl.getCanonicalLocales( - ['ab-cd', 'ff', 'de-rt', 'ab-Cd']), ['ab-CD', 'ff', 'de-RT'])); +assert.compareArray(Intl.getCanonicalLocales( + ['ab-cd', 'ff', 'de-rt', 'ab-Cd']), ['ab-CD', 'ff', 'de-RT']); var locales = Intl.getCanonicalLocales(['en-US', 'en-US']); -assert(compareArray(locales, ['en-US']), 'en-US'); +assert.compareArray(locales, ['en-US'], 'en-US'); reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/locales-is-not-a-string.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/locales-is-not-a-string.js index bff120d27572..2aa0565785f1 100644 --- a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/locales-is-not-a-string.js +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/locales-is-not-a-string.js @@ -15,7 +15,7 @@ features: [Symbol] var gCL = Intl.getCanonicalLocales; function assertArray(l, r) { - assert(compareArray(l, r), r); + assert.compareArray(l, r, r); } assertArray(gCL(), []); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/main.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/main.js index 6e27ca6a5e6b..68814318386a 100644 --- a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/main.js +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/main.js @@ -14,7 +14,7 @@ includes: [compareArray.js] var gCL = Intl.getCanonicalLocales; function assertArray(l, r) { - assert(compareArray(l, r), r); + assert.compareArray(l, r, r); } assertArray(gCL(), []); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-arg-length.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-arg-length.js index 12d4e8c56710..3d781c03010e 100644 --- a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-arg-length.js +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-arg-length.js @@ -32,8 +32,11 @@ Object.defineProperty(locales, "length", { get: function() { return "1" } }); -assert(compareArray(Intl.getCanonicalLocales(locales), ['en-US']), - "should return one element if locales.length is '1'"); +assert.compareArray( + Intl.getCanonicalLocales(locales), + ['en-US'], + "should return one element if locales.length is '1'" +); var locales = { '0': 'en-US', @@ -44,8 +47,11 @@ Object.defineProperty(locales, "length", { get: function() { return 1.3 } }); -assert(compareArray(Intl.getCanonicalLocales(locales), ['en-US']), - "should return one element if locales.length is 1.3"); +assert.compareArray( + Intl.getCanonicalLocales(locales), + ['en-US'], + "should return one element if locales.length is 1.3" +); var locales = { '0': 'en-US', @@ -69,8 +75,11 @@ Object.defineProperty(locales, "length", { get: function() { return -Infinity } }); -assert(compareArray(Intl.getCanonicalLocales(locales), []), - "should return empty array if locales.length is -Infinity"); +assert.compareArray( + Intl.getCanonicalLocales(locales), + [], + "should return empty array if locales.length is -Infinity" +); var locales = { length: -Math.pow(2, 32) + 1 @@ -80,8 +89,11 @@ Object.defineProperty(locales, "0", { get: function() { throw new Error("must not be gotten!"); } }) -assert(compareArray(Intl.getCanonicalLocales(locales), []), - "should return empty array if locales.length is a negative value"); +assert.compareArray( + Intl.getCanonicalLocales(locales), + [], + "should return empty array if locales.length is a negative value" +); var count = 0; var locs = { get length() { if (count++ > 0) throw 42; return 0; } }; diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-push.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-push.js index c2e2938be1c8..d8c8a794ca28 100644 --- a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-push.js +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-push.js @@ -16,6 +16,6 @@ Array.prototype.push = function() { throw 42; }; // must not throw 42, might if push is used var arr = Intl.getCanonicalLocales(["en-US"]); -assert(compareArray(arr, ["en-US"])); +assert.compareArray(arr, ["en-US"]); reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/to-string.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/to-string.js index ebc0a5ba3cd2..464a4cb03b21 100644 --- a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/to-string.js +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/to-string.js @@ -17,6 +17,6 @@ var locales = { length: 2 }; -assert(compareArray(Intl.getCanonicalLocales(locales), [ "en-US", "pt-BR" ])); +assert.compareArray(Intl.getCanonicalLocales(locales), [ "en-US", "pt-BR" ]); reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/weird-cases.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/weird-cases.js index adf48ad404f9..e7b680b570de 100644 --- a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/weird-cases.js +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/weird-cases.js @@ -20,7 +20,7 @@ var weirdCases = ]; weirdCases.forEach(function (weird) { - assert(compareArray(Intl.getCanonicalLocales(weird), [weird])); + assert.compareArray(Intl.getCanonicalLocales(weird), [weird]); }); reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/browser.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/builtin.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/builtin.js new file mode 100644 index 000000000000..8689ef54afa9 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/builtin.js @@ -0,0 +1,44 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + Intl.supportedValuesOf is a built-in function object.. +info: | + Intl.supportedValuesOf ( key ) + + 18 ECMAScript Standard Built-in Objects: + Unless specified otherwise, a built-in object that is callable as a function + is a built-in function object with the characteristics described in 10.3. + Unless specified otherwise, the [[Extensible]] internal slot of a built-in + object initially has the value true. + + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial value + of the expression Function.prototype (20.2.3), as the value of its + [[Prototype]] internal slot. + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. +includes: [isConstructor.js] +features: [Intl-enumeration, Reflect.construct] +---*/ + +assert.sameValue(typeof Intl.supportedValuesOf, "function", + "Intl.supportedValuesOf is a function"); + +assert(!Object.prototype.hasOwnProperty.call(Intl.supportedValuesOf, "prototype"), + "Intl.supportedValuesOf doesn't have an own 'prototype' property"); + +assert(Object.isExtensible(Intl.supportedValuesOf), + "Built-in objects must be extensible"); + +assert.sameValue(Object.getPrototypeOf(Intl.supportedValuesOf), Function.prototype, + "[[Prototype]] of Intl.supportedValuesOf is Function.prototype"); + +assert(!isConstructor(Intl.supportedValuesOf), + "Intl.supportedValuesOf not a constructor function"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars-accepted-by-DateTimeFormat.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars-accepted-by-DateTimeFormat.js new file mode 100644 index 000000000000..b78e76f008d1 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars-accepted-by-DateTimeFormat.js @@ -0,0 +1,47 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "calendar" values can be used with DateTimeFormat. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + 2. If key is "calendar", then + a. Let list be ! AvailableCalendars( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableCalendars ( ) + The AvailableCalendars abstract operation returns a List, ordered as if an + Array of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains unique calendar types identifying the + calendars for which the implementation provides the functionality of + Intl.DateTimeFormat objects. The list must include "gregory". +includes: [testIntl.js] +locale: [en] +features: [Intl-enumeration] +---*/ + +const calendars = Intl.supportedValuesOf("calendar"); + +for (let calendar of calendars) { + let obj = new Intl.DateTimeFormat("en", {calendar}); + assert.sameValue(obj.resolvedOptions().calendar, calendar, + `${calendar} is supported by DateTimeFormat`); +} + +for (let calendar of allCalendars()) { + let obj = new Intl.DateTimeFormat("en", {calendar}); + if (obj.resolvedOptions().calendar === calendar) { + assert(calendars.includes(calendar), + `${calendar} supported but not returned by supportedValuesOf`); + } else { + assert(!calendars.includes(calendar), + `${calendar} not supported but returned by supportedValuesOf`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars-accepted-by-DisplayNames.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars-accepted-by-DisplayNames.js new file mode 100644 index 000000000000..bc002f4ed3c4 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars-accepted-by-DisplayNames.js @@ -0,0 +1,47 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "calendar" values can be used with DisplayNames. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + 2. If key is "calendar", then + a. Let list be ! AvailableCalendars( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableCalendars ( ) + The AvailableCalendars abstract operation returns a List, ordered as if an + Array of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains unique calendar types identifying the + calendars for which the implementation provides the functionality of + Intl.DateTimeFormat objects. The list must include "gregory". +includes: [testIntl.js] +locale: [en] +features: [Intl-enumeration, Intl.DisplayNames-v2] +---*/ + +const calendars = Intl.supportedValuesOf("calendar"); + +const obj = new Intl.DisplayNames("en", {type: "calendar", fallback: "none"}); + +for (let calendar of calendars) { + assert.sameValue(typeof obj.of(calendar), "string", + `${calendar} is supported by DisplayNames`); +} + +for (let calendar of allCalendars()) { + if (typeof obj.of(calendar) === "string") { + assert(calendars.includes(calendar), + `${calendar} supported but not returned by supportedValuesOf`); + } else { + assert(!calendars.includes(calendar), + `${calendar} not supported but returned by supportedValuesOf`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars.js new file mode 100644 index 000000000000..4cf4aec7a19f --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/calendars.js @@ -0,0 +1,56 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "calendar" values are sorted, unique, and match the type production. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + 2. If key is "calendar", then + a. Let list be ! AvailableCalendars( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableCalendars ( ) + The AvailableCalendars abstract operation returns a List, ordered as if an + Array of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains unique calendar types identifying the + calendars for which the implementation provides the functionality of + Intl.DateTimeFormat objects. The list must include "gregory". +includes: [compareArray.js] +features: [Intl-enumeration, Intl.Locale] +---*/ + +const calendars = Intl.supportedValuesOf("calendar"); + +assert(Array.isArray(calendars), "Returns an Array object."); +assert.sameValue(Object.getPrototypeOf(calendars), Array.prototype, + "The array prototype is Array.prototype"); + +const otherCalendars = Intl.supportedValuesOf("calendar"); +assert.notSameValue(otherCalendars, calendars, + "Returns a new array object for each call."); + +assert.compareArray(calendars, otherCalendars.sort(), + "The array is sorted."); + +assert.sameValue(new Set(calendars).size, calendars.length, + "The array doesn't contain duplicates."); + +// https://unicode.org/reports/tr35/tr35.html#Unicode_locale_identifier +const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/; +for (let calendar of calendars) { + assert(typeRE.test(calendar), `${calendar} matches the 'type' production`); +} + +for (let calendar of calendars) { + assert.sameValue(new Intl.Locale("und", {calendar}).calendar, calendar, + `${calendar} is canonicalised`); +} + +assert(calendars.includes("gregory"), "Includes the Gregorian calendar."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/coerced-to-string.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/coerced-to-string.js new file mode 100644 index 000000000000..b5354265b9d3 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/coerced-to-string.js @@ -0,0 +1,38 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + Input key is coerced with ToString. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + 2. If key is "calendar", then + a. Let list be ! AvailableCalendars( ). + ... + 9. Return ! CreateArrayFromList( list ). +includes: [compareArray.js] +features: [Intl-enumeration] +---*/ + +const calendars = Intl.supportedValuesOf("calendar"); + +// ToString on a String object. +assert.compareArray(Intl.supportedValuesOf(new String("calendar")), calendars); + +// ToString on a plain object. +let obj = { + toString() { + return "calendar"; + } +}; +assert.compareArray(Intl.supportedValuesOf(obj), calendars); + +// ToString() of a symbol throws a TypeError. +assert.throws(TypeError, function() { + Intl.supportedValuesOf(Symbol()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/collations-accepted-by-Collator.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/collations-accepted-by-Collator.js new file mode 100644 index 000000000000..ca972afe334b --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/collations-accepted-by-Collator.js @@ -0,0 +1,83 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "collation" values can be used with Collator. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 3. Else if key is "collation", then + a. Let list be ! AvailableCollations( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableCollations ( ) + The AvailableCollations abstract operation returns a List, ordered as if an + Array of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains unique collation types identifying the + collations for which the implementation provides the functionality of + Intl.Collator objects. +includes: [testIntl.js] +locale: [en, ar, de, es, ko, ln, si, sv, zh] +features: [Intl-enumeration] +---*/ + +const collations = Intl.supportedValuesOf("collation"); + +// Not all locales support all possible collations, so test the minimal set to +// cover all supported collations. +// +// The list of all collations can be derived from +// . +// +// Note: "standard" and "search" are explicitly disallowed by Intl.Collator. +const locales = [ + "en", // ducet, emoji, eor + "ar", // compat + "de", // phonebk + "es", // trad + "hi", // direct + "ko", // searchjl + "ln", // phonetic + "si", // dict + "sv", // reformed + "zh", // big5han, gb2312, pinyin, stroke, unihan, zhuyin +]; + +for (let collation of collations) { + let supported = false; + for (let locale of locales) { + let obj = new Intl.Collator(locale, {collation}); + if (obj.resolvedOptions().collation === collation) { + supported = true; + break; + } + } + + assert(supported, `${collation} is supported by Collator`); +} + +for (let collation of allCollations()) { + let supported = false; + for (let locale of locales) { + let obj = new Intl.Collator(locale, {collation}); + if (obj.resolvedOptions().collation === collation) { + supported = true; + break; + } + } + + if (supported) { + assert(collations.includes(collation), + `${collation} supported but not returned by supportedValuesOf`); + } else { + assert(!collations.includes(collation), + `${collation} not supported but returned by supportedValuesOf`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/collations.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/collations.js new file mode 100644 index 000000000000..9e6623c0afc3 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/collations.js @@ -0,0 +1,58 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "collation" values are sorted, unique, and match the type production. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 3. Else if key is "collation", then + a. Let list be ! AvailableCollations( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableCollations ( ) + The AvailableCollations abstract operation returns a List, ordered as if an + Array of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains unique collation types identifying the + collations for which the implementation provides the functionality of + Intl.Collator objects. +includes: [compareArray.js] +features: [Intl-enumeration, Intl.Locale] +---*/ + +const collations = Intl.supportedValuesOf("collation"); + +assert(Array.isArray(collations), "Returns an Array object."); +assert.sameValue(Object.getPrototypeOf(collations), Array.prototype, + "The array prototype is Array.prototype"); + +const otherCollations = Intl.supportedValuesOf("collation"); +assert.notSameValue(otherCollations, collations, + "Returns a new array object for each call."); + +assert.compareArray(collations, otherCollations.sort(), + "The array is sorted."); + +assert.sameValue(new Set(collations).size, collations.length, + "The array doesn't contain duplicates."); + +// https://unicode.org/reports/tr35/tr35.html#Unicode_locale_identifier +const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/; +for (let collation of collations) { + assert(typeRE.test(collation), `${collation} matches the 'type' production`); +} + +for (let collation of collations) { + assert.sameValue(new Intl.Locale("und", {collation}).collation, collation, + `${collation} is canonicalised`); +} + +assert(!collations.includes("standard"), "Mustn't include the 'standard' collation type."); +assert(!collations.includes("search"), "Mustn't include the 'search' collation type."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies-accepted-by-DisplayNames.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies-accepted-by-DisplayNames.js new file mode 100644 index 000000000000..d6951ff12ca6 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies-accepted-by-DisplayNames.js @@ -0,0 +1,53 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "currency" values can be used with DisplayNames. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 4. Else if key is "currency", then + a. Let list be ! AvailableCurrencies( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableCurrencies ( ) + The AvailableCurrencies abstract operation returns a List, ordered as if an + Array of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains unique, well-formed, and upper case + canonicalized 3-letter ISO 4217 currency codes, identifying the currencies + for which the implementation provides the functionality of Intl.DisplayNames + and Intl.NumberFormat objects. +locale: [en] +features: [Intl-enumeration, Intl.DisplayNames] +---*/ + +const currencies = Intl.supportedValuesOf("currency"); + +const obj = new Intl.DisplayNames("en", {type: "currency", fallback: "none"}); + +for (let currency of currencies) { + assert.sameValue(typeof obj.of(currency), "string", + `${currency} is supported by DisplayNames`); +} + +for (let i = 0x41; i <= 0x5A; ++i) { + for (let j = 0x41; j <= 0x5A; ++j) { + for (let k = 0x41; k <= 0x5A; ++k) { + let currency = String.fromCharCode(i, j, k); + if (typeof obj.of(currency) === "string") { + assert(currencies.includes(currency), + `${currency} supported but not returned by supportedValuesOf`); + } else { + assert(!currencies.includes(currency), + `${currency} not supported but returned by supportedValuesOf`); + } + } + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies-accepted-by-NumberFormat.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies-accepted-by-NumberFormat.js new file mode 100644 index 000000000000..089d0dd32250 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies-accepted-by-NumberFormat.js @@ -0,0 +1,46 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "currency" values can be used with NumberFormat. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 4. Else if key is "currency", then + a. Let list be ! AvailableCurrencies( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableCurrencies ( ) + The AvailableCurrencies abstract operation returns a List, ordered as if an + Array of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains unique, well-formed, and upper case + canonicalized 3-letter ISO 4217 currency codes, identifying the currencies + for which the implementation provides the functionality of Intl.DisplayNames + and Intl.NumberFormat objects. +locale: [en] +features: [Intl-enumeration] +---*/ + +const currencies = Intl.supportedValuesOf("currency"); + +for (let currency of currencies) { + let obj = new Intl.NumberFormat("en", {style: "currency", currency}); + assert.sameValue(obj.resolvedOptions().currency, currency, + `${currency} is supported by NumberFormat`); +} + +// Note: We can't test that additional currency values not present in |currencies| +// aren't supported by Intl.NumberFormat, because PartitionNumberPattern defaults +// to using the currency code itself when the currency is unsupported: +// +// PartitionNumberPattern, step 8.k.iii: +// Let cd be an ILD String value representing currency after x in currencyDisplay form, +// which may depend on x in languages having different plural forms. If the +// implementation does not have such a representation of currency, use currency itself. + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies.js new file mode 100644 index 000000000000..467ee39ca163 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/currencies.js @@ -0,0 +1,50 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "currency" values are sorted, unique, and upper-case canonicalised. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 4. Else if key is "currency", then + a. Let list be ! AvailableCurrencies( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableCurrencies ( ) + The AvailableCurrencies abstract operation returns a List, ordered as if an + Array of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains unique, well-formed, and upper case + canonicalized 3-letter ISO 4217 currency codes, identifying the currencies + for which the implementation provides the functionality of Intl.DisplayNames + and Intl.NumberFormat objects. +includes: [compareArray.js] +features: [Intl-enumeration] +---*/ + +const currencies = Intl.supportedValuesOf("currency"); + +assert(Array.isArray(currencies), "Returns an Array object."); +assert.sameValue(Object.getPrototypeOf(currencies), Array.prototype, + "The array prototype is Array.prototype"); + +const otherCurrencies = Intl.supportedValuesOf("currency"); +assert.notSameValue(otherCurrencies, currencies, + "Returns a new array object for each call."); + +assert.compareArray(currencies, otherCurrencies.sort(), + "The array is sorted."); + +assert.sameValue(new Set(currencies).size, currencies.length, + "The array doesn't contain duplicates."); + +const codeRE = /^[A-Z]{3}$/; +for (let currency of currencies) { + assert(codeRE.test(currency), `${currency} is a 3-letter ISO 4217 currency code`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/invalid-key.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/invalid-key.js new file mode 100644 index 000000000000..07202b4b5dd9 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/invalid-key.js @@ -0,0 +1,45 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + Intl.supportedValuesOf throws a RangeError if the key is invalid. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 8. Else, + a. Throw a RangeError exception. + ... +features: [Intl-enumeration] +---*/ + +const invalidKeys = [ + // Empty string is invalid. + "", + + // Various unsupported keys. + "hourCycle", "locale", "language", "script", "region", + + // Plural form of supported keys not valid. + "calendars", "collations", "currencies", "numberingSystems", "timeZones", "units", + + // Wrong case for supported keys. + "CALENDAR", "Collation", "Currency", "numberingsystem", "timezone", "UNIT", + + // NUL character must be handled correctly. + "calendar\0", + + // Non-string cases. + undefined, null, false, true, NaN, 0, Math.PI, 123n, {}, [], +]; + +for (let key of invalidKeys) { + assert.throws(RangeError, function() { + Intl.supportedValuesOf(key); + }, "key: " + key); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/length.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/length.js new file mode 100644 index 000000000000..39a5d577f0e5 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/length.js @@ -0,0 +1,32 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + Intl.supportedValuesOf.length value and descriptor. +info: | + Intl.supportedValuesOf ( key ) + + 18 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a "length" + property whose value is a non-negative integral Number. Unless otherwise + specified, this value is equal to the number of required parameters shown in + the subclause heading for the function description. Optional parameters and + rest parameters are not included in the parameter count. + + Unless otherwise specified, the "length" property of a built-in function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl-enumeration] +---*/ + +verifyProperty(Intl.supportedValuesOf, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/name.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/name.js new file mode 100644 index 000000000000..c8838bb249bc --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/name.js @@ -0,0 +1,34 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + Intl.supportedValuesOf.name value and descriptor. +info: | + Intl.supportedValuesOf ( key ) + + 18 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a "name" + property whose value is a String. Unless otherwise specified, this value is + the name that is given to the function in this specification. Functions that + are identified as anonymous functions use the empty String as the value of + the "name" property. For functions that are specified as properties of + objects, the name value is the property name string used to access the + function. + + Unless otherwise specified, the "name" property of a built-in function object + has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl-enumeration] +---*/ + +verifyProperty(Intl.supportedValuesOf, "name", { + value: "supportedValuesOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-DateTimeFormat.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-DateTimeFormat.js new file mode 100644 index 000000000000..cf2c83540325 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-DateTimeFormat.js @@ -0,0 +1,50 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "numberingSystem" values can be used with DateTimeFormat. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 5. Else if key is "numberingSystem", then + a. Let list be ! AvailableNumberingSystems( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableNumberingSystems ( ) + The AvailableNumberingSystems abstract operation returns a List, ordered as + if an Array of the same values had been sorted using %Array.prototype.sort% + using undefined as comparefn, that contains unique numbering systems + identifiers identifying the numbering systems for which the implementation + provides the functionality of Intl.DateTimeFormat, Intl.NumberFormat, and + Intl.RelativeTimeFormat objects. The list must include the Numbering System + value of every row of Table 4, except the header row. +includes: [testIntl.js] +locale: [en] +features: [Intl-enumeration] +---*/ + +const numberingSystems = Intl.supportedValuesOf("numberingSystem"); + +for (let numberingSystem of numberingSystems) { + let obj = new Intl.DateTimeFormat("en", {numberingSystem}); + assert.sameValue(obj.resolvedOptions().numberingSystem, numberingSystem, + `${numberingSystem} is supported by DateTimeFormat`); +} + +for (let numberingSystem of allNumberingSystems()) { + let obj = new Intl.DateTimeFormat("en", {numberingSystem}); + if (obj.resolvedOptions().numberingSystem === numberingSystem) { + assert(numberingSystems.includes(numberingSystem), + `${numberingSystem} supported but not returned by supportedValuesOf`); + } else { + assert(!numberingSystems.includes(numberingSystem), + `${numberingSystem} not supported but returned by supportedValuesOf`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-NumberFormat.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-NumberFormat.js new file mode 100644 index 000000000000..347fc7e409f3 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-NumberFormat.js @@ -0,0 +1,50 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "numberingSystem" values can be used with NumberFormat. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 5. Else if key is "numberingSystem", then + a. Let list be ! AvailableNumberingSystems( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableNumberingSystems ( ) + The AvailableNumberingSystems abstract operation returns a List, ordered as + if an Array of the same values had been sorted using %Array.prototype.sort% + using undefined as comparefn, that contains unique numbering systems + identifiers identifying the numbering systems for which the implementation + provides the functionality of Intl.DateTimeFormat, Intl.NumberFormat, and + Intl.RelativeTimeFormat objects. The list must include the Numbering System + value of every row of Table 4, except the header row. +includes: [testIntl.js] +locale: [en] +features: [Intl-enumeration] +---*/ + +const numberingSystems = Intl.supportedValuesOf("numberingSystem"); + +for (let numberingSystem of numberingSystems) { + let obj = new Intl.NumberFormat("en", {numberingSystem}); + assert.sameValue(obj.resolvedOptions().numberingSystem, numberingSystem, + `${numberingSystem} is supported by NumberFormat`); +} + +for (let numberingSystem of allNumberingSystems()) { + let obj = new Intl.NumberFormat("en", {numberingSystem}); + if (obj.resolvedOptions().numberingSystem === numberingSystem) { + assert(numberingSystems.includes(numberingSystem), + `${numberingSystem} supported but not returned by supportedValuesOf`); + } else { + assert(!numberingSystems.includes(numberingSystem), + `${numberingSystem} not supported but returned by supportedValuesOf`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-RelativeTimeFormat.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-RelativeTimeFormat.js new file mode 100644 index 000000000000..33acc2c99822 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-RelativeTimeFormat.js @@ -0,0 +1,50 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "numberingSystem" values can be used with RelativeTimeFormat. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 5. Else if key is "numberingSystem", then + a. Let list be ! AvailableNumberingSystems( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableNumberingSystems ( ) + The AvailableNumberingSystems abstract operation returns a List, ordered as + if an Array of the same values had been sorted using %Array.prototype.sort% + using undefined as comparefn, that contains unique numbering systems + identifiers identifying the numbering systems for which the implementation + provides the functionality of Intl.DateTimeFormat, Intl.NumberFormat, and + Intl.RelativeTimeFormat objects. The list must include the Numbering System + value of every row of Table 4, except the header row. +includes: [testIntl.js] +locale: [en] +features: [Intl-enumeration, Intl.RelativeTimeFormat] +---*/ + +const numberingSystems = Intl.supportedValuesOf("numberingSystem"); + +for (let numberingSystem of numberingSystems) { + let obj = new Intl.RelativeTimeFormat("en", {numberingSystem}); + assert.sameValue(obj.resolvedOptions().numberingSystem, numberingSystem, + `${numberingSystem} is supported by RelativeTimeFormat`); +} + +for (let numberingSystem of allNumberingSystems()) { + let obj = new Intl.RelativeTimeFormat("en", {numberingSystem}); + if (obj.resolvedOptions().numberingSystem === numberingSystem) { + assert(numberingSystems.includes(numberingSystem), + `${numberingSystem} supported but not returned by supportedValuesOf`); + } else { + assert(!numberingSystems.includes(numberingSystem), + `${numberingSystem} not supported but returned by supportedValuesOf`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-with-simple-digit-mappings.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-with-simple-digit-mappings.js new file mode 100644 index 000000000000..0122acd3d37d --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems-with-simple-digit-mappings.js @@ -0,0 +1,38 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "numberingSystem" values contain all numbering systems with simple digit mappings. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 5. Else if key is "numberingSystem", then + a. Let list be ! AvailableNumberingSystems( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableNumberingSystems ( ) + The AvailableNumberingSystems abstract operation returns a List, ordered as + if an Array of the same values had been sorted using %Array.prototype.sort% + using undefined as comparefn, that contains unique numbering systems + identifiers identifying the numbering systems for which the implementation + provides the functionality of Intl.DateTimeFormat, Intl.NumberFormat, and + Intl.RelativeTimeFormat objects. The list must include the Numbering System + value of every row of Table 4, except the header row. +includes: [testIntl.js] +features: [Intl-enumeration] +---*/ + +const numberingSystems = Intl.supportedValuesOf("numberingSystem"); + +// Table 10: Numbering systems with simple digit mappings +for (let numberingSystem of Object.keys(numberingSystemDigits)) { + assert(numberingSystems.includes(numberingSystem), + `${numberingSystem} with simple digit mappings is supported`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems.js new file mode 100644 index 000000000000..cb02432cd78a --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/numberingSystems.js @@ -0,0 +1,57 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "numberingSystem" values are sorted, unique, and match the type production. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 5. Else if key is "numberingSystem", then + a. Let list be ! AvailableNumberingSystems( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableNumberingSystems ( ) + The AvailableNumberingSystems abstract operation returns a List, ordered as + if an Array of the same values had been sorted using %Array.prototype.sort% + using undefined as comparefn, that contains unique numbering systems + identifiers identifying the numbering systems for which the implementation + provides the functionality of Intl.DateTimeFormat, Intl.NumberFormat, and + Intl.RelativeTimeFormat objects. The list must include the Numbering System + value of every row of Table 4, except the header row. +includes: [compareArray.js] +features: [Intl-enumeration, Intl.Locale] +---*/ + +const numberingSystems = Intl.supportedValuesOf("numberingSystem"); + +assert(Array.isArray(numberingSystems), "Returns an Array object."); +assert.sameValue(Object.getPrototypeOf(numberingSystems), Array.prototype, + "The array prototype is Array.prototype"); + +const otherNumberingSystems = Intl.supportedValuesOf("numberingSystem"); +assert.notSameValue(otherNumberingSystems, numberingSystems, + "Returns a new array object for each call."); + +assert.compareArray(numberingSystems, otherNumberingSystems.sort(), + "The array is sorted."); + +assert.sameValue(new Set(numberingSystems).size, numberingSystems.length, + "The array doesn't contain duplicates."); + +// https://unicode.org/reports/tr35/tr35.html#Unicode_locale_identifier +const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/; +for (let numberingSystem of numberingSystems) { + assert(typeRE.test(numberingSystem), `${numberingSystem} matches the 'type' production`); +} + +for (let numberingSystem of numberingSystems) { + assert.sameValue(new Intl.Locale("und", {numberingSystem}).numberingSystem, numberingSystem, + `${numberingSystem} is canonicalised`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/prop-desc.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/prop-desc.js new file mode 100644 index 000000000000..5722b8f3ac26 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/prop-desc.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + Intl.supportedValuesOf property attributes. +info: | + Intl.supportedValuesOf ( key ) + + 18 ECMAScript Standard Built-in Objects: + Every other data property described in clauses 19 through 28 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [Intl-enumeration] +---*/ + +verifyProperty(Intl, "supportedValuesOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/shell.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/timeZones-accepted-by-DateTimeFormat.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/timeZones-accepted-by-DateTimeFormat.js new file mode 100644 index 000000000000..b2be51b737ba --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/timeZones-accepted-by-DateTimeFormat.js @@ -0,0 +1,46 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "timeZone" values can be used with DateTimeFormat. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 6. Else if key is "timeZone", then + a. Let list be ! AvailableTimeZones( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableTimeZones () + The AvailableTimeZones abstract operation returns a sorted List of supported + Zone and Link names in the IANA Time Zone Database. The following steps are + taken: + + 1. Let names be a List of all supported Zone and Link names in the IANA Time + Zone Database. + 2. Let result be a new empty List. + 3. For each element name of names, do + a. Assert: ! IsValidTimeZoneName( name ) is true. + b. Let canonical be ! CanonicalizeTimeZoneName( name ). + c. If result does not contain an element equal to canonical, then + i. Append canonical to the end of result. + 4. Sort result in order as if an Array of the same values had been sorted using + %Array.prototype.sort% using undefined as comparefn. + 5. Return result. +locale: [en] +features: [Intl-enumeration] +---*/ + +const timeZones = Intl.supportedValuesOf("timeZone"); + +for (let timeZone of timeZones) { + let obj = new Intl.DateTimeFormat("en", {timeZone}); + assert.sameValue(obj.resolvedOptions().timeZone, timeZone, + `${timeZone} is supported by DateTimeFormat`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/timeZones.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/timeZones.js new file mode 100644 index 000000000000..0f12d4c9e4c0 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/timeZones.js @@ -0,0 +1,59 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "timeZone" values are sorted, unique, and canonicalised. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 6. Else if key is "timeZone", then + a. Let list be ! AvailableTimeZones( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableTimeZones () + The AvailableTimeZones abstract operation returns a sorted List of supported + Zone and Link names in the IANA Time Zone Database. The following steps are + taken: + + 1. Let names be a List of all supported Zone and Link names in the IANA Time + Zone Database. + 2. Let result be a new empty List. + 3. For each element name of names, do + a. Assert: ! IsValidTimeZoneName( name ) is true. + b. Let canonical be ! CanonicalizeTimeZoneName( name ). + c. If result does not contain an element equal to canonical, then + i. Append canonical to the end of result. + 4. Sort result in order as if an Array of the same values had been sorted using + %Array.prototype.sort% using undefined as comparefn. + 5. Return result. +includes: [compareArray.js, testIntl.js] +features: [Intl-enumeration] +---*/ + +const timeZones = Intl.supportedValuesOf("timeZone"); + +assert(Array.isArray(timeZones), "Returns an Array object."); +assert.sameValue(Object.getPrototypeOf(timeZones), Array.prototype, + "The array prototype is Array.prototype"); + +const otherTimeZones = Intl.supportedValuesOf("timeZone"); +assert.notSameValue(otherTimeZones, timeZones, + "Returns a new array object for each call."); + +assert.compareArray(timeZones, otherTimeZones.sort(), + "The array is sorted."); + +assert.sameValue(new Set(timeZones).size, timeZones.length, + "The array doesn't contain duplicates."); + +for (let timeZone of timeZones) { + assert(isCanonicalizedStructurallyValidTimeZoneName(timeZone), + `${timeZone} is a canonicalised and structurally valid time zone name`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/units-accepted-by-NumberFormat.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/units-accepted-by-NumberFormat.js new file mode 100644 index 000000000000..5a23660e98e5 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/units-accepted-by-NumberFormat.js @@ -0,0 +1,47 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "unit" values can be used with NumberFormat. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 7. Else if key is "unit", then + a. Let list be ! AvailableUnits( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableUnits ( ) + The AvailableUnits abstract operation returns a List, ordered as if an Array + of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains the unique values of simple unit + identifiers listed in every row of Table 1, except the header row. +includes: [testIntl.js] +locale: [en] +features: [Intl-enumeration] +---*/ + +const units = Intl.supportedValuesOf("unit"); + +for (let unit of units) { + let obj = new Intl.NumberFormat("en", {style: "unit", unit}); + assert.sameValue(obj.resolvedOptions().unit, unit, + `${unit} is supported by NumberFormat`); +} + +for (let unit of allSimpleSanctionedUnits()) { + let obj = new Intl.NumberFormat("en", {style: "unit", unit}); + if (obj.resolvedOptions().unit === unit) { + assert(units.includes(unit), + `${unit} supported but not returned by supportedValuesOf`); + } else { + assert(!units.includes(unit), + `${unit} not supported but returned by supportedValuesOf`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/supportedValuesOf/units.js b/js/src/tests/test262/intl402/Intl/supportedValuesOf/units.js new file mode 100644 index 000000000000..864121a6e385 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/supportedValuesOf/units.js @@ -0,0 +1,50 @@ +// Copyright (C) 2021 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.supportedvaluesof +description: > + The returned "unit" values are sorted, unique, and well-formed. +info: | + Intl.supportedValuesOf ( key ) + + 1. Let key be ? ToString(key). + ... + 7. Else if key is "unit", then + a. Let list be ! AvailableUnits( ). + ... + 9. Return ! CreateArrayFromList( list ). + + AvailableUnits ( ) + The AvailableUnits abstract operation returns a List, ordered as if an Array + of the same values had been sorted using %Array.prototype.sort% using + undefined as comparefn, that contains the unique values of simple unit + identifiers listed in every row of Table 1, except the header row. +includes: [compareArray.js, testIntl.js] +features: [Intl-enumeration] +---*/ + +const units = Intl.supportedValuesOf("unit"); + +assert(Array.isArray(units), "Returns an Array object."); +assert.sameValue(Object.getPrototypeOf(units), Array.prototype, + "The array prototype is Array.prototype"); + +const otherUnits = Intl.supportedValuesOf("unit"); +assert.notSameValue(otherUnits, units, + "Returns a new array object for each call."); + +assert.compareArray(units, otherUnits.sort(), + "The array is sorted."); + +assert.sameValue(new Set(units).size, units.length, + "The array doesn't contain duplicates."); + +const simpleSanctioned = allSimpleSanctionedUnits(); + +for (let unit of units) { + assert(simpleSanctioned.includes(unit), `${unit} is a simple, sanctioned unit`); + assert(!unit.includes("-per-"), `${unit} isn't a compound unit`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-undefined.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-undefined.js index b5b66041f42a..ced482c74b31 100644 --- a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-undefined.js +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-undefined.js @@ -16,6 +16,6 @@ includes: [compareArray.js] let lf = new Intl.ListFormat(); -assert(compareArray([], lf.formatToParts(undefined))); +assert.compareArray([], lf.formatToParts(undefined)); reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/order.js index f71c0489b3b9..a1231a3696a5 100644 --- a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/order.js +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/order.js @@ -4,7 +4,6 @@ /*--- esid: sec-Intl.ListFormat.prototype.resolvedOptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [compareArray.js] features: [Intl.ListFormat] ---*/ @@ -16,6 +15,14 @@ const expected = [ "style", ]; -assert.compareArray(Object.getOwnPropertyNames(options), expected); +const actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); +} reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/weekInfo/output-object-keys.js b/js/src/tests/test262/intl402/Locale/prototype/weekInfo/output-object-keys.js index 901d0a0012f6..48b0ab297169 100644 --- a/js/src/tests/test262/intl402/Locale/prototype/weekInfo/output-object-keys.js +++ b/js/src/tests/test262/intl402/Locale/prototype/weekInfo/output-object-keys.js @@ -1,5 +1,6 @@ // |reftest| skip -- Intl.Locale-info is not supported // Copyright 2021 Igalia, S.L. All rights reserved. +// Copyright 2021 Apple Inc. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- @@ -29,7 +30,7 @@ function isIntegerBetweenOneAndSeven(value) { return value === 1 || value === 2 || value === 3 || value === 4 || value === 5 || value === 6 || value === 7; } -assert.compareArray(Reflect.ownKeys(result), ['firstDay', 'weekendStart', 'weekendEnd', 'minimalDays']); +assert.compareArray(Reflect.ownKeys(result), ['firstDay', 'weekend', 'minimalDays']); verifyProperty(result, 'firstDay', { writable: true, @@ -41,25 +42,19 @@ assert( '`firstDay` must be an integer between one and seven (inclusive)' ); -verifyProperty(result, 'weekendStart', { +verifyProperty(result, 'weekend', { writable: true, enumerable: true, configurable: true }); assert( - isIntegerBetweenOneAndSeven(new Intl.Locale('en').weekInfo.weekendStart), - '`weekendStart` must be an integer between one and seven (inclusive)' + new Intl.Locale('en').weekInfo.weekend.every(isIntegerBetweenOneAndSeven), + '`weekend` must include integers between one and seven (inclusive)' ); -verifyProperty(result, 'weekendEnd', { - writable: true, - enumerable: true, - configurable: true -}); -assert( - isIntegerBetweenOneAndSeven(new Intl.Locale('en').weekInfo.weekendEnd), - '`weekendEnd` must be an integer between one and seven (inclusive)' -); +let original = new Intl.Locale('en').weekInfo.weekend; +let sorted = original.slice().sort(); +assert.compareArray(original, sorted); verifyProperty(result, 'minimalDays', { writable: true, diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-roundingMode-invalid.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-roundingMode-invalid.js new file mode 100644 index 000000000000..0d1e9bc488f3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-roundingMode-invalid.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: Abrupt completion from invalid values for `roundingMode` +features: [Intl.NumberFormat-v3] +---*/ + +assert.throws(RangeError, function() { + new Intl.NumberFormat('en', {roundingMode: null}); +}, 'null'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat('en', {roundingMode: 3}); +}, 'number'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat('en', {roundingMode: true}); +}, 'boolean'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat('en', {roundingMode: 'HalfExpand'}); +}, 'invalid string'); + +var symbol = Symbol('halfExpand'); +assert.throws(TypeError, function() { + new Intl.NumberFormat('en', {roundingMode: symbol}); +}, 'Symbol'); + +var brokenToString = { toString: function() { throw new Test262Error(); } }; +assert.throws(Test262Error, function() { + new Intl.NumberFormat('en', {roundingMode: brokenToString}); +}, 'broken `toString` implementation'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-increment.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-increment.js new file mode 100644 index 000000000000..a6578e01dab5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-increment.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: > + Exception from accessing the "roundingIncrement" option for the NumberFormat + constructor should be propagated to the caller +features: [Intl.NumberFormat-v3] +---*/ + +assert.throws(Test262Error, function() { + new Intl.NumberFormat('en', { + get roundingIncrement() { + throw new Test262Error(); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-mode.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-mode.js new file mode 100644 index 000000000000..f32e7db9ae72 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-mode.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: > + Exception from accessing the "roundingMode" option for the NumberFormat + constructor should be propagated to the caller +features: [Intl.NumberFormat-v3] +---*/ + +assert.throws(Test262Error, function() { + new Intl.NumberFormat('en', { + get roundingMode() { + throw new Test262Error(); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-priority.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-priority.js new file mode 100644 index 000000000000..ec6f9863b6b4 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-priority.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: > + Exception from accessing the "roundingPriority" option for the NumberFormat + constructor should be propagated to the caller +features: [Intl.NumberFormat-v3] +---*/ + +assert.throws(Test262Error, function() { + new Intl.NumberFormat('en', { + get roundingPriority() { + throw new Test262Error(); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-trailing-zero-display.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-trailing-zero-display.js new file mode 100644 index 000000000000..3d585dfebaaa --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-trailing-zero-display.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: > + Exception from accessing the "trailingZeroDisplay" option for the + NumberFormat constructor should be propagated to the caller +features: [Intl.NumberFormat-v3] +---*/ + +assert.throws(Test262Error, function() { + new Intl.NumberFormat('en', { + get trailingZeroDisplay() { + throw new Test262Error(); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js b/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js new file mode 100644 index 000000000000..d18cd71e2369 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js @@ -0,0 +1,47 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: Rejects invalid values for roundingIncrement option. +features: [Intl.NumberFormat-v3] +---*/ + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 0}); +}, '0'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 3}); +}, '3'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 4}); +}, '4'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 5000.1}); +}, '5000.1'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 5001}); +}, '5001'); + +assert.throws(TypeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 2, roundingPriority: 'morePrecision'}); +}, '2, roundingType is "morePrecision"'); + +assert.throws(TypeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 2, roundingPriority: 'lessPrecision'}); +}, '2, roundingType is "lessPrecision"'); + +assert.throws(TypeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 2, minimumSignificantDigits: 1}); +}, '2, roundingType is "significantDigits"'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 2, maximumFractionDigits:3 , minimumFractionDigits:2 }); +}, '"maximumFractionDigits" is not equal to "minimumFractionDigits"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement.js b/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement.js new file mode 100644 index 000000000000..373c43e65c94 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: Checks handling of the roundingIncrement option to the NumberFormat constructor. +includes: [compareArray.js] +features: [Intl.NumberFormat-v3] +---*/ + +const values = [ + [undefined, 1], + [1, 1], + [2, 2], + [5, 5], + [10, 10], + [20, 20], + [25, 25], + [50, 50], + [100, 100], + [200, 200], + [250, 250], + [500, 500], + [1000, 1000], + [2000, 2000], + [2500, 2500], + [5000, 5000], + [true, 1], + ["2", 2], + [{valueOf: function() { return 5; }}, 5], +]; + +for (const [value, expected] of values) { + const callOrder = []; + const nf = new Intl.NumberFormat([], { + get notation() { + callOrder.push("notation"); + return "standard"; + }, + get roundingIncrement() { + callOrder.push("roundingIncrement"); + return value; + } + }); + const resolvedOptions = nf.resolvedOptions(); + assert("roundingIncrement" in resolvedOptions, "has property for value " + value); + assert.sameValue(resolvedOptions.roundingIncrement, expected); + + assert.compareArray(callOrder, ["notation", "roundingIncrement"]); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay-negative.js b/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay-negative.js new file mode 100644 index 000000000000..d48f2ada2c1e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay-negative.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 32. Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero", "negative" », "auto"). + 33. Set numberFormat.[[SignDisplay]] to signDisplay. +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat([], { + signDisplay: 'negative', +}); +const resolvedOptions = nf.resolvedOptions(); + +verifyProperty(resolvedOptions, 'signDisplay', { + value: 'negative', + writable: true, + enumerable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay-invalid.js b/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay-invalid.js new file mode 100644 index 000000000000..f425649b298c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay-invalid.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: Rejects invalid values for trailingZeroDisplay option. +features: [Intl.NumberFormat-v3] +---*/ + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {trailingZeroDisplay: ''}); +}, 'empty string'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {trailingZeroDisplay: 'Auto'}); +}, 'Auto'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {trailingZeroDisplay: 'StripIfInteger'}); +}, 'StripIfInteger'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {trailingZeroDisplay: 'stripifinteger'}); +}, 'stripifinteger'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {trailingZeroDisplay: ' auto'}); +}, '" auto" (with leading space)'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {trailingZeroDisplay: 'auto '}); +}, '"auto " (with trailing space)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay.js b/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay.js new file mode 100644 index 000000000000..0951190aafe0 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-initializenumberformat +description: Checks handling of the trailingZeroDisplay option to the NumberFormat constructor. +includes: [compareArray.js] +features: [Intl.NumberFormat-v3] +---*/ + +const values = [ + [undefined, "auto"], + ["auto", "auto"], + ["stripIfInteger", "stripIfInteger"], + [{toString: function() { return "stripIfInteger"; }}, "stripIfInteger"], +]; + +for (const [value, expected] of values) { + const callOrder = []; + const nf = new Intl.NumberFormat([], { + get roundingIncrement() { + callOrder.push("roundingIncrement"); + return 1; + }, + get trailingZeroDisplay() { + callOrder.push("trailingZeroDisplay"); + return value; + } + }); + const resolvedOptions = nf.resolvedOptions(); + assert("trailingZeroDisplay" in resolvedOptions, "has property for value " + value); + assert.sameValue(resolvedOptions.trailingZeroDisplay, expected); + + assert.compareArray(callOrder, ["roundingIncrement", "trailingZeroDisplay"]); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js b/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js index b14981cf7a80..36f2e8a002ff 100644 --- a/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js @@ -4,6 +4,7 @@ /*--- esid: sec-initializenumberformat description: Checks handling of the unit style. +includes: [testIntl.js] features: [Intl.NumberFormat-unified] ---*/ @@ -51,51 +52,7 @@ function check(unit) { assert.sameValue(options.unit, unit); } -const units = [ - "acre", - "bit", - "byte", - "celsius", - "centimeter", - "day", - "degree", - "fahrenheit", - "fluid-ounce", - "foot", - "gallon", - "gigabit", - "gigabyte", - "gram", - "hectare", - "hour", - "inch", - "kilobit", - "kilobyte", - "kilogram", - "kilometer", - "liter", - "megabit", - "megabyte", - "meter", - "mile", - "mile-scandinavian", - "millimeter", - "milliliter", - "millisecond", - "minute", - "month", - "ounce", - "percent", - "petabyte", - "pound", - "second", - "stone", - "terabit", - "terabyte", - "week", - "yard", - "year", -]; +const units = allSimpleSanctionedUnits(); for (const simpleUnit of units) { check(simpleUnit); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js new file mode 100644 index 000000000000..8b954d4dcbc9 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Tests that the digits are determined correctly when specifying at same time «"minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits"» +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [new Intl.NumberFormat().resolvedOptions().locale, "ar", "de", "th", "ja"]; +var numberingSystems = ["latn", "arab", "thai", "hanidec"]; + +var nfTestMatrix = [ + // mnfd & mxfd > mnsd & mxsd + [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 4, minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, { 1.23456: "1.2" }], + [{ useGrouping: false, minimumFractionDigits: 2, maximumFractionDigits: 4, minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, { 1.23456: "1.2" }], + // mnfd & mxfd ∩ mnsd & mxsd + [{ useGrouping: false, minimumFractionDigits: 2, maximumFractionDigits: 4, minimumSignificantDigits: 2, maximumSignificantDigits: 3 }, { 1.23456: "1.23" }], + // mnfd & mxfd < mnsd & mxsd + [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 2, minimumSignificantDigits: 1, maximumSignificantDigits: 4}, { 1.23456: "1.235" }], + [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 2, minimumSignificantDigits: 2, maximumSignificantDigits: 4}, { 1.23456: "1.235" }], +]; + +nfTestMatrix.forEach((nfTestValues)=>{ + testNumberFormat(locales, numberingSystems, ...nfTestValues) +}) + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1.js new file mode 100644 index 000000000000..e9ff02fd73b4 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `1`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 1, maximumFractionDigits: 1}, + { + '1.100': '1.1', + '1.125': '1.1', + '1.150': '1.2', + '1.175': '1.2', + '1.200': '1.2', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 1, maximumFractionDigits: 2}, + { + '1.0100': '1.01', + '1.0125': '1.01', + '1.0150': '1.02', + '1.0175': '1.02', + '1.0200': '1.02', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js new file mode 100644 index 000000000000..573d099efe94 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `10`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 10, maximumFractionDigits: 2}, + { + '1.100': '1.1', + '1.125': '1.1', + '1.150': '1.2', + '1.175': '1.2', + '1.200': '1.2', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 10, maximumFractionDigits: 3}, + { + '1.0100': '1.01', + '1.0125': '1.01', + '1.0150': '1.02', + '1.0175': '1.02', + '1.0200': '1.02', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js new file mode 100644 index 000000000000..34cf6134c790 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `100`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 100, maximumFractionDigits: 3}, + { + '1.100': '1.1', + '1.125': '1.1', + '1.150': '1.2', + '1.175': '1.2', + '1.200': '1.2', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 100, maximumFractionDigits: 4}, + { + '1.0100': '1.01', + '1.0125': '1.01', + '1.0150': '1.02', + '1.0175': '1.02', + '1.0200': '1.02', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js new file mode 100644 index 000000000000..6d12cb423d93 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `1000`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 1000, maximumFractionDigits: 4}, + { + '1.100': '1.1', + '1.125': '1.1', + '1.150': '1.2', + '1.175': '1.2', + '1.200': '1.2', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 1000, maximumFractionDigits: 5}, + { + '1.0100': '1.01', + '1.0125': '1.01', + '1.0150': '1.02', + '1.0175': '1.02', + '1.0200': '1.02', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2.js new file mode 100644 index 000000000000..326d2cd0f6d8 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `2`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 2, maximumFractionDigits: 1}, + { + '1.20': '1.2', + '1.25': '1.2', + '1.30': '1.4', + '1.35': '1.4', + '1.40': '1.4', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 2, maximumFractionDigits: 2}, + { + '1.020': '1.02', + '1.025': '1.02', + '1.030': '1.04', + '1.035': '1.04', + '1.040': '1.04', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js new file mode 100644 index 000000000000..a0c5da43c2e9 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `20`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 20, maximumFractionDigits: 2}, + { + '1.20': '1.2', + '1.25': '1.2', + '1.30': '1.4', + '1.35': '1.4', + '1.40': '1.4', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 20, maximumFractionDigits: 3}, + { + '1.020': '1.02', + '1.025': '1.02', + '1.030': '1.04', + '1.035': '1.04', + '1.040': '1.04', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js new file mode 100644 index 000000000000..f8eaa0abee58 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `200`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 200, maximumFractionDigits: 3}, + { + '1.20': '1.2', + '1.25': '1.2', + '1.30': '1.4', + '1.35': '1.4', + '1.40': '1.4', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 200, maximumFractionDigits: 4}, + { + '1.020': '1.02', + '1.025': '1.02', + '1.030': '1.04', + '1.035': '1.04', + '1.040': '1.04', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js new file mode 100644 index 000000000000..53695ab55d05 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `2000`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 2000, maximumFractionDigits: 4}, + { + '1.20': '1.2', + '1.25': '1.2', + '1.30': '1.4', + '1.35': '1.4', + '1.40': '1.4', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 2000, maximumFractionDigits: 5}, + { + '1.020': '1.02', + '1.025': '1.02', + '1.030': '1.04', + '1.035': '1.04', + '1.040': '1.04', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js new file mode 100644 index 000000000000..d2e3aaefb2f2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `25`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 25, maximumFractionDigits: 2, minimumFractionDigits: 1}, + { + '1.2500': '1.25', + '1.3125': '1.25', + '1.3750': '1.5', + '1.4375': '1.5', + '1.5000': '1.5', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 25, maximumFractionDigits: 3}, + { + '1.02500': '1.025', + '1.03125': '1.025', + '1.03750': '1.05', + '1.04375': '1.05', + '1.05000': '1.05', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js new file mode 100644 index 000000000000..5f3c6ec8e538 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `250`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 250, maximumFractionDigits: 3, minimumFractionDigits: 1}, + { + '1.2500': '1.25', + '1.3125': '1.25', + '1.3750': '1.5', + '1.4375': '1.5', + '1.5000': '1.5', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 250, maximumFractionDigits: 4}, + { + '1.02500': '1.025', + '1.03125': '1.025', + '1.03750': '1.05', + '1.04375': '1.05', + '1.05000': '1.05', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js new file mode 100644 index 000000000000..f7cc0e5e3b4c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `2500`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 2500, maximumFractionDigits: 4, minimumFractionDigits: 1}, + { + '1.2500': '1.25', + '1.3125': '1.25', + '1.3750': '1.5', + '1.4375': '1.5', + '1.5000': '1.5', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 2500, maximumFractionDigits: 5}, + { + '1.02500': '1.025', + '1.03125': '1.025', + '1.03750': '1.05', + '1.04375': '1.05', + '1.05000': '1.05', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js new file mode 100644 index 000000000000..fe314ad1d3a2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `5`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 5, maximumFractionDigits: 1, minimumFractionDigits: 1}, + { + '1.500': '1.5', + '1.625': '1.5', + '1.750': '2.0', + '1.875': '2.0', + '2.000': '2.0', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 5, maximumFractionDigits: 2}, + { + '1.0500': '1.05', + '1.0625': '1.05', + '1.0750': '1.1', + '1.0875': '1.1', + '1.1000': '1.1', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js new file mode 100644 index 000000000000..864ae7fe1e67 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `50`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 50, maximumFractionDigits: 2, minimumFractionDigits: 1}, + { + '1.500': '1.5', + '1.625': '1.5', + '1.750': '2.0', + '1.875': '2.0', + '2.000': '2.0', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 50, maximumFractionDigits: 3}, + { + '1.0500': '1.05', + '1.0625': '1.05', + '1.0750': '1.1', + '1.0875': '1.1', + '1.1000': '1.1', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js new file mode 100644 index 000000000000..e2d8ffcb898e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `500`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 500, maximumFractionDigits: 3, minimumFractionDigits: 1}, + { + '1.500': '1.5', + '1.625': '1.5', + '1.750': '2.0', + '1.875': '2.0', + '2.000': '2.0', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 500, maximumFractionDigits: 4}, + { + '1.0500': '1.05', + '1.0625': '1.05', + '1.0750': '1.1', + '1.0875': '1.1', + '1.1000': '1.1', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js new file mode 100644 index 000000000000..4e4cd1c302b0 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: When set to `5000`, roundingIncrement is correctly applied +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 5000, maximumFractionDigits: 4, minimumFractionDigits: 1}, + { + '1.500': '1.5', + '1.625': '1.5', + '1.750': '2.0', + '1.875': '2.0', + '2.000': '2.0', + } +); + +testNumberFormat( + locales, + numberingSystems, + {roundingIncrement: 5000, maximumFractionDigits: 5}, + { + '1.0500': '1.05', + '1.0625': '1.05', + '1.0750': '1.1', + '1.0875': '1.1', + '1.1000': '1.1', + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-ceil.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-ceil.js new file mode 100644 index 000000000000..e8b2ecb7323c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-ceil.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "ceil", rounding tends toward positive infinity +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'ceil', maximumSignificantDigits: 2}, + { + '1.101': '1.2', + '1.15': '1.2', + '1.1999': '1.2', + '1.25': '1.3', + '0': '0', + '-0': '-0', + '-1.101': '-1.1', + '-1.15': '-1.1', + '-1.1999': '-1.1', + '-1.25': '-1.2' + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-expand.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-expand.js new file mode 100644 index 000000000000..7eb22a70c0d2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-expand.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "expand", rounding tends away from zero +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'expand', maximumSignificantDigits: 2}, + { + '1.101': '1.2', + '1.15': '1.2', + '1.1999': '1.2', + '1.25': '1.3', + '0': '0', + '-0': '-0', + '-1.101': '-1.2', + '-1.15': '-1.2', + '-1.1999': '-1.2', + '-1.25': '-1.3' + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-floor.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-floor.js new file mode 100644 index 000000000000..2606a9b87baa --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-floor.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "floor", rounding tends toward negative infinity +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'floor', maximumSignificantDigits: 2}, + { + '1.101': '1.1', + '1.15': '1.1', + '1.1999': '1.1', + '1.25': '1.2', + '0': '0', + '-0': '-0', + '-1.101': '-1.2', + '-1.15': '-1.2', + '-1.1999': '-1.2', + '-1.25': '-1.3' + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-ceil.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-ceil.js new file mode 100644 index 000000000000..4fe267a41385 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-ceil.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "halfExpand", rounding tends toward the closest value + with ties tending toward positive infinity +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'halfCeil', maximumSignificantDigits: 2}, + { + '1.101': '1.1', + '1.15': '1.2', + '1.1999': '1.2', + '1.25': '1.3', + '0': '0', + '-0': '-0', + '-1.101': '-1.1', + '-1.15': '-1.1', + '-1.1999': '-1.2', + '-1.25': '-1.2' + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-even.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-even.js new file mode 100644 index 000000000000..58958f849870 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-even.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "halfEven", rounding tends toward the closest value + with ties tending toward the value with even cardinality +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'halfEven', maximumSignificantDigits: 2}, + { + '1.101': '1.1', + '1.15': '1.2', + '1.1999': '1.2', + '1.25': '1.2', + '0': '0', + '-0': '-0', + '-1.101': '-1.1', + '-1.15': '-1.2', + '-1.1999': '-1.2', + '-1.25': '-1.2' + } +); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-expand.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-expand.js new file mode 100644 index 000000000000..e5a5edee5e1a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-expand.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "halfExpand", rounding tends toward the closest value + with ties tending away from zero +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'halfExpand', maximumSignificantDigits: 2}, + { + '1.101': '1.1', + '1.15': '1.2', + '1.1999': '1.2', + '1.25': '1.3', + '0': '0', + '-0': '-0', + '-1.101': '-1.1', + '-1.15': '-1.2', + '-1.1999': '-1.2', + '-1.25': '-1.3' + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-floor.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-floor.js new file mode 100644 index 000000000000..fe0b4bccbc27 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-floor.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "halfFloor", rounding tends toward the closest value + with ties tending toward negative infinity +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'halfFloor', maximumSignificantDigits: 2}, + { + '1.101': '1.1', + '1.15': '1.1', + '1.1999': '1.2', + '1.25': '1.2', + '0': '0', + '-0': '-0', + '-1.101': '-1.1', + '-1.15': '-1.2', + '-1.1999': '-1.2', + '-1.25': '-1.3' + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-trunc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-trunc.js new file mode 100644 index 000000000000..15bef9d56974 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-trunc.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "halfTrunc", rounding tends toward the closest value + with ties tending toward zero +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'halfTrunc', maximumSignificantDigits: 2}, + { + '1.101': '1.1', + '1.15': '1.1', + '1.1999': '1.2', + '1.25': '1.2', + '0': '0', + '-0': '-0', + '-1.101': '-1.1', + '-1.15': '-1.1', + '-1.1999': '-1.2', + '-1.25': '-1.2' + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-trunc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-trunc.js new file mode 100644 index 000000000000..9ec8ed360ca2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-trunc.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roundingMode is "trunc", rounding tends toward zero +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingMode: 'trunc', maximumSignificantDigits: 2}, + { + '1.101': '1.1', + '1.15': '1.1', + '1.1999': '1.1', + '1.25': '1.2', + '0': '0', + '-0': '-0', + '-1.101': '-1.1', + '-1.15': '-1.1', + '-1.1999': '-1.1', + '-1.25': '-1.2' + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-auto.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-auto.js new file mode 100644 index 000000000000..09ae7e47a543 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-auto.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roungingPriority is "auto", the constraint on significant digits is + preferred over the constraint on fraction digits +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +// minimumSignificantDigits is less precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'auto', minimumSignificantDigits: 2, minimumFractionDigitsDigits: 2}, + {'1': '1.0'} +); + +// minimumSignificantDigits is more precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'auto', minimumSignificantDigits: 3, minimumFractionDigitsDigits: 2}, + {'1': '1.00'} +); + +// maximumSignificantDigits is less precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'auto', maximumSignificantDigits: 2, maximumFractionDigitsDigits: 2}, + {'1.23': '1.2'} +); + +// maximumSignificantDigits is more precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'auto', maximumSignificantDigits: 3, maximumFractionDigitsDigits: 1}, + {'1.234': '1.23'} +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js new file mode 100644 index 000000000000..272f81b6a136 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roungingPriority is "lessPrecision", the constraint which produces the + less precise result is preferred +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +// minimumSignificantDigits is less precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'lessPrecision', minimumSignificantDigits: 2, minimumFractionDigits: 2}, + {'1': '1.00'} +); + +// minimumSignificantDigits is more precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'lessPrecision', minimumSignificantDigits: 3, minimumFractionDigits: 1}, + {'1': '1.0'} +); + +// maximumSignificantDigits is less precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'lessPrecision', maximumSignificantDigits: 2, maximumFractionDigits: 2}, + {'1.23': '1.2'} +); + +// maximumSignificantDigits is more precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'lessPrecision', maximumSignificantDigits: 3, maximumFractionDigits: 1}, + {'1.234': '1.2'} +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-more-precision.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-more-precision.js new file mode 100644 index 000000000000..93ff0169c573 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-more-precision.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + When roungingPriority is "morePrecision", the constraint which produces the + more precise result is preferred +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja' +]; +var numberingSystems = ['arab', 'latn', 'thai', 'hanidec']; + +// minimumSignificantDigits is less precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'morePrecision', minimumSignificantDigits: 2, minimumFractionDigits: 2}, + {'1': '1.00'} +); + +// minimumSignificantDigits is more precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'morePrecision', minimumSignificantDigits: 3, minimumFractionDigits: 2}, + {'1': '1.00'} +); + +// maximumSignificantDigits is less precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'morePrecision', maximumSignificantDigits: 2, maximumFractionDigits: 2}, + {'1.23': '1.23'} +); + +// maximumSignificantDigits is more precise +testNumberFormat( + locales, + numberingSystems, + {useGrouping: false, roundingPriority: 'morePrecision', maximumSignificantDigits: 3, maximumFractionDigits: 1}, + {'1.234': '1.23'} +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js index 84699dfa0ebb..112657283c1d 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js @@ -7,93 +7,17 @@ description: > Tests that Intl.NumberFormat.prototype.format supports all numbering systems with simple digit mappings. author: Roozbeh Pournader +includes: [testIntl.js] ---*/ -const numberingSystems = { - adlm: 0x1E950, - ahom: 0x11730, - arab: 0x0660, - arabext: 0x06F0, - bali: 0x1B50, - beng: 0x09E6, - bhks: 0x11C50, - brah: 0x11066, - cakm: 0x11136, - cham: 0xAA50, - deva: 0x0966, - diak: 0x11950, - fullwide: 0xFF10, - gong: 0x11DA0, - gonm: 0x11D50, - gujr: 0x0AE6, - guru: 0x0A66, - hanidec: [0x3007, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, - 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D], - hmng: 0x16B50, - hmnp: 0x1E140, - java: 0xA9D0, - kali: 0xA900, - khmr: 0x17E0, - knda: 0x0CE6, - lana: 0x1A80, - lanatham: 0x1A90, - laoo: 0x0ED0, - latn: 0x0030, - lepc: 0x1C40, - limb: 0x1946, - mathbold: 0x1D7CE, - mathdbl: 0x1D7D8, - mathmono: 0x1D7F6, - mathsanb: 0x1D7EC, - mathsans: 0x1D7E2, - mlym: 0x0D66, - modi: 0x11650, - mong: 0x1810, - mroo: 0x16A60, - mtei: 0xABF0, - mymr: 0x1040, - mymrshan: 0x1090, - mymrtlng: 0xA9F0, - newa: 0x11450, - nkoo: 0x07C0, - olck: 0x1C50, - orya: 0x0B66, - osma: 0x104A0, - rohg: 0x10D30, - saur: 0xA8D0, - segment: 0x1FBF0, - shrd: 0x111D0, - sind: 0x112F0, - sinh: 0x0DE6, - sora: 0x110F0, - sund: 0x1BB0, - takr: 0x116C0, - talu: 0x19D0, - tamldec: 0x0BE6, - telu: 0x0C66, - thai: 0x0E50, - tibt: 0x0F20, - tirh: 0x114D0, - vaii: 0xA620, - wara: 0x118E0, - wcho: 0x1E2F0, -}; - -for (let [numberingSystem, digitList] of Object.entries(numberingSystems)) { - if (typeof digitList === 'number') { - let zeroCode = digitList; - digitList = []; - for (let i = 0; i <= 9; ++i) { - digitList[i] = zeroCode + i; - } - } - +for (let [numberingSystem, digits] of Object.entries(numberingSystemDigits)) { + let digitList = [...digits]; assert.sameValue(digitList.length, 10); let nf = new Intl.NumberFormat(undefined, {numberingSystem}); for (let i = 0; i <= 9; ++i) { - assert.sameValue(nf.format(i), String.fromCodePoint(digitList[i]), + assert.sameValue(nf.format(i), digitList[i], `numberingSystem: ${numberingSystem}, digit: ${i}`); } } diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js index d51d9bc7d37b..72d8ccc41019 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.format -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [de-DE] features: [Intl.NumberFormat-unified] ---*/ diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js index 2508a1c960b9..72a1a0ba2ecb 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.format -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [en-US] features: [Intl.NumberFormat-unified] ---*/ diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js index 768ebbf61faa..f28ba6c26357 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.format -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [ja-JP] features: [Intl.NumberFormat-unified] ---*/ diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js index fdf626fd917a..cfe8f9393a07 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.format -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [ko-KR] features: [Intl.NumberFormat-unified] ---*/ diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js index 92c5c22f5e82..677b0b400e05 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.format -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [zh-TW] features: [Intl.NumberFormat-unified] ---*/ diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-de-DE.js new file mode 100644 index 000000000000..b631d59008df --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-de-DE.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); +assert.sameValue(nf.format(-987), "-987,00 $"); +assert.sameValue(nf.format(-0.0001), "0,00 $"); +assert.sameValue(nf.format(-0), "0,00 $"); +assert.sameValue(nf.format(0), "0,00 $"); +assert.sameValue(nf.format(0.0001), "0,00 $"); +assert.sameValue(nf.format(987), "987,00 $"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-en-US.js new file mode 100644 index 000000000000..51e96c4af648 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-en-US.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); +assert.sameValue(nf.format(-987), "($987.00)"); +assert.sameValue(nf.format(-0.0001), "$0.00"); +assert.sameValue(nf.format(-0), "$0.00"); +assert.sameValue(nf.format(0), "$0.00"); +assert.sameValue(nf.format(0.0001), "$0.00"); +assert.sameValue(nf.format(987), "$987.00"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ja-JP.js new file mode 100644 index 000000000000..27c29fa81932 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ja-JP.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); +assert.sameValue(nf.format(-987), "($987.00)"); +assert.sameValue(nf.format(-0.0001), "$0.00"); +assert.sameValue(nf.format(-0), "$0.00"); +assert.sameValue(nf.format(0), "$0.00"); +assert.sameValue(nf.format(0.0001), "$0.00"); +assert.sameValue(nf.format(987), "$987.00"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ko-KR.js new file mode 100644 index 000000000000..5ae7941e6ae0 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ko-KR.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); +assert.sameValue(nf.format(-987), "(US$987.00)"); +assert.sameValue(nf.format(-0.0001), "US$0.00"); +assert.sameValue(nf.format(-0), "US$0.00"); +assert.sameValue(nf.format(0), "US$0.00"); +assert.sameValue(nf.format(0.0001), "US$0.00"); +assert.sameValue(nf.format(987), "US$987.00"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-zh-TW.js new file mode 100644 index 000000000000..95d41d512dfa --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-zh-TW.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); +assert.sameValue(nf.format(-987), "(US$987.00)"); +assert.sameValue(nf.format(-0.0001), "US$0.00"); +assert.sameValue(nf.format(-0), "US$0.00"); +assert.sameValue(nf.format(0), "US$0.00"); +assert.sameValue(nf.format(0.0001), "US$0.00"); +assert.sameValue(nf.format(987), "US$987.00"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-de-DE.js new file mode 100644 index 000000000000..665018b4df6a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-de-DE.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("de-DE", {signDisplay: "negative"}); +assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity"); +assert.sameValue(nf.format(-987), "-987", "-987"); +assert.sameValue(nf.format(-0.0001), "0", "-0.0001"); +assert.sameValue(nf.format(-0), "0", "-0"); +assert.sameValue(nf.format(0), "0", "0"); +assert.sameValue(nf.format(0.0001), "0", "0.0001"); +assert.sameValue(nf.format(987), "987", "987"); +assert.sameValue(nf.format(Infinity), "∞", "Infinity"); +assert.sameValue(nf.format(NaN), "NaN", "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-en-US.js new file mode 100644 index 000000000000..cb0301e464a2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-en-US.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("en-US", {signDisplay: "negative"}); +assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity"); +assert.sameValue(nf.format(-987), "-987", "-987"); +assert.sameValue(nf.format(-0.0001), "0", "-0.0001"); +assert.sameValue(nf.format(-0), "0", "-0"); +assert.sameValue(nf.format(0), "0", "0"); +assert.sameValue(nf.format(0.0001), "0", "0.0001"); +assert.sameValue(nf.format(987), "987", "987"); +assert.sameValue(nf.format(Infinity), "∞", "Infinity"); +assert.sameValue(nf.format(NaN), "NaN", "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ja-JP.js new file mode 100644 index 000000000000..e88ff00dd7c2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ja-JP.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("ja-JP", {signDisplay: "negative"}); +assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity"); +assert.sameValue(nf.format(-987), "-987", "-987"); +assert.sameValue(nf.format(-0.0001), "0", "-0.0001"); +assert.sameValue(nf.format(-0), "0", "-0"); +assert.sameValue(nf.format(0), "0", "0"); +assert.sameValue(nf.format(0.0001), "0", "0.0001"); +assert.sameValue(nf.format(987), "987", "987"); +assert.sameValue(nf.format(Infinity), "∞", "Infinity"); +assert.sameValue(nf.format(NaN), "NaN", "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ko-KR.js new file mode 100644 index 000000000000..5b0f6835df85 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ko-KR.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("ko-KR", {signDisplay: "negative"}); +assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity"); +assert.sameValue(nf.format(-987), "-987", "-987"); +assert.sameValue(nf.format(-0.0001), "0", "-0.0001"); +assert.sameValue(nf.format(-0), "0", "-0"); +assert.sameValue(nf.format(0), "0", "0"); +assert.sameValue(nf.format(0.0001), "0", "0.0001"); +assert.sameValue(nf.format(987), "987", "987"); +assert.sameValue(nf.format(Infinity), "∞", "Infinity"); +assert.sameValue(nf.format(NaN), "NaN", "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-zh-TW.js new file mode 100644 index 000000000000..54555bd5a1d7 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-zh-TW.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat("zh-TW", {signDisplay: "negative"}); +assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity"); +assert.sameValue(nf.format(-987), "-987", "-987"); +assert.sameValue(nf.format(-0.0001), "0", "-0.0001"); +assert.sameValue(nf.format(-0), "0", "-0"); +assert.sameValue(nf.format(0), "0", "0"); +assert.sameValue(nf.format(0.0001), "0", "0.0001"); +assert.sameValue(nf.format(987), "987", "987"); +assert.sameValue(nf.format(Infinity), "∞", "Infinity"); +assert.sameValue(nf.format(NaN), "非數值", "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js index f939789ddd68..8c441008a3a1 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js @@ -4,6 +4,7 @@ /*--- esid: sec-intl.numberformat.prototype.format description: Checks handling of units. +includes: [testIntl.js] features: [Intl.NumberFormat-unified] ---*/ @@ -13,51 +14,7 @@ function check(unit) { assert.notSameValue(s1, s2); } -const units = [ - "acre", - "bit", - "byte", - "celsius", - "centimeter", - "day", - "degree", - "fahrenheit", - "fluid-ounce", - "foot", - "gallon", - "gigabit", - "gigabyte", - "gram", - "hectare", - "hour", - "inch", - "kilobit", - "kilobyte", - "kilogram", - "kilometer", - "liter", - "megabit", - "megabyte", - "meter", - "mile", - "mile-scandinavian", - "millimeter", - "milliliter", - "millisecond", - "minute", - "month", - "ounce", - "percent", - "petabyte", - "pound", - "second", - "stone", - "terabit", - "terabyte", - "week", - "yard", - "year", -]; +const units = allSimpleSanctionedUnits(); for (const simpleUnit of units) { check(simpleUnit); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-de-DE.js new file mode 100644 index 000000000000..a2368e2d218e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-de-DE.js @@ -0,0 +1,33 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: | + Checks handling of the useGrouping option to the NumberFormat constructor. +locale: [de-DE] +---*/ + +var nf; + +nf = new Intl.NumberFormat('de-DE', {}); + +assert.sameValue(nf.format(100), '100', '(omitted)'); +assert.sameValue(nf.format(1000), '1.000', '(omitted)'); +assert.sameValue(nf.format(10000), '10.000', '(omitted)'); +assert.sameValue(nf.format(100000), '100.000', '(omitted)'); + +nf = new Intl.NumberFormat('de-DE', {useGrouping: true}); + +assert.sameValue(nf.format(100), '100', 'true'); +assert.sameValue(nf.format(1000), '1.000', 'true'); +assert.sameValue(nf.format(100000), '100.000', 'true'); + +nf = new Intl.NumberFormat('de-DE', {useGrouping: false}); + +assert.sameValue(nf.format(100), '100', 'false'); +assert.sameValue(nf.format(1000), '1000', 'false'); +assert.sameValue(nf.format(10000), '10000', 'false'); +assert.sameValue(nf.format(100000), '100000', 'false'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-IN.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-IN.js new file mode 100644 index 000000000000..29bc42b207f7 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-IN.js @@ -0,0 +1,34 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: | + Checks handling of the useGrouping option to the NumberFormat constructor. +locale: [en-IN] +---*/ + +var nf; + +nf = new Intl.NumberFormat('en-IN', {}); + +assert.sameValue(nf.format(100), '100', '(omitted)'); +assert.sameValue(nf.format(1000), '1,000', '(omitted)'); +assert.sameValue(nf.format(10000), '10,000', '(omitted)'); +assert.sameValue(nf.format(100000), '1,00,000', '(omitted)'); + +nf = new Intl.NumberFormat('en-IN', {useGrouping: true}); + +assert.sameValue(nf.format(100), '100', 'true'); +assert.sameValue(nf.format(1000), '1,000', 'true'); +assert.sameValue(nf.format(10000), '10,000', 'true'); +assert.sameValue(nf.format(100000), '1,00,000', 'true'); + +nf = new Intl.NumberFormat('en-IN', {useGrouping: false}); + +assert.sameValue(nf.format(100), '100', 'false'); +assert.sameValue(nf.format(1000), '1000', 'false'); +assert.sameValue(nf.format(10000), '10000', 'false'); +assert.sameValue(nf.format(100000), '100000', 'false'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-US.js new file mode 100644 index 000000000000..3baaafb8bce4 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-US.js @@ -0,0 +1,34 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: | + Checks handling of the useGrouping option to the NumberFormat constructor. +locale: [en-US] +---*/ + +var nf; + +nf = new Intl.NumberFormat('en-US', {}); + +assert.sameValue(nf.format(100), '100', '(omitted)'); +assert.sameValue(nf.format(1000), '1,000', '(omitted)'); +assert.sameValue(nf.format(10000), '10,000', '(omitted)'); +assert.sameValue(nf.format(100000), '100,000', '(omitted)'); + +nf = new Intl.NumberFormat('en-US', {useGrouping: true}); + +assert.sameValue(nf.format(100), '100', 'true'); +assert.sameValue(nf.format(1000), '1,000', 'true'); +assert.sameValue(nf.format(10000), '10,000', 'true'); +assert.sameValue(nf.format(100000), '100,000', 'true'); + +nf = new Intl.NumberFormat('en-US', {useGrouping: false}); + +assert.sameValue(nf.format(100), '100', 'false'); +assert.sameValue(nf.format(1000), '1000', 'false'); +assert.sameValue(nf.format(10000), '10000', 'false'); +assert.sameValue(nf.format(100000), '100000', 'false'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-de-DE.js new file mode 100644 index 000000000000..b7a23f224394 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-de-DE.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: | + Checks handling of the useGrouping option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-v3] +---*/ + +var nf; + +nf = new Intl.NumberFormat('de-DE', {useGrouping: 'always'}); + +assert.sameValue(nf.format(100), '100', '"always"'); +assert.sameValue(nf.format(1000), '1.000', '"always"'); +assert.sameValue(nf.format(10000), '10.000', '"always"'); +assert.sameValue(nf.format(100000), '100.000', '"always"'); + +nf = new Intl.NumberFormat('de-DE', {useGrouping: 'min2'}); + +assert.sameValue(nf.format(100), '100', '"min2"'); +assert.sameValue(nf.format(1000), '1000', '"min2"'); +assert.sameValue(nf.format(10000), '10.000', '"min2"'); +assert.sameValue(nf.format(100000), '100.000', '"min2"'); + +nf = new Intl.NumberFormat('de-DE', {notation: 'compact'}); + +assert.sameValue(nf.format(100), '100', 'notation: "compact"'); +assert.sameValue(nf.format(1000), '1000', 'notation: "compact"'); +assert.sameValue(nf.format(10000), '10.000', 'notation: "compact"'); +assert.sameValue(nf.format(100000), '100.000', 'notation: "compact"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-IN.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-IN.js new file mode 100644 index 000000000000..f36e4de7887e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-IN.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: | + Checks handling of the useGrouping option to the NumberFormat constructor. +locale: [en-IN] +features: [Intl.NumberFormat-v3] +---*/ + +var nf; + +nf = new Intl.NumberFormat('en-IN', {useGrouping: 'always'}); + +assert.sameValue(nf.format(100), '100', '"always"'); +assert.sameValue(nf.format(1000), '1,000', '"always"'); +assert.sameValue(nf.format(10000), '10,000', '"always"'); +assert.sameValue(nf.format(100000), '1,00,000', '"always"'); + +nf = new Intl.NumberFormat('en-IN', {useGrouping: 'min2'}); + +assert.sameValue(nf.format(100), '100', '"min2"'); +assert.sameValue(nf.format(1000), '1000', '"min2"'); +assert.sameValue(nf.format(10000), '10,000', '"min2"'); +assert.sameValue(nf.format(100000), '1,00,000', '"min2"'); + +nf = new Intl.NumberFormat('en-IN', {notation: 'compact'}); + +assert.sameValue(nf.format(100), '100', 'notation: "compact"'); +assert.sameValue(nf.format(1000), '1T', 'notation: "compact"'); +assert.sameValue(nf.format(10000), '10T', 'notation: "compact"'); +assert.sameValue(nf.format(100000), '1L', 'notation: "compact"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-US.js new file mode 100644 index 000000000000..3a1212eae1df --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-US.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: | + Checks handling of the useGrouping option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-v3] +---*/ + +var nf; + +nf = new Intl.NumberFormat('en-US', {useGrouping: 'always'}); + +assert.sameValue(nf.format(100), '100', '"always"'); +assert.sameValue(nf.format(1000), '1,000', '"always"'); +assert.sameValue(nf.format(10000), '10,000', '"always"'); +assert.sameValue(nf.format(100000), '100,000', '"always"'); + +nf = new Intl.NumberFormat('en-US', {useGrouping: 'min2'}); + +assert.sameValue(nf.format(100), '100', '"min2"'); +assert.sameValue(nf.format(1000), '1000', '"min2"'); +assert.sameValue(nf.format(10000), '10,000', '"min2"'); +assert.sameValue(nf.format(100000), '100,000', '"min2"'); + +nf = new Intl.NumberFormat('en-US', {notation: 'compact'}); + +assert.sameValue(nf.format(100), '100', 'notation: "compact"'); +assert.sameValue(nf.format(1000), '1K', 'notation: "compact"'); +assert.sameValue(nf.format(10000), '10K', 'notation: "compact"'); +assert.sameValue(nf.format(100000), '100K', 'notation: "compact"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-decimal-string.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-decimal-string.js new file mode 100644 index 000000000000..6d7135634e5c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-decimal-string.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-number-format-functions +description: > + Intl.NumberFormat.prototype.format converts its argument (called value) to a + number using ToIntlMathematicalValue. +features: [Intl.NumberFormat-v3] +locale: [en-US] +---*/ + +var nf = new Intl.NumberFormat('en-US', {maximumFractionDigits: 20}); + +// The value 100,000 should only be interpreted as infinity if the input is the +// string "Infinity". +assert.sameValue(nf.format('100000'), '100,000'); +// The value -100,000 should only be interpreted as negative infinity if the +// input is the string "-Infinity". +assert.sameValue(nf.format('-100000'), '-100,000'); + +assert.sameValue(nf.format('1.0000000000000001'), '1.0000000000000001'); +assert.sameValue(nf.format('-1.0000000000000001'), '-1.0000000000000001'); +assert.sameValue(nf.format('987654321987654321'), '987,654,321,987,654,321'); +assert.sameValue(nf.format('-987654321987654321'), '-987,654,321,987,654,321'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js index 8d05270da3d3..3785b291033c 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js @@ -19,7 +19,9 @@ const toNumberResults = [ [true, 1], [false, 0], ['42', 42], - ['foo', NaN] + ['foo', NaN], + ['Infinity', Infinity], + ['-Infinity', -Infinity] ]; const nf = new Intl.NumberFormat(); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/argument-to-Intlmathematicalvalue-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/argument-to-Intlmathematicalvalue-throws.js new file mode 100644 index 000000000000..2f9bac16c1dc --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/argument-to-Intlmathematicalvalue-throws.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-formatRange +description: > + "formatRange" basic tests when argument cannot be converted using ToIntlMathematicalValue +info: | + Intl.NumberFormat.prototype.formatRange( start, end ) + (...) + 4. Let x be ? ToIntlMathematicalValue(start). + 5. Let y be ? ToIntlMathematicalValue(end). +features: [Intl.NumberFormat-v3] +---*/ + + +const nf = new Intl.NumberFormat(); + +// Throw if arguments cannot be cast using the method ToIntlMathematicalValue +assert.throws(TypeError, () => { nf.formatRange(Symbol(102), 201) }); +assert.throws(TypeError, () => { nf.formatRange(102,Symbol(201)) }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/builtin.js new file mode 100644 index 000000000000..760cada27715 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/builtin.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Tests that the Intl.NumberFormat.prototype.formatRange function meets the + requirements for built-in objects defined by the ECMAScript Language + Specification. +includes: [isConstructor.js] +features: [Reflect.construct,Intl.NumberFormat-v3] +---*/ + +const formatRange = Intl.NumberFormat.prototype.formatRange; + +assert.sameValue(Object.prototype.toString.call(formatRange), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(formatRange), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(formatRange), Function.prototype); + +assert.sameValue(formatRange.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(formatRange), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/en-US.js new file mode 100644 index 000000000000..1023bf5cdb1c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/en-US.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-formatRange +description: Basic tests for the en-US output of formatRange() +locale: [en-US] +features: [Intl.NumberFormat-v3] +---*/ + +// Basic example test en-US +const nf = new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + maximumFractionDigits: 0, +}); + +assert.sameValue(nf.formatRange(3, 5), "$3 – $5"); +assert.sameValue(nf.formatRange(2.9, 3.1), "~$3"); + + +// Basic example test en-US using signDisplay to always +const nf2 = new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + signDisplay: "always", +}); + +assert.sameValue(nf2.formatRange(2.9, 3.1), "+$2.90–3.10"); + +// Basic example test en-US string formatting +const nf3 = new Intl.NumberFormat("en-US"); +const string1 = "987654321987654321"; +const string2 = "987654321987654322"; + +assert.sameValue(nf3.formatRange(string1, string2), "987,654,321,987,654,321–987,654,321,987,654,322"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/invoked-as-func.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/invoked-as-func.js new file mode 100644 index 000000000000..bd73a820f248 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/invoked-as-func.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-NumberFormat +description: basic tests internal slot initialization and call receiver errors +info: | + Intl.NumberFormat.prototype.formatRange(start, end ) + (...) + 2. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]) +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat(); + +// Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]) +let f = nf['formatRange']; + +assert.sameValue(typeof f, 'function'); +assert.throws(TypeError, () => { f(1, 23) }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/length.js new file mode 100644 index 000000000000..7f006c5199bf --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.NumberFormat.prototype.formatRange.length. +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ +verifyProperty(Intl.NumberFormat.prototype.formatRange, 'length', { + value: 2, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/name.js new file mode 100644 index 000000000000..8bbfd6f27c1e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/name.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.NumberFormat.prototype.formatRange.name value and descriptor. +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ +verifyProperty(Intl.NumberFormat.prototype.formatRange, 'name', { + value: 'formatRange', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/nan-arguments-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/nan-arguments-throws.js new file mode 100644 index 000000000000..d6bd6f81b9aa --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/nan-arguments-throws.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-formatRange +description: > + "formatRange" Throws a RangeError if some of arguments is cast to NaN +info: | + Intl.NumberFormat.prototype.formatRange( start, end ) + (...) + 6. Return ? FormatNumericRange(nf, x, y). + + FormatNumericRange( numberFormat, x, y ) + 1. Let parts be ? PartitionNumberRangePattern(numberFormat, x, y). + + PartitionNumberRangePattern( numberFormat, x, y ) + 1. If x is NaN or y is NaN, throw a RangeError exception. +features: [Intl.NumberFormat-v3] +---*/ + + +const nf = new Intl.NumberFormat(); + +// If x or y is NaN ..., throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRange(NaN, 23) }); +assert.throws(RangeError, () => { nf.formatRange(12, NaN) }); +assert.throws(RangeError, () => { nf.formatRange(NaN, -23) }); +assert.throws(RangeError, () => { nf.formatRange(-12, NaN) }); +assert.throws(RangeError, () => { nf.formatRange(NaN, NaN) }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/prop-desc.js new file mode 100644 index 000000000000..a43f83d9a10b --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/prop-desc.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Property type and descriptor. +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ + +assert.sameValue( + typeof Intl.NumberFormat.prototype.formatRange, + 'function', + '`typeof Intl.NumberFormat.prototype.formatRange` is `function`' +); + +verifyProperty(Intl.NumberFormat.prototype, 'formatRange', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/pt-PT.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/pt-PT.js new file mode 100644 index 000000000000..25c9904f53ef --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/pt-PT.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-formatRange +description: Basic tests for the pt-PT output of formatRange() +locale: [pt-PT] +features: [Intl.NumberFormat-v3] +---*/ + +// Basic example test pt-PT +const nf = new Intl.NumberFormat("pt-PT", { + style: "currency", + currency: "EUR", + maximumFractionDigits: 0, +}); + +assert.sameValue(nf.formatRange(3, 5), "3 - 5\u00a0€"); +assert.sameValue(nf.formatRange(2.9, 3.1), "~3\u00a0€"); + + +// Basic example test pt-PT using signDisplay to always +const nf2 = new Intl.NumberFormat("pt-PT", { + style: "currency", + currency: "EUR", + signDisplay: "always", +}); + +assert.sameValue(nf2.formatRange(2.9, 3.1), "+2,90 - 3,10\u00a0€"); + +// Basic example test pt-PT string formatting +const nf3 = new Intl.NumberFormat("pt-PT"); +const string1 = "987654321987654321"; +const string2 = "987654321987654322"; + +assert.sameValue(nf3.formatRange(string1, string2), "987\u00a0654\u00a0321\u00a0987\u00a0654\u00a0321 - 987\u00a0654\u00a0321\u00a0987\u00a0654\u00a0322"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/undefined-arguments-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/undefined-arguments-throws.js new file mode 100644 index 000000000000..5e32540cc4e2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/undefined-arguments-throws.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.formatRange +description: > + "formatRange" basic tests when arguments are undefined throw a TypeError exception. +info: | + Intl.NumberFormat.prototype.formatRange ( start, end ) + (...) + 3. If start is undefined or end is undefined, throw a TypeError exception. +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat(); + +// If arguments are undefined throw a TypeError exception. +assert.throws(TypeError, () => { nf.formatRange(undefined, 23) }); +assert.throws(TypeError, () => { nf.formatRange(1,undefined) }); +assert.throws(TypeError, () => { nf.formatRange(undefined, undefined)}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws.js new file mode 100644 index 000000000000..12ab35b12636 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.formatRange +description: > + "formatRange" basic tests when argument x > y, BigInt included and covers PartitionNumberRangePattern throw a RangeError exception. +info: | + 1.1.21 PartitionNumberRangePattern( numberFormat, x, y ) + (...) + 1.1.21_2.a. If y is a mathematical value and y < x, throw a RangeError exception. + 1.1.21._2.b if y is -∞, throw a RangeError exception. + 1.1.21._2.c if y is -0 and x ≥ 0, throw a RangeError exception. + (...) + 1.1.21._3.a if y is a mathematical value, throw a RangeError exception + 1.1.21._3.b if y is -∞, throw a RangeError exception. + 1.1.21._3.c if y is -0, throw a RangeError exception. + (...) + 1.1.21_4.a if y is a mathematical value and y < 0, throw a RangeError exception. + 1.1.21_4.b if y is -∞, throw a RangeError exception. +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat(); + +// If x > y, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRange(23, 12) }); + +// 1.1.21_2 (...) +// If x > y, throw a RangeError exception and both x and y are bigint. +assert.throws(RangeError, () => { nf.formatRange(23n, 12n) }); +//if y is -∞, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRange(23, -Infinity) }); +//if y is -0 and x ≥ 0, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRange(23, -0) }); +assert.throws(RangeError, () => { nf.formatRange(0, -0) }); + +// 1.1.21_3 (...) +// if y is a mathematical value, throw a RangeError exception +assert.throws(RangeError, () => { nf.formatRange(Infinity, 23) }); +// if y is -∞, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRange(Infinity, -Infinity) }); +// if y is -0, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRange(Infinity, -0) }); + +// 1.1.21_4 (...) +// if y is a mathematical value and y < 0, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRange(-0, -1) }); +// if y is -∞, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRange(-0, -Infinity) }); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/argument-to-Intlmathematicalvalue-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/argument-to-Intlmathematicalvalue-throws.js new file mode 100644 index 000000000000..27548f332830 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/argument-to-Intlmathematicalvalue-throws.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-formatRangeToParts +description: > + "formatRangeToParts" basic tests when argument cannot be converted using ToIntlMathematicalValue +info: | + Intl.NumberFormat.prototype.formatRangeToParts( start, end ) + (...) + 4. Let x be ? ToIntlMathematicalValue(start). + 5. Let y be ? ToIntlMathematicalValue(end). +features: [Intl.NumberFormat-v3] +---*/ + + +const nf = new Intl.NumberFormat(); + +// Throw if arguments cannot be cast using the method ToIntlMathematicalValue +assert.throws(TypeError, () => { nf.formatRangeToParts(Symbol(102), 201) }); +assert.throws(TypeError, () => { nf.formatRangeToParts(102,Symbol(201)) }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/builtin.js new file mode 100644 index 000000000000..caa8eae606e5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/builtin.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Tests that the Intl.NumberFormat.prototype.formatRangeToParts function meets the + requirements for built-in objects defined by the ECMAScript Language + Specification. +includes: [isConstructor.js] +features: [Reflect.construct,Intl.NumberFormat-v3] +---*/ + +const formatRangeToParts = Intl.NumberFormat.prototype.formatRangeToParts; + +assert.sameValue(Object.prototype.toString.call(formatRangeToParts), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(formatRangeToParts), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(formatRangeToParts), Function.prototype); + +assert.sameValue(formatRangeToParts.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(formatRangeToParts), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/en-US.js new file mode 100644 index 000000000000..e378b6c3ca0d --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/en-US.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-formatRangeToParts +description: Basic tests for the en-US output of formatRangeToParts() +locale: [en-US] +features: [Intl.NumberFormat-v3] +includes: [propertyHelper.js] +---*/ + +// Utils functions +function* zip(a, b) { + assert.sameValue(a.length, b.length); + for (let i = 0; i < a.length; ++i) { + yield [i, a[i], b[i]]; + } +} + +function compare(actual, expected) { + for (const [i, actualEntry, expectedEntry] of zip(actual, expected)) { + // assertions + assert.sameValue(actualEntry.type, expectedEntry.type, `type for entry ${i}`); + assert.sameValue(actualEntry.value, expectedEntry.value, `value for entry ${i}`); + assert.sameValue(actualEntry.source, expectedEntry.source, `source for entry ${i}`); + + // 1.1.25_4.a Let O be ObjectCreate(%ObjectPrototype%). + assert.sameValue(Object.getPrototypeOf(actualEntry), Object.prototype, `prototype for entry ${i}`); + // 1.1.25_4.b Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]) + verifyProperty(actualEntry, 'type', { enumerable: true, writable: true, configurable: true }); + // 1.1.25_4.c Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]). + verifyProperty(actualEntry, 'value', { enumerable: true, writable: true, configurable: true }); + // 1.1.25_4.d Perform ! CreateDataPropertyOrThrow(O, "source", part.[[Source]]). + verifyProperty(actualEntry, 'source', { enumerable: true, writable: true, configurable: true }); + } +} + +// Basic example test en-US +const nf = new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + maximumFractionDigits: 0, +}); + +compare(nf.formatRangeToParts(3, 5), [ + {type: "currency", value: "$", source: "startRange"}, + {type: "integer", value: "3", source: "startRange"}, + {type: "literal", value: " – ", source: "shared"}, + {type: "currency", value: "$", source: "endRange"}, + {type: "integer", value: "5", source: "endRange"} +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func.js new file mode 100644 index 000000000000..1d776fc43564 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-NumberFormat +description: basic tests internal slot initialization and call receiver errors +info: | + Intl.NumberFormat.prototype.formatRangeToParts ( start, end ) + (...) + 2. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]) +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat(); + +// Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]) +let f = nf['formatRangeToParts']; + +assert.sameValue(typeof f, 'function'); +assert.throws(TypeError, () => { f(1, 23) }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/length.js new file mode 100644 index 000000000000..b77d30b677ea --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.NumberFormat.prototype.formatRangeToParts.length. +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ +verifyProperty(Intl.NumberFormat.prototype.formatRangeToParts, 'length', { + value: 2, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/name.js new file mode 100644 index 000000000000..ed7b412e29e7 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/name.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.NumberFormat.prototype.formatRangeToParts.name value and descriptor. +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ +verifyProperty(Intl.NumberFormat.prototype.formatRangeToParts, 'name', { + value: 'formatRangeToParts', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws.js new file mode 100644 index 000000000000..4be27f9a8140 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat-formatRangeToParts +description: > + "formatRangeToParts" Throws a RangeError if some of arguments is cast to NaN +info: | + Intl.NumberFormat.prototype.formatRangeToParts( start, end ) + (...) + 6. Return ? FormatNumericRangeToParts(nf, x, y). + + FormatNumericRangeToParts( numberFormat, x, y ) + 1. Let parts be ? PartitionNumberRangePattern(numberFormat, x, y). + + PartitionNumberRangePattern( numberFormat, x, y ) + 1. If x is NaN or y is NaN, throw a RangeError exception. +features: [Intl.NumberFormat-v3] +---*/ + + +const nf = new Intl.NumberFormat(); + +// If x or y is NaN ..., throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRangeToParts(NaN, 23) }); +assert.throws(RangeError, () => { nf.formatRangeToParts(12, NaN) }); +assert.throws(RangeError, () => { nf.formatRangeToParts(NaN, -23) }); +assert.throws(RangeError, () => { nf.formatRangeToParts(-12, NaN) }); +assert.throws(RangeError, () => { nf.formatRangeToParts(NaN, NaN) }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/prop-desc.js new file mode 100644 index 000000000000..83318e16ddeb --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/prop-desc.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Property type and descriptor. +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ + +assert.sameValue( + typeof Intl.NumberFormat.prototype.formatRangeToParts, + 'function', + '`typeof Intl.NumberFormat.prototype.formatRangeToParts` is `function`' +); + +verifyProperty(Intl.NumberFormat.prototype, 'formatRangeToParts', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/shell.js new file mode 100644 index 000000000000..54371b778989 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/undefined-arguments-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/undefined-arguments-throws.js new file mode 100644 index 000000000000..51249d0cc7d4 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/undefined-arguments-throws.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.formatRangeToParts +description: > + "formatRangeToParts" basic tests when arguments are undefined throw a TypeError exception. +info: | + Intl.NumberFormat.prototype.formatRangeToParts ( start, end ) + (...) + 3. If start is undefined or end is undefined, throw a TypeError exception. +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat(); + +// If arguments are undefined throw a TypeError exception. +assert.throws(TypeError, () => { nf.formatRangeToParts(undefined, 23) }); +assert.throws(TypeError, () => { nf.formatRangeToParts(1,undefined) }); +assert.throws(TypeError, () => { nf.formatRangeToParts(undefined, undefined)}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws.js new file mode 100644 index 000000000000..f850ff38ce28 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.formatRangeToParts +description: > + "formatRangeToParts" basic tests when argument x > y, BigInt included and covers PartitionNumberRangePattern throw a RangeError exception. +info: | + 1.1.21 PartitionNumberRangePattern( numberFormat, x, y ) + (...) + 1.1.21_2.a. If y is a mathematical value and y < x, throw a RangeError exception. + 1.1.21._2.b if y is -∞, throw a RangeError exception. + 1.1.21._2.c if y is -0 and x ≥ 0, throw a RangeError exception. + (...) + 1.1.21._3.a if y is a mathematical value, throw a RangeError exception + 1.1.21._3.b if y is -∞, throw a RangeError exception. + 1.1.21._3.c if y is -0, throw a RangeError exception. + (...) + 1.1.21_4.a if y is a mathematical value and y < 0, throw a RangeError exception. + 1.1.21_4.b if y is -∞, throw a RangeError exception. +features: [Intl.NumberFormat-v3] +---*/ + +const nf = new Intl.NumberFormat(); + +// If x > y, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRangeToParts(23, 12) }); + +// 1.1.21_2 (...) +// If x > y, throw a RangeError exception and both x and y are bigint. +assert.throws(RangeError, () => { nf.formatRangeToParts(23n, 12n) }); +//if y is -∞, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRangeToParts(23, -Infinity) }); +//if y is -0 and x ≥ 0, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRangeToParts(23, -0) }); +assert.throws(RangeError, () => { nf.formatRangeToParts(0, -0) }); + +// 1.1.21_3 (...) +// if y is a mathematical value, throw a RangeError exception +assert.throws(RangeError, () => { nf.formatRangeToParts(Infinity, 23) }); +// if y is -∞, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRangeToParts(Infinity, -Infinity) }); +// if y is -0, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRangeToParts(Infinity, -0) }); + +// 1.1.21_4 (...) +// if y is a mathematical value and y < 0, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRangeToParts(-0, -1) }); +// if y is -∞, throw a RangeError exception. +assert.throws(RangeError, () => { nf.formatRangeToParts(-0, -Infinity) }); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js index fc03d0b585ee..d2f61becd618 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.formattoparts -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [de-DE] features: [Intl.NumberFormat-unified] ---*/ @@ -60,12 +60,12 @@ const tests = [ for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); - verifyFormatParts(nf.formatToParts(-987), negative); - verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); - verifyFormatParts(nf.formatToParts(-0), negativeZero); - verifyFormatParts(nf.formatToParts(0), zero); - verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); - verifyFormatParts(nf.formatToParts(987), positive); + verifyFormatParts(nf.formatToParts(-987), negative, "negative"); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero"); + verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero"); + verifyFormatParts(nf.formatToParts(0), zero, "zero"); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero"); + verifyFormatParts(nf.formatToParts(987), positive, "positive"); } diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js index a55af1a2d56b..9905591d77f4 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.formattoparts -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [en-US] features: [Intl.NumberFormat-unified] ---*/ @@ -60,12 +60,12 @@ const tests = [ for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); - verifyFormatParts(nf.formatToParts(-987), negative); - verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); - verifyFormatParts(nf.formatToParts(-0), negativeZero); - verifyFormatParts(nf.formatToParts(0), zero); - verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); - verifyFormatParts(nf.formatToParts(987), positive); + verifyFormatParts(nf.formatToParts(-987), negative, "negative"); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero"); + verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero"); + verifyFormatParts(nf.formatToParts(0), zero, "zero"); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero"); + verifyFormatParts(nf.formatToParts(987), positive, "positive"); } diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js index c7feda2b40a6..67d4db79b35a 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.formattoparts -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [ja-JP] features: [Intl.NumberFormat-unified] ---*/ @@ -60,12 +60,12 @@ const tests = [ for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); - verifyFormatParts(nf.formatToParts(-987), negative); - verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); - verifyFormatParts(nf.formatToParts(-0), negativeZero); - verifyFormatParts(nf.formatToParts(0), zero); - verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); - verifyFormatParts(nf.formatToParts(987), positive); + verifyFormatParts(nf.formatToParts(-987), negative, "negative"); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero"); + verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero"); + verifyFormatParts(nf.formatToParts(0), zero, "zero"); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero"); + verifyFormatParts(nf.formatToParts(987), positive, "positive"); } diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js index 2188d980205b..226394e2ef34 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.formattoparts -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [ko-KR] features: [Intl.NumberFormat-unified] ---*/ @@ -60,12 +60,12 @@ const tests = [ for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); - verifyFormatParts(nf.formatToParts(-987), negative); - verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); - verifyFormatParts(nf.formatToParts(-0), negativeZero); - verifyFormatParts(nf.formatToParts(0), zero); - verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); - verifyFormatParts(nf.formatToParts(987), positive); + verifyFormatParts(nf.formatToParts(-987), negative, "negative"); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero"); + verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero"); + verifyFormatParts(nf.formatToParts(0), zero, "zero"); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero"); + verifyFormatParts(nf.formatToParts(987), positive, "positive"); } diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js index 89629468a28e..27027aee330e 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js @@ -3,7 +3,7 @@ /*--- esid: sec-intl.numberformat.prototype.formattoparts -description: Checks handling of the compactDisplay option to the NumberFormat constructor. +description: Checks handling of the signDisplay option to the NumberFormat constructor. locale: [zh-TW] features: [Intl.NumberFormat-unified] ---*/ @@ -60,12 +60,12 @@ const tests = [ for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); - verifyFormatParts(nf.formatToParts(-987), negative); - verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); - verifyFormatParts(nf.formatToParts(-0), negativeZero); - verifyFormatParts(nf.formatToParts(0), zero); - verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); - verifyFormatParts(nf.formatToParts(987), positive); + verifyFormatParts(nf.formatToParts(-987), negative, "negative"); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero"); + verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero"); + verifyFormatParts(nf.formatToParts(0), zero, "zero"); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero"); + verifyFormatParts(nf.formatToParts(987), positive, "positive"); } diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-de-DE.js new file mode 100644 index 000000000000..388e0869f41a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-de-DE.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); + +verifyFormatParts( + nf.formatToParts(-987), + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + "negative" +); +verifyFormatParts( + nf.formatToParts(-0.0001), + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + "negativeNearZero" +); +verifyFormatParts( + nf.formatToParts(-0), + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + "negativeZero" +); +verifyFormatParts( + nf.formatToParts(0), + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + "zero" +); +verifyFormatParts( + nf.formatToParts(0.0001), + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + "positiveNearZero" +); +verifyFormatParts( + nf.formatToParts(987), + [{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + "positive" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-en-US.js new file mode 100644 index 000000000000..f94f8b28b87f --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-en-US.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); + +verifyFormatParts( + nf.formatToParts(-987), + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + "negative" +); +verifyFormatParts( + nf.formatToParts(-0.0001), + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "negativeNearZero" +); +verifyFormatParts( + nf.formatToParts(-0), + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "negativeZero" +); +verifyFormatParts( + nf.formatToParts(0), + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "zero" +); +verifyFormatParts( + nf.formatToParts(0.0001), + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "positiveNearZero" +); +verifyFormatParts( + nf.formatToParts(987), + [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "positive" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ja-JP.js new file mode 100644 index 000000000000..c8f77888eeb8 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ja-JP.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); + +verifyFormatParts( + nf.formatToParts(-987), + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + "negative" +); +verifyFormatParts( + nf.formatToParts(-0.0001), + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "negativeNearZero" +); +verifyFormatParts( + nf.formatToParts(-0), + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "negativeZero" +); +verifyFormatParts( + nf.formatToParts(0), + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "zero" +); +verifyFormatParts( + nf.formatToParts(0.0001), + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "positiveNearZero" +); +verifyFormatParts( + nf.formatToParts(987), + [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "positive" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ko-KR.js new file mode 100644 index 000000000000..f8495a63e7eb --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ko-KR.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); + +verifyFormatParts( + nf.formatToParts(-987), + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + "negative" +); +verifyFormatParts( + nf.formatToParts(-0.0001), + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "negativeNearZero" +); +verifyFormatParts( + nf.formatToParts(-0), + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "negativeZero" +); +verifyFormatParts( + nf.formatToParts(0), + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "zero" +); +verifyFormatParts( + nf.formatToParts(0.0001), + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "positiveNearZero" +); +verifyFormatParts( + nf.formatToParts(987), + [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "positive" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-zh-TW.js new file mode 100644 index 000000000000..901059092d4c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-zh-TW.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" }); + +verifyFormatParts( + nf.formatToParts(-987), + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + "negative" +); +verifyFormatParts( + nf.formatToParts(-0.0001), + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "negativeNearZero" +); +verifyFormatParts( + nf.formatToParts(-0), + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "negativeZero" +); +verifyFormatParts( + nf.formatToParts(0), + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "zero" +); +verifyFormatParts( + nf.formatToParts(0.0001), + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "positiveNearZero" +); +verifyFormatParts( + nf.formatToParts(987), + [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + "positive" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-de-DE.js new file mode 100644 index 000000000000..365a51fdda92 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-de-DE.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const signDisplay = "negative"; +const nf = new Intl.NumberFormat("de-DE", {signDisplay: "negative"}); + +verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"NaN"}], `NaN (${signDisplay})`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-en-US.js new file mode 100644 index 000000000000..8522b632e4ee --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-en-US.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const signDisplay = "negative"; +const nf = new Intl.NumberFormat("en-US", {signDisplay: "negative"}); + +verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"NaN"}], `NaN (${signDisplay})`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ja-JP.js new file mode 100644 index 000000000000..b261a20cbcfa --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ja-JP.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const signDisplay = "negative"; +const nf = new Intl.NumberFormat("ja-JP", {signDisplay: "negative"}); + +verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"NaN"}], `NaN (${signDisplay})`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ko-KR.js new file mode 100644 index 000000000000..f150f010f9dc --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ko-KR.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const signDisplay = "negative"; +const nf = new Intl.NumberFormat("ko-KR", {signDisplay: "negative"}); + +verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"NaN"}], `NaN (${signDisplay})`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-zh-TW.js new file mode 100644 index 000000000000..abe75d860767 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-zh-TW.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-v3] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const signDisplay = "negative"; +const nf = new Intl.NumberFormat("zh-TW", {signDisplay: "negative"}); + +verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`); +verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`); +verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"非數值"}], `NaN (${signDisplay})`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js index 0fb1fb510d16..ab50612af2b2 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js @@ -1,4 +1,6 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet // Copyright 2012 Mozilla Corporation. All rights reserved. +// Copyright 2022 Apple Inc. All rights reserved. // This code is governed by the license found in the LICENSE file. /*--- @@ -9,6 +11,7 @@ description: > properties. author: Norbert Lindenberg includes: [testIntl.js, propertyHelper.js] +features: [Intl.NumberFormat-v3] ---*/ var actual = new Intl.NumberFormat().resolvedOptions(); @@ -25,7 +28,7 @@ assert.sameValue(actual.style, "decimal"); assert.sameValue(actual.minimumIntegerDigits, 1); assert.sameValue(actual.minimumFractionDigits, 0); assert.sameValue(actual.maximumFractionDigits, 3); -assert.sameValue(actual.useGrouping, true); +assert.sameValue(actual.useGrouping, "auto"); var dataPropertyDesc = { writable: true, enumerable: true, configurable: true }; verifyProperty(actual, "locale", dataPropertyDesc); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js index 81385e67c634..16f35fb743cf 100644 --- a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js @@ -4,7 +4,6 @@ /*--- esid: sec-intl.numberformat.prototype.resolvedoptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [compareArray.js] features: [Intl.NumberFormat-unified] ---*/ @@ -31,6 +30,14 @@ const expected = [ "signDisplay", ]; -assert.compareArray(Object.getOwnPropertyNames(options), expected); +const actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); +} reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/roundingMode.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/roundingMode.js new file mode 100644 index 000000000000..d65c73cba353 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/roundingMode.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// Copyright 2021 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat.prototype.resolvedoptions +description: roundingMode property for the object returned by resolvedOptions() +features: [Intl.NumberFormat-v3] +---*/ + +var options; + +options = new Intl.NumberFormat([], {}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'halfExpand', 'default'); + +options = new Intl.NumberFormat([], {roundingMode: 'ceil'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'ceil'); + +options = new Intl.NumberFormat([], {roundingMode: 'floor'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'floor'); + +options = new Intl.NumberFormat([], {roundingMode: 'expand'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'expand'); + +options = new Intl.NumberFormat([], {roundingMode: 'trunc'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'trunc'); + +options = new Intl.NumberFormat([], {roundingMode: 'halfCeil'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'halfCeil'); + +options = new Intl.NumberFormat([], {roundingMode: 'halfFloor'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'halfFloor'); + +options = new Intl.NumberFormat([], {roundingMode: 'halfExpand'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'halfExpand'); + +options = new Intl.NumberFormat([], {roundingMode: 'halfTrunc'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'halfTrunc'); + +options = new Intl.NumberFormat([], {roundingMode: 'halfEven'}).resolvedOptions(); +assert.sameValue(options.roundingMode, 'halfEven'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority.js b/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority.js new file mode 100644 index 000000000000..234461694216 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.numberformat +description: Tests that the option roundingPriority is processed correctly. +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +testOption( + Intl.NumberFormat, + "roundingPriority", + "string", + ["auto", "morePrecision", "lessPrecision"], + "auto" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping-extended.js b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping-extended.js new file mode 100644 index 000000000000..a18f77d1a700 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping-extended.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Tests that the option useGrouping is processed correctly. +info: | + The "Intl.NumberFormat v3" proposal contradicts the behavior required by the + latest revision of ECMA402. Likewise, this test contradicts + test-option-useGrouping.js. Until the proposal is included in a published + standard (when the tests' discrepancies can be resolved), implementations + should only expect to pass one of these two tests. +features: [Intl.NumberFormat-v3] +---*/ + +function render(options) { + var nf = new Intl.NumberFormat(undefined, options); + return nf.resolvedOptions().useGrouping; +} + +assert.sameValue(render({}), 'auto', '(omitted)'); +assert.sameValue(render({useGrouping: undefined}), 'auto', 'undefined'); +assert.sameValue(render({useGrouping: 'auto'}), 'auto', '"auto"'); +assert.sameValue(render({useGrouping: true}), 'always', 'true'); +assert.sameValue(render({useGrouping: 'always'}), 'always', '"always"'); +assert.sameValue(render({useGrouping: false}), false, 'false'); +assert.sameValue(render({useGrouping: null}), false, 'null'); +assert.sameValue(render({useGrouping: 'min2'}), 'min2', '"min2"'); + +assert.sameValue(render({notation: 'compact'}), 'min2', 'compact, (omitted)'); +assert.sameValue(render({notation: 'compact', useGrouping: undefined}), 'min2', 'compact, undefined'); +assert.sameValue(render({notation: 'compact', useGrouping: 'auto'}), 'auto', 'compact, "auto"'); +assert.sameValue(render({notation: 'compact', useGrouping: true}), 'always', 'compact, true'); +assert.sameValue(render({notation: 'compact', useGrouping: 'always'}), 'always', 'compact, "always"'); +assert.sameValue(render({notation: 'compact', useGrouping: false}), false, 'compact, false'); +assert.sameValue(render({notation: 'compact', useGrouping: null}), false, 'compact, null'); +assert.sameValue(render({notation: 'compact', useGrouping: 'min2'}), 'min2', 'compact, "min2"'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat(undefined, {useGrouping: 'undefined'}); +}, '"undefined"'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat(undefined, {useGrouping: 'false'}); +}, '"false"'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat(undefined, {useGrouping: 'true'}); +}, '"true"'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat(undefined, {useGrouping: 'min3'}); +}, '"min3"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js index 4e9317af310b..a4ae0400feaf 100644 --- a/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js +++ b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js @@ -1,13 +1,39 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet // Copyright 2012 Mozilla Corporation. All rights reserved. +// Copyright 2022 Apple Inc. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- es5id: 11.1.1_34 description: Tests that the option useGrouping is processed correctly. +info: | + The "Intl.NumberFormat v3" proposal contradicts the behavior required by the + latest revision of ECMA402. Likewise, this test contradicts + test-option-useGrouping-extended.js. Until the proposal is included in a + published standard (when the tests' discrepancies can be resolved), + implementations should only expect to pass one of these two tests. author: Norbert Lindenberg -includes: [testIntl.js] +features: [Intl.NumberFormat-v3] ---*/ -testOption(Intl.NumberFormat, "useGrouping", "boolean", undefined, true); +function resolveUseGrouping(option) { + return new Intl.NumberFormat(undefined, { useGrouping: option }).resolvedOptions().useGrouping; +} + +for (let string of ["min2", "auto", "always"]) { + assert.sameValue(resolveUseGrouping(string), string); +} + +assert.sameValue(resolveUseGrouping(true), "always"); +assert.sameValue(resolveUseGrouping(false), false); +assert.sameValue(resolveUseGrouping(undefined), "auto"); + +for (let falsy of [0, null, ""]) { + assert.sameValue(resolveUseGrouping(falsy), false); +} + +for (let truthy of [42, "MIN2", {}]) { + assert.throws(RangeError, () => { resolveUseGrouping(truthy); }, "Invalid truthy value"); +} reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/order.js index b4a87c025928..4d39e632ebc1 100644 --- a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/order.js +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/order.js @@ -4,7 +4,6 @@ /*--- esid: sec-intl.numberformat.prototype.resolvedoptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [compareArray.js] features: [Intl.NumberFormat-unified] ---*/ @@ -22,6 +21,14 @@ const expected = [ "pluralCategories", ]; -assert.compareArray(Object.getOwnPropertyNames(options), expected); +const actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); +} reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/argument-tonumber-throws.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/argument-tonumber-throws.js new file mode 100644 index 000000000000..9d6ebd4c64e1 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/argument-tonumber-throws.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.selectRange +description: > + "selectRange" basic tests when argument cannot be converted using ToNumber +info: | + Intl.PluralRules.prototype.selectRange ( start, end ) + (...) + 4. Let x be ? ToNumber(start). + 5. Let y be ? ToNumber(end). +locale: [en-US] +features: [Intl.NumberFormat-v3] +---*/ + +const pr = new Intl.PluralRules("en-US"); + +// Throw if arguments cannot be cast toNumber +assert.throws(TypeError, () => { pr.selectRange(Symbol(102), 201) }); +assert.throws(TypeError, () => { pr.selectRange(102,Symbol(201)) }); +assert.throws(TypeError, () => { pr.selectRange(23n, 100) }); +assert.throws(TypeError, () => { pr.selectRange(100, 23n) }); +assert.throws(TypeError, () => { pr.selectRange(23n, 23n) }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/browser.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/default-en-us.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/default-en-us.js new file mode 100644 index 000000000000..a1130b1f443b --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/default-en-us.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.PluralRules.prototype.selectRange default behaviour returning "few" or "other" +locale: [en-US] +features: [Intl.NumberFormat-v3] +---*/ + +const pr = new Intl.PluralRules("en-US"); + +assert.sameValue(pr.selectRange(102, 201), "other"); +assert.sameValue(pr.selectRange(200, 200), "other"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/invoked-as-func.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/invoked-as-func.js new file mode 100644 index 000000000000..602e815d5f46 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/invoked-as-func.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.selectRange +description: basic tests internal slot initialization and call receiver errors +info: | + Intl.PluralRules.prototype.selectRange(start, end ) + (...) + 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]) +features: [Intl.NumberFormat-v3] +---*/ + +const pr = new Intl.PluralRules(); + +// Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]). +let sr = pr['selectRange']; + +assert.sameValue(typeof sr, 'function'); +assert.throws(TypeError, () => { sr(1, 23) }); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/length.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/length.js new file mode 100644 index 000000000000..1f723589b3d1 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/length.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.selectRange +description: Intl.PluralRules.prototype.selectRange.length is 2 +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ + +verifyProperty(Intl.PluralRules.prototype.selectRange, 'length', { + value: 2, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/name.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/name.js new file mode 100644 index 000000000000..d3b850d7f250 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/name.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.selectRange +description: Intl.PluralRules.prototype.selectRange.name is "selectRange" +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ + +verifyProperty(Intl.PluralRules.prototype.selectRange, 'name', { + value: 'selectRange', + enumerable: false, + writable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/nan-arguments-throws.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/nan-arguments-throws.js new file mode 100644 index 000000000000..12fc44c58b00 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/nan-arguments-throws.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.selectRange +description: > + "selectRange" Throws a RangeError if some of arguments is cast to NaN +info: | + Intl.PluralRules.prototype.selectRange ( start, end ) + (...) + WIP: https://github.com/tc39/proposal-intl-numberformat-v3/pull/76 + + +features: [Intl.NumberFormat-v3] +---*/ + +const pr = new Intl.PluralRules(); + +assert.throws(RangeError, () => { pr.selectRange(NaN, 100) }, "NaN/Number"); +assert.throws(RangeError, () => { pr.selectRange(100, NaN) }, "Number/NaN"); +assert.throws(RangeError, () => { pr.selectRange(NaN, NaN) }, "NaN/NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/prop-desc.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/prop-desc.js new file mode 100644 index 000000000000..a65445561e7b --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.selectRange +description: Property descriptor of Intl.PluralRules.prototype.selectRange +includes: [propertyHelper.js] +features: [Intl.NumberFormat-v3] +---*/ + +assert.sameValue( + typeof Intl.PluralRules.prototype.selectRange, + 'function', + '`typeof Intl.PluralRules.prototype.selectRange` is `function`' +); + +verifyProperty(Intl.PluralRules.prototype, 'selectRange', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/shell.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/undefined-arguments-throws.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/undefined-arguments-throws.js new file mode 100644 index 000000000000..48cc5fd4cac3 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/undefined-arguments-throws.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.selectRange +description: > + "selectRange" basic tests when arguments are undefined throw a TypeError exception. +info: | + Intl.PluralRules.prototype.selectRange ( start, end ) + (...) + 3. If start is undefined or end is undefined, throw a TypeError exception. +features: [Intl.NumberFormat-v3] +---*/ + +const pr = new Intl.PluralRules(); + +// 1. If arguments are undefined throw a TypeError exception. +assert.throws(TypeError, () => { pr.selectRange(undefined, 201) }); +assert.throws(TypeError, () => { pr.selectRange(102, undefined) }); +assert.throws(TypeError, () => { pr.selectRange(undefined, undefined)}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/x-greater-than-y-throws.js b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/x-greater-than-y-throws.js new file mode 100644 index 000000000000..fe8883fdbdfa --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/selectRange/x-greater-than-y-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(release_or_beta) -- Intl.NumberFormat-v3 is not released yet +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.selectRange +description: > + "selectRange" basic tests when argument x > y, throw a RangeError exception. +info: | + 1.1.6 ResolvePluralRange ( pluralRules, x, y ) + (...) + 5. If x > y, throw a RangeError exception. +features: [Intl.NumberFormat-v3] +---*/ + +const pr = new Intl.PluralRules(); + +// 1. If x > y, throw a RangeError exception. +assert.throws(RangeError, () => { pr.selectRange(201, 102) }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/order.js index c5f35fd39682..c0017b721c89 100644 --- a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/order.js +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/order.js @@ -4,7 +4,6 @@ /*--- esid: sec-intl.relativetimeformat.prototype.resolvedoptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [compareArray.js] features: [Intl.RelativeTimeFormat] ---*/ @@ -17,6 +16,14 @@ const expected = [ "numberingSystem", ]; -assert.compareArray(Object.getOwnPropertyNames(options), expected); +const actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); +} reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/order.js index 8da78e8f2f4c..139f6c1c4c2e 100644 --- a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/order.js +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/order.js @@ -5,7 +5,6 @@ /*--- esid: sec-Intl.Segmenter.prototype.resolvedOptions description: Verifies the property order for the object returned by resolvedOptions(). -includes: [compareArray.js] features: [Intl.Segmenter] ---*/ @@ -18,6 +17,14 @@ const expected = [ "granularity", ]; -assert.compareArray(Object.getOwnPropertyNames(options), expected); +const actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(actual.indexOf("locale") > -1, "\"locale\" is present"); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`); +} reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/from/basic.js b/js/src/tests/test262/intl402/Temporal/Calendar/from/basic.js new file mode 100644 index 000000000000..141946a33c80 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/from/basic.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Support for non-ISO calendars in Calendar.from(). +features: [Temporal] +---*/ + +function test(item, id = item) { + const calendar = Temporal.Calendar.from(item); + assert(calendar instanceof Temporal.Calendar, `Calendar.from(${item}) is a calendar`); + assert.sameValue(calendar.id, id, `Calendar.from(${item}) has the correct ID`); +} +test("gregory"); +test("japanese"); +test("1994-11-05T08:15:30-05:00[u-ca=gregory]", "gregory"); +test("1994-11-05T13:15:30Z[u-ca=japanese]", "japanese"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/from/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/from/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/from/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..398929b0d0ea --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dateadd +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const duration = new Temporal.Duration(1); + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.dateAdd({ era: "ad", eraYear: inf, month: 5, day: 2, calendar: instance }, duration, { overflow }), `eraYear property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.dateAdd({ era: "ad", eraYear: obj, month: 5, day: 2, calendar: instance }, duration, { overflow })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateAdd/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..cbbb7e79e0f5 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.datefromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.dateFromFields({ ...base, eraYear: inf }, { overflow }), `eraYear property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.dateFromFields({ ...base, eraYear: obj }, { overflow })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateFromFields/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..60409fab3122 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dateuntil +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const other = new Temporal.PlainDate(2001, 6, 3); +const base = { era: "ad", month: 5, day: 2, calendar: instance }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.dateUntil({ ...base, eraYear: inf }, other), `eraYear property cannot be ${inf}`); + + assert.throws(RangeError, () => instance.dateUntil(other, { ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, "eraYear"); + assert.throws(RangeError, () => instance.dateUntil({ ...base, eraYear: obj1 }, other)); + assert.compareArray(calls1, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, "eraYear"); + assert.throws(RangeError, () => instance.dateUntil(other, { ...base, eraYear: obj2 })); + assert.compareArray(calls2, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dateUntil/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..688ae1782fe6 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.day +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.day({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.day({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/day/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..7592f2267fd5 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dayofweek +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.dayOfWeek({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.dayOfWeek({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfWeek/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..2b78e42395ab --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dayofyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.dayOfYear({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.dayOfYear({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/dayOfYear/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..74a7d21daffe --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.daysinmonth +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.daysInMonth({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.daysInMonth({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInMonth/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..43ed9a7478f5 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.daysinweek +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.daysInWeek({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.daysInWeek({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInWeek/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..94158bc1c7bf --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.daysinyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.daysInYear({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.daysInYear({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/daysInYear/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js new file mode 100644 index 000000000000..aed5a0da4eaf --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.era(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-string-with-utc-designator.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..b1b1192937b4 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.era(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..effcf747e35b --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.era(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/era/branding.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/Calendar/prototype/era/branding.js rename to js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/builtin.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/builtin.js new file mode 100644 index 000000000000..aff39598a5fe --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: > + Tests that Temporal.Calendar.prototype.era + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.era), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.era), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.era), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.era.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..23589a8b7cfa --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.era({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..4efbaff92704 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.era +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.era({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.era({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/length.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/length.js new file mode 100644 index 000000000000..8a666b83802d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: Temporal.Calendar.prototype.era.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.era, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/name.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/name.js new file mode 100644 index 000000000000..32fed7037b2f --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: Temporal.Calendar.prototype.era.name is "era". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.era, "name", { + value: "era", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/not-a-constructor.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/not-a-constructor.js new file mode 100644 index 000000000000..46303e3e74d6 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: > + Temporal.Calendar.prototype.era does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.era(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.era), false, + "isConstructor(Temporal.Calendar.prototype.era)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/prop-desc.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/prop-desc.js new file mode 100644 index 000000000000..1ca4d3246a20 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: The "era" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.era, + "function", + "`typeof Calendar.prototype.era` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "era", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/year-zero.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/year-zero.js new file mode 100644 index 000000000000..9686051bef45 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/era/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.era(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js new file mode 100644 index 000000000000..eb3aa2316562 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.eraYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-string-with-utc-designator.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-string-with-utc-designator.js new file mode 100644 index 000000000000..34b43fd21657 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.eraYear(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..023a487e8de6 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.eraYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/eraYear/branding.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/Calendar/prototype/eraYear/branding.js rename to js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/builtin.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/builtin.js new file mode 100644 index 000000000000..dab84976b2c6 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: > + Tests that Temporal.Calendar.prototype.eraYear + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.eraYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.eraYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.eraYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.eraYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 000000000000..e54fe8e5d77f --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +calendar.eraYear({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..fa70f290da8d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.erayear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.eraYear({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.eraYear({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/length.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/length.js new file mode 100644 index 000000000000..8bc4aeddc087 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/length.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: Temporal.Calendar.prototype.eraYear.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.eraYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/name.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/name.js new file mode 100644 index 000000000000..e9fd54b9a6b3 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/name.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: Temporal.Calendar.prototype.eraYear.name is "eraYear". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.eraYear, "name", { + value: "eraYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/not-a-constructor.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/not-a-constructor.js new file mode 100644 index 000000000000..a4c5e17bab71 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: > + Temporal.Calendar.prototype.eraYear does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.eraYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.eraYear), false, + "isConstructor(Temporal.Calendar.prototype.eraYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/prop-desc.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/prop-desc.js new file mode 100644 index 000000000000..138818e7382b --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: The "eraYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.eraYear, + "function", + "`typeof Calendar.prototype.eraYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "eraYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/shell.js new file mode 100644 index 000000000000..5228295abfe7 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/shell.js @@ -0,0 +1,1517 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/year-zero.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/year-zero.js new file mode 100644 index 000000000000..9e25ef926e02 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/eraYear/year-zero.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const arg = "-000000-10-31"; +const instance = new Temporal.Calendar("iso8601"); + +assert.throws( + RangeError, + () => { instance.eraYear(arg); }, + "reject minus zero as extended year" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..caeb8281df83 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.inleapyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.inLeapYear({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.inLeapYear({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/inLeapYear/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..17c583a8818f --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.month +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.month({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.month({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/month/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..e5b3065f20c0 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.monthcode +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.monthCode({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.monthCode({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthCode/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..7880fa7c56c7 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.monthdayfromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.monthDayFromFields({ ...base, eraYear: inf }, { overflow }), `eraYear property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.monthDayFromFields({ ...base, eraYear: obj }, { overflow })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthDayFromFields/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..6493d010c33a --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.monthsinyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.monthsInYear({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.monthsInYear({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/monthsInYear/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..92c6b67bc574 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.weekofyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.weekOfYear({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.weekOfYear({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/weekOfYear/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..9d27f7a89b7d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.year +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.year({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.year({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/year/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/browser.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..2b272f08c615 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.yearmonthfromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("gregory"); +const base = { era: "ad", month: 5, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.yearMonthFromFields({ ...base, eraYear: inf }, { overflow }), `eraYear property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.yearMonthFromFields({ ...base, eraYear: obj }, { overflow })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Calendar/prototype/yearMonthFromFields/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Calendar/shell.js b/js/src/tests/test262/intl402/Temporal/Calendar/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Duration/browser.js b/js/src/tests/test262/intl402/Temporal/Duration/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/browser.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/relativeto-infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/relativeto-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..e043c6abd9ff --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/relativeto-infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.duration.prototype.add +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.add(instance, { relativeTo: { ...base, eraYear: inf } }), `eraYear property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.add(instance, { relativeTo: { ...base, eraYear: obj } })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/relativeto-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/relativeto-string-datetime.js new file mode 100644 index 000000000000..fbc12e34d24f --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/relativeto-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +description: > + Conversion of ISO date-time strings as relativeTo option to + Temporal.ZonedDateTime or Temporal.PlainDateTime instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = "2019-11-01T00:00[America/Vancouver]"; +const result4 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result4, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00Z[America/Vancouver]"; +const result5 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result5, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00-07:00[America/Vancouver]"; +const result6 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); +TemporalHelpers.assertDuration(result6, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+04:15[America/Vancouver]"; +assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/shell.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/add/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/browser.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/relativeto-infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/relativeto-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..02c05819612c --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/relativeto-infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.duration.prototype.round +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.round({ smallestUnit: "seconds", relativeTo: { ...base, eraYear: inf } }), `eraYear property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.round({ smallestUnit: "seconds", relativeTo: { ...base, eraYear: obj } })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/relativeto-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/relativeto-string-datetime.js new file mode 100644 index 000000000000..84da06ecee48 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/relativeto-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + Conversion of ISO date-time strings as relativeTo option to + Temporal.ZonedDateTime or Temporal.PlainDateTime instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = "2019-11-01T00:00[America/Vancouver]"; +const result4 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result4, 1, 0, 0, 0, 24, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00Z[America/Vancouver]"; +const result5 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result5, 1, 0, 0, 0, 24, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00-07:00[America/Vancouver]"; +const result6 = instance.round({ largestUnit: "years", relativeTo }); +TemporalHelpers.assertDuration(result6, 1, 0, 0, 0, 24, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+04:15[America/Vancouver]"; +assert.throws(RangeError, () => instance.round({ largestUnit: "years", relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/shell.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/round/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/browser.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/relativeto-infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/relativeto-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..fd20b09ab15d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/relativeto-infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.duration.prototype.subtract +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.subtract(instance, { relativeTo: { ...base, eraYear: inf } }), `eraYear property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.subtract(instance, { relativeTo: { ...base, eraYear: obj } })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/relativeto-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/relativeto-string-datetime.js new file mode 100644 index 000000000000..5987b70dfe32 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/relativeto-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +description: > + Conversion of ISO date-time strings as relativeTo option to + Temporal.ZonedDateTime or Temporal.PlainDateTime instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 1); + +let relativeTo = "2019-11-01T00:00[America/Vancouver]"; +const result4 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result4, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00Z[America/Vancouver]"; +const result5 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result5, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00-07:00[America/Vancouver]"; +const result6 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }); +TemporalHelpers.assertDuration(result6, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+04:15[America/Vancouver]"; +assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/shell.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/subtract/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/browser.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/relativeto-infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/relativeto-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..7c75eb356e8c --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/relativeto-infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.duration.prototype.total +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.total({ unit: "seconds", relativeTo: { ...base, eraYear: inf } }), `eraYear property cannot be ${inf} in relativeTo`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.total({ unit: "seconds", relativeTo: { ...base, eraYear: obj } })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/relativeto-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/relativeto-string-datetime.js new file mode 100644 index 000000000000..55f6566ca1d5 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/relativeto-string-datetime.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + Conversion of ISO date-time strings as relativeTo option to + Temporal.ZonedDateTime or Temporal.PlainDateTime instances +features: [Temporal] +---*/ + +const instance = new Temporal.Duration(1, 0, 0, 0, 24); + +let relativeTo = "2019-11-01T00:00[America/Vancouver]"; +const result4 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result4, 366.96, "date-time + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00Z[America/Vancouver]"; +const result5 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result5, 366.96, "date-time + Z + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00-07:00[America/Vancouver]"; +const result6 = instance.total({ unit: "days", relativeTo }); +assert.sameValue(result6, 366.96, "date-time + offset + IANA annotation is a zoned relativeTo"); + +relativeTo = "2019-11-01T00:00+04:15[America/Vancouver]"; +assert.throws(RangeError, () => instance.total({ unit: "days", relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/shell.js b/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Duration/prototype/total/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/Duration/shell.js b/js/src/tests/test262/intl402/Temporal/Duration/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/browser.js b/js/src/tests/test262/intl402/Temporal/Instant/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/locales-undefined.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/locales-undefined.js new file mode 100644 index 000000000000..6148d02e04c2 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/locales-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: Omitting the locales argument defaults to the DateTimeFormat default +features: [BigInt, Temporal] +---*/ + +const instant = new Temporal.Instant(957270896_987_650_000n); +const defaultFormatter = new Intl.DateTimeFormat([], Object.create(null)); +const expected = defaultFormatter.format(instant); + +const actualExplicit = instant.toLocaleString(undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = instant.toLocaleString(); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/options-conflict.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/options-conflict.js new file mode 100644 index 000000000000..e79a627e54cb --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/options-conflict.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-temporal.instant.prototype.tolocalestring +description: > + Conflicting properties of dateStyle must be rejected with a TypeError for the options argument +info: | + Using sec-temporal-getdatetimeformatpattern: + GetDateTimeFormatPattern ( dateStyle, timeStyle, matcher, opt, dataLocaleData, hc ) + + 1. If dateStyle is not undefined or timeStyle is not undefined, then + a. For each row in Table 7, except the header row, do + i. Let prop be the name given in the Property column of the row. + ii. Let p be opt.[[]]. + iii. If p is not undefined, then + 1. Throw a TypeError exception. +features: [BigInt, Temporal] +---*/ + +// Table 14 - Supported fields + example value for each field +const conflictingOptions = [ + [ "weekday", "short" ], + [ "era", "short" ], + [ "year", "numeric" ], + [ "month", "numeric" ], + [ "day", "numeric" ], + [ "hour", "numeric" ], + [ "minute", "numeric" ], + [ "second", "numeric" ], + [ "dayPeriod", "short" ], + [ "fractionalSecondDigits", 3 ], +]; +const instant = new Temporal.Instant(957270896_987_650_000n); + +assert.sameValue(typeof instant.toLocaleString("en", { dateStyle: "short" }), "string"); +assert.sameValue(typeof instant.toLocaleString("en", { timeStyle: "short" }), "string"); + +for (const [ option, value ] of conflictingOptions) { + assert.throws(TypeError, function() { + instant.toLocaleString("en", { [option]: value, dateStyle: "short" }); + }, `instant.toLocaleString("en", { ${option}: "${value}", dateStyle: "short" }) throws TypeError`); + + assert.throws(TypeError, function() { + instant.toLocaleString("en", { [option]: value, timeStyle: "short" }); + }, `instant.toLocaleString("en", { ${option}: "${value}", timeStyle: "short" }) throws TypeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/options-undefined.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/options-undefined.js new file mode 100644 index 000000000000..2d5833d5ec33 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/options-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const instant = new Temporal.Instant(957270896_987_650_000n); +const defaultFormatter = new Intl.DateTimeFormat('en', Object.create(null)); +const expected = defaultFormatter.format(instant); + +const actualExplicit = instant.toLocaleString('en', undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = instant.toLocaleString('en'); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toLocaleString/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/browser.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/shell.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/timezone-string-datetime.js new file mode 100644 index 000000000000..eb823f64c1cb --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toString/timezone-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = instance.toString({ timeZone }); +assert.sameValue(result1.substr(-6), "-08:00", "date-time + IANA annotation is the IANA time zone"); +const result2 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result2.substr(-6), "-08:00", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = instance.toString({ timeZone }); +assert.sameValue(result3.substr(-6), "-08:00", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result4.substr(-6), "-08:00", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = instance.toString({ timeZone }); +assert.sameValue(result5.substr(-6), "-08:00", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = instance.toString({ timeZone: { timeZone } }); +assert.sameValue(result6.substr(-6), "-08:00", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..96d1a11e9200 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result1.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result2.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result3.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result4.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = instance.toZonedDateTime({ timeZone, calendar: "iso8601" }); +assert.sameValue(result5.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTime({ timeZone: { timeZone }, calendar: "iso8601" }); +assert.sameValue(result6.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/browser.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/shell.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-datetime.js new file mode 100644 index 000000000000..5278f1db4e6e --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Instant/prototype/toZonedDateTimeISO/timezone-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tozoneddatetimeiso +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(0n); + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result1.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result2.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result3.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result4.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = instance.toZonedDateTimeISO(timeZone); +assert.sameValue(result5.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTimeISO({ timeZone }); +assert.sameValue(result6.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Instant/shell.js b/js/src/tests/test262/intl402/Temporal/Instant/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/browser.js b/js/src/tests/test262/intl402/Temporal/Now/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDate/browser.js b/js/src/tests/test262/intl402/Temporal/Now/plainDate/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDate/calendar-string.js b/js/src/tests/test262/intl402/Temporal/Now/plainDate/calendar-string.js new file mode 100644 index 000000000000..dad18c5a2501 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Now/plainDate/calendar-string.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindate +description: String calendar argument +features: [Temporal] +---*/ + +const date = Temporal.Now.plainDate("gregory"); +assert(date instanceof Temporal.PlainDate); +assert.sameValue(date.calendar.id, "gregory"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDate/shell.js b/js/src/tests/test262/intl402/Temporal/Now/plainDate/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/Now/plainDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDateTime/calendar-string.js b/js/src/tests/test262/intl402/Temporal/Now/plainDateTime/calendar-string.js new file mode 100644 index 000000000000..abba88e6957e --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Now/plainDateTime/calendar-string.js @@ -0,0 +1,15 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.plaindatetime +description: String calendar argument +features: [Temporal] +---*/ + +const dt = Temporal.Now.plainDateTime("gregory"); +assert(dt instanceof Temporal.PlainDateTime); +assert.sameValue(dt.calendar.id, "gregory"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/Now/plainDateTime/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/browser.js b/js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/shell.js b/js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/timezone-string-datetime.js new file mode 100644 index 000000000000..c8bfcda54332 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Now/plainDateTimeISO/timezone-string-datetime.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.now.plaindatetimeiso +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => Temporal.Now.plainDateTimeISO(timeZone), "bare date-time string is not a time zone"); +assert.throws(RangeError, () => Temporal.Now.plainDateTimeISO({ timeZone }), "bare date-time string is not a time zone"); + +// The following are all valid strings so should not throw: + +[ + "2021-08-19T17:30Z", + "2021-08-19T1730Z", + "2021-08-19T17:30-07:00", + "2021-08-19T1730-07:00", + "2021-08-19T17:30-0700", + "2021-08-19T1730-0700", + "2021-08-19T17:30[America/Vancouver]", + "2021-08-19T1730[America/Vancouver]", + "2021-08-19T17:30Z[America/Vancouver]", + "2021-08-19T1730Z[America/Vancouver]", + "2021-08-19T17:30-07:00[America/Vancouver]", + "2021-08-19T1730-07:00[America/Vancouver]", + "2021-08-19T17:30-0700[America/Vancouver]", + "2021-08-19T1730-0700[America/Vancouver]", +].forEach((timeZone) => { + Temporal.Now.plainDateTimeISO(timeZone); + Temporal.Now.plainDateTimeISO({ timeZone }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Now/shell.js b/js/src/tests/test262/intl402/Temporal/Now/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/calendar-string.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/calendar-string.js new file mode 100644 index 000000000000..d1c0921343eb --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/calendar-string.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: String calendar argument +features: [Temporal] +---*/ + +const zdt = Temporal.Now.zonedDateTime("gregory"); +const tz = Temporal.Now.timeZone(); +assert(zdt instanceof Temporal.ZonedDateTime); +assert(zdt.calendar instanceof Temporal.Calendar); +assert.sameValue(zdt.calendar.id, "gregory"); +assert(zdt.timeZone instanceof Temporal.TimeZone); +assert.sameValue(zdt.timeZone.id, tz.id); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/calendar-timezone-string.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/calendar-timezone-string.js new file mode 100644 index 000000000000..46723c903306 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/calendar-timezone-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: String calendar and time zone arguments +features: [Temporal] +---*/ + +const zdt = Temporal.Now.zonedDateTime("gregory", "America/Los_Angeles"); +assert(zdt instanceof Temporal.ZonedDateTime); +assert(zdt.calendar instanceof Temporal.Calendar); +assert.sameValue(zdt.calendar.id, "gregory"); +assert(zdt.timeZone instanceof Temporal.TimeZone); +assert.sameValue(zdt.timeZone.id, "America/Los_Angeles"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..5b2fd3bee184 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTime/timezone-string-datetime.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result1.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result2.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result3.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result4.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = Temporal.Now.zonedDateTime("iso8601", timeZone); +assert.sameValue(result5.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = Temporal.Now.zonedDateTime("iso8601", { timeZone }); +assert.sameValue(result6.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/browser.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/shell.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/timezone-string-datetime.js new file mode 100644 index 000000000000..535719d23b81 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/timezone-string-datetime.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result1.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result2.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result3.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result4.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = Temporal.Now.zonedDateTimeISO(timeZone); +assert.sameValue(result5.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = Temporal.Now.zonedDateTimeISO({ timeZone }); +assert.sameValue(result6.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/timezone-string.js b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/timezone-string.js new file mode 100644 index 000000000000..31a7badf2851 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/Now/zonedDateTimeISO/timezone-string.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.now.zoneddatetimeiso +description: String calendar argument +features: [Temporal] +---*/ + +const zdt = Temporal.Now.zonedDateTimeISO("America/Los_Angeles"); +assert(zdt instanceof Temporal.ZonedDateTime); +assert(zdt.calendar instanceof Temporal.Calendar); +assert.sameValue(zdt.calendar.id, "iso8601"); +assert(zdt.timeZone instanceof Temporal.TimeZone); +assert.sameValue(zdt.timeZone.id, "America/Los_Angeles"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/compare/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/compare/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDate/compare/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..bf1307a3be82 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/compare/infinity-throws-rangeerror.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.plaindate.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const other = new Temporal.PlainDate(2000, 5, 2, "gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => Temporal.PlainDate.compare({ ...base, eraYear: inf }, other), `eraYear property cannot be ${inf}`); + + assert.throws(RangeError, () => Temporal.PlainDate.compare(other, { ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainDate.compare({ ...base, eraYear: obj1 }, other)); + assert.compareArray(calls1, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainDate.compare(other, { ...base, eraYear: obj2 })); + assert.compareArray(calls2, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/compare/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/compare/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/compare/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/from/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/from/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDate/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..6d341238f363 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/from/infinity-throws-rangeerror.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainDate.from({ ...base, eraYear: inf }, { overflow }), `eraYear property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainDate.from({ ...base, eraYear: obj }, { overflow })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/from/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/from/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/from/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..1e79b183c87f --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2, "gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/equals/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/era/branding.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/era/branding.js rename to js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/prop-desc.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/prop-desc.js new file mode 100644 index 000000000000..b1303ffd922d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.era +description: The "era" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "era"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/era/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/eraYear/branding.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/eraYear/branding.js rename to js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/calendar-returns-infinity.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/calendar-returns-infinity.js new file mode 100644 index 000000000000..891263804778 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.erayear +description: Getter throws if the calendar returns ±∞ from its eraYear method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + eraYear() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainDate(2000, 5, 2, pos); +assert.throws(RangeError, () => instance1.eraYear); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainDate(2000, 5, 2, neg); +assert.throws(RangeError, () => instance2.eraYear); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/prop-desc.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/prop-desc.js new file mode 100644 index 000000000000..d16374c200f4 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.erayear +description: The "eraYear" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "eraYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/eraYear/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..ff496468f373 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.prototype.since +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2, "gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.since({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.since({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/since/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/locales-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/locales-undefined.js new file mode 100644 index 000000000000..6aca6799edbb --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/locales-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: Omitting the locales argument defaults to the DateTimeFormat default +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const defaultFormatter = new Intl.DateTimeFormat([], Object.create(null)); +const expected = defaultFormatter.format(date); + +const actualExplicit = date.toLocaleString(undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = date.toLocaleString(); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict.js new file mode 100644 index 000000000000..ab8f1b8e2f32 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-temporal.plaindate.prototype.tolocalestring +description: > + Conflicting properties of dateStyle must be rejected with a TypeError for the options argument +info: | + Using sec-temporal-getdatetimeformatpattern: + GetDateTimeFormatPattern ( dateStyle, timeStyle, matcher, opt, dataLocaleData, hc ) + + 1. If dateStyle is not undefined or timeStyle is not undefined, then + a. For each row in Table 7, except the header row, do + i. Let prop be the name given in the Property column of the row. + ii. Let p be opt.[[]]. + iii. If p is not undefined, then + 1. Throw a TypeError exception. +features: [Temporal] +---*/ + +// Table 14 - Supported fields + example value for each field +const conflictingOptions = [ + [ "weekday", "short" ], + [ "era", "short" ], + [ "year", "numeric" ], + [ "month", "numeric" ], + [ "day", "numeric" ], +]; +const date = new Temporal.PlainDate(2000, 5, 2); + +assert.sameValue(typeof date.toLocaleString("en", { dateStyle: "short" }), "string"); + +for (const [ option, value ] of conflictingOptions) { + assert.throws(TypeError, function() { + date.toLocaleString("en", { [option]: value, dateStyle: "short" }); + }, `date.toLocaleString("en", { ${option}: "${value}", dateStyle: "short" }) throws TypeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/options-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/options-undefined.js new file mode 100644 index 000000000000..d287ec2383ea --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/options-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const defaultFormatter = new Intl.DateTimeFormat('en', Object.create(null)); +const expected = defaultFormatter.format(date); + +const actualExplicit = date.toLocaleString('en', undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = date.toLocaleString('en'); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/resolved-time-zone.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/resolved-time-zone.js new file mode 100644 index 000000000000..8894fbc10470 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/resolved-time-zone.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2021, 8, 4); +const result = date.toLocaleString("en", { timeZone: "Pacific/Apia" }); +assert.sameValue(result, "8/4/2021"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..b2cc851f6eec --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => instance.toLocaleString(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..a2b262dbbd4d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = instance.toZonedDateTime(timeZone); +assert.sameValue(result1.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result2.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = instance.toZonedDateTime(timeZone); +assert.sameValue(result3.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result4.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = instance.toZonedDateTime(timeZone); +assert.sameValue(result5.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result6.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..feaa6626caca --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2, "gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.until({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.until({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDate/prototype/until/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDate/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDate/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..cd34752313d2 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/infinity-throws-rangeerror.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.plaindatetime.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const other = new Temporal.PlainDateTime(2000, 5, 2, 15, "gregory"); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => Temporal.PlainDateTime.compare({ ...base, eraYear: inf }, other), `eraYear property cannot be ${inf}`); + + assert.throws(RangeError, () => Temporal.PlainDateTime.compare(other, { ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainDateTime.compare({ ...base, eraYear: obj1 }, other)); + assert.compareArray(calls1, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainDateTime.compare(other, { ...base, eraYear: obj2 })); + assert.compareArray(calls2, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/compare/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/from/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/from/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..9db21819f809 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/from/infinity-throws-rangeerror.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainDateTime.from({ ...base, eraYear: inf }, { overflow }), `eraYear property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainDateTime.from({ ...base, eraYear: obj }, { overflow })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/from/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/from/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/from/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..1ce3dd5ce8e8 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, "gregory"); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/equals/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/era/branding.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/era/branding.js rename to js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/prop-desc.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/prop-desc.js new file mode 100644 index 000000000000..e72fb35897dd --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.era +description: The "era" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "era"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/era/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/eraYear/branding.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainDateTime/prototype/eraYear/branding.js rename to js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/calendar-returns-infinity.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/calendar-returns-infinity.js new file mode 100644 index 000000000000..8f0d61c8b633 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.erayear +description: Getter throws if the calendar returns ±∞ from its eraYear method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + eraYear() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, pos); +assert.throws(RangeError, () => instance1.eraYear); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainDateTime(2000, 5, 2, 15, 30, 45, 987, 654, 321, neg); +assert.throws(RangeError, () => instance2.eraYear); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/prop-desc.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/prop-desc.js new file mode 100644 index 000000000000..609d2b8ccf74 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.erayear +description: The "eraYear" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "eraYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/eraYear/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f8b89b960f41 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.since +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, "gregory"); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.since({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.since({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/since/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/locales-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/locales-undefined.js new file mode 100644 index 000000000000..b27f24fdcb99 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/locales-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: Omitting the locales argument defaults to the DateTimeFormat default +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const defaultFormatter = new Intl.DateTimeFormat([], Object.create(null)); +const expected = defaultFormatter.format(datetime); + +const actualExplicit = datetime.toLocaleString(undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = datetime.toLocaleString(); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict.js new file mode 100644 index 000000000000..60813030ebcc --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-temporal.plaindatetime.prototype.tolocalestring +description: > + Conflicting properties of dateStyle must be rejected with a TypeError for the options argument +info: | + Using sec-temporal-getdatetimeformatpattern: + GetDateTimeFormatPattern ( dateStyle, timeStyle, matcher, opt, dataLocaleData, hc ) + + 1. If dateStyle is not undefined or timeStyle is not undefined, then + a. For each row in Table 7, except the header row, do + i. Let prop be the name given in the Property column of the row. + ii. Let p be opt.[[]]. + iii. If p is not undefined, then + 1. Throw a TypeError exception. +features: [Temporal] +---*/ + +// Table 14 - Supported fields + example value for each field +const conflictingOptions = [ + [ "weekday", "short" ], + [ "era", "short" ], + [ "year", "numeric" ], + [ "month", "numeric" ], + [ "day", "numeric" ], + [ "hour", "numeric" ], + [ "minute", "numeric" ], + [ "second", "numeric" ], + [ "dayPeriod", "short" ], + [ "fractionalSecondDigits", 3 ], +]; +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +assert.sameValue(typeof datetime.toLocaleString("en", { dateStyle: "short" }), "string"); +assert.sameValue(typeof datetime.toLocaleString("en", { timeStyle: "short" }), "string"); + +for (const [ option, value ] of conflictingOptions) { + assert.throws(TypeError, function() { + datetime.toLocaleString("en", { [option]: value, dateStyle: "short" }); + }, `datetime.toLocaleString("en", { ${option}: "${value}", dateStyle: "short" }) throws TypeError`); + + assert.throws(TypeError, function() { + datetime.toLocaleString("en", { [option]: value, timeStyle: "short" }); + }, `datetime.toLocaleString("en", { ${option}: "${value}", timeStyle: "short" }) throws TypeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-undefined.js new file mode 100644 index 000000000000..ceb36ba83133 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const defaultFormatter = new Intl.DateTimeFormat('en', Object.create(null)); +const expected = defaultFormatter.format(datetime); + +const actualExplicit = datetime.toLocaleString('en', undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = datetime.toLocaleString('en'); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/resolved-time-zone.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/resolved-time-zone.js new file mode 100644 index 000000000000..a095c6f4524d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/resolved-time-zone.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +features: [Temporal] +---*/ + +const datetime1 = new Temporal.PlainDateTime(2021, 8, 4, 0, 30, 45, 123, 456, 789); +const result1 = datetime1.toLocaleString("en", { timeZone: "Pacific/Apia" }); +assert.sameValue(result1, "8/4/2021, 12:30:45 AM"); + +const datetime2 = new Temporal.PlainDateTime(2021, 8, 4, 23, 30, 45, 123, 456, 789); +const result2 = datetime2.toLocaleString("en", { timeZone: "Pacific/Apia" }); +assert.sameValue(result2, "8/4/2021, 11:30:45 PM"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..f2a37362b417 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => instance.toLocaleString(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..f09b22ad18fc --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2); + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = instance.toZonedDateTime(timeZone); +assert.sameValue(result1.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result2.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = instance.toZonedDateTime(timeZone); +assert.sameValue(result3.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result4.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = instance.toZonedDateTime(timeZone); +assert.sameValue(result5.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTime({ timeZone }); +assert.sameValue(result6.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..87fcb10d4cc1 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, "gregory"); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.until({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.until({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/until/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/browser.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..bbcec60f4db1 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindatetime.prototype.withplaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 15, "gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.withPlainDate({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.withPlainDate({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainDateTime/prototype/withPlainDate/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/PlainDateTime/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/browser.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/browser.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..72baf33d126c --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plainmonthday.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainMonthDay(5, 2, "gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/shell.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/equals/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/locales-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/locales-undefined.js new file mode 100644 index 000000000000..c6f4e6defcb1 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/locales-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: Omitting the locales argument defaults to the DateTimeFormat default +features: [Temporal] +---*/ + +const defaultFormatter = new Intl.DateTimeFormat([], Object.create(null)); +const { calendar } = defaultFormatter.resolvedOptions(); +const monthday = new Temporal.PlainMonthDay(5, 2, calendar); +const expected = defaultFormatter.format(monthday); + +const actualExplicit = monthday.toLocaleString(undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = monthday.toLocaleString(); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-undefined.js new file mode 100644 index 000000000000..37ea1bd277bd --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const defaultFormatter = new Intl.DateTimeFormat('en', Object.create(null)); +const { calendar } = defaultFormatter.resolvedOptions(); +const monthday = new Temporal.PlainMonthDay(5, 2, calendar); +const expected = defaultFormatter.format(monthday); + +const actualExplicit = monthday.toLocaleString('en', undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = monthday.toLocaleString('en'); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/resolved-time-zone.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/resolved-time-zone.js new file mode 100644 index 000000000000..2f8be3fb24af --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/resolved-time-zone.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +features: [Temporal] +---*/ + +const monthDay = new Temporal.PlainMonthDay(8, 4, "gregory"); +const result = monthDay.toLocaleString("en", { timeZone: "Pacific/Apia" }); +assert.sameValue(result, "8/4"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..66d3b4fa9b52 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainMonthDay(5, 2); +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => instance.toLocaleString(undefined, { calendar: "iso8601" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/browser.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..2beaf71f8502 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws a RangeError if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plainmonthday.prototype.toplaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainMonthDay(5, 2, "gregory"); + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.toPlainDate({ era: "ad", eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.toPlainDate({ era: "ad", eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainMonthDay/shell.js b/js/src/tests/test262/intl402/Temporal/PlainMonthDay/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/browser.js b/js/src/tests/test262/intl402/Temporal/PlainTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/locales-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/locales-undefined.js new file mode 100644 index 000000000000..263b1f739df0 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/locales-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: Omitting the locales argument defaults to the DateTimeFormat default +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const defaultFormatter = new Intl.DateTimeFormat([], Object.create(null)); +const expected = defaultFormatter.format(time); + +const actualExplicit = time.toLocaleString(undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = time.toLocaleString(); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict.js new file mode 100644 index 000000000000..b4058e7dda0a --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict.js @@ -0,0 +1,40 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-temporal.plaintime.prototype.tolocalestring +description: > + Conflicting properties of dateStyle must be rejected with a TypeError for the options argument +info: | + Using sec-temporal-getdatetimeformatpattern: + GetDateTimeFormatPattern ( dateStyle, timeStyle, matcher, opt, dataLocaleData, hc ) + + 1. If dateStyle is not undefined or timeStyle is not undefined, then + a. For each row in Table 7, except the header row, do + i. Let prop be the name given in the Property column of the row. + ii. Let p be opt.[[]]. + iii. If p is not undefined, then + 1. Throw a TypeError exception. +features: [Temporal] +---*/ + +// Table 14 - Supported fields + example value for each field +const conflictingOptions = [ + [ "hour", "numeric" ], + [ "minute", "numeric" ], + [ "second", "numeric" ], + [ "dayPeriod", "short" ], + [ "fractionalSecondDigits", 3 ], +]; +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.sameValue(typeof time.toLocaleString("en", { timeStyle: "short" }), "string"); + +for (const [ option, value ] of conflictingOptions) { + assert.throws(TypeError, function() { + time.toLocaleString("en", { [option]: value, timeStyle: "short" }); + }, `time.toLocaleString("en", { ${option}: "${value}", timeStyle: "short" }) throws TypeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/options-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/options-undefined.js new file mode 100644 index 000000000000..3a7ff9ece34b --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/options-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const defaultFormatter = new Intl.DateTimeFormat('en', Object.create(null)); +const expected = defaultFormatter.format(time); + +const actualExplicit = time.toLocaleString('en', undefined); +assert.sameValue(actualExplicit, expected, "default options are determined by Intl.DateTimeFormat"); + +const actualImplicit = time.toLocaleString('en'); +assert.sameValue(actualImplicit, expected, "default options are determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/resolved-time-zone.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/resolved-time-zone.js new file mode 100644 index 000000000000..a4bccb213fe2 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/resolved-time-zone.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +features: [Temporal] +---*/ + +const time1 = new Temporal.PlainTime(0, 30, 45, 123, 456, 789); +const result1 = time1.toLocaleString("en", { timeZone: "Pacific/Apia" }); +assert.sameValue(result1, "12:30:45 AM"); + +const time2 = new Temporal.PlainTime(23, 30, 45, 123, 456, 789); +const result2 = time2.toLocaleString("en", { timeZone: "Pacific/Apia" }); +assert.sameValue(result2, "11:30:45 PM"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..aca867f22a11 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => instance.toLocaleString(), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..e5c8f6cf47ea --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.toplaindatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.toPlainDateTime({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.toPlainDateTime({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toPlainDateTime/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js new file mode 100644 index 000000000000..5cbcc44e740e --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.tozoneddatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, eraYear: inf } }), `eraYear property cannot be ${inf} in plainDate`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, eraYear: obj } })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 000000000000..dc780f926b83 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result1.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result2.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result3.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result4.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result5.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone: { timeZone } }); +assert.sameValue(result6.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainTime/shell.js b/js/src/tests/test262/intl402/Temporal/PlainTime/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..449829aff2b6 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/infinity-throws-rangeerror.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const other = new Temporal.PlainYearMonth(2000, 5, "gregory"); +const base = { era: "ad", month: 5, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => Temporal.PlainYearMonth.compare({ ...base, eraYear: inf }, other), `eraYear property cannot be ${inf}`); + + assert.throws(RangeError, () => Temporal.PlainYearMonth.compare(other, { ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainYearMonth.compare({ ...base, eraYear: obj1 }, other)); + assert.compareArray(calls1, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainYearMonth.compare(other, { ...base, eraYear: obj2 })); + assert.compareArray(calls2, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/compare/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/argument-object.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/argument-object.js new file mode 100644 index 000000000000..df7b9a89f362 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/argument-object.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: An object argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const monthDayItem = { calendar: "gregory", era: "ce", eraYear: 2019, month: 11, get day() { throw new Test262Error("should not read the day property") } }; +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from(monthDayItem), + 2019, 11, "M11", "month with day", "ce", 2019); + +const monthCodeDayItem = { calendar: "gregory", era: "ce", eraYear: 2019, monthCode: "M11", get day() { throw new Test262Error("should not read the day property") } }; +TemporalHelpers.assertPlainYearMonth(Temporal.PlainYearMonth.from(monthCodeDayItem), + 2019, 11, "M11", "monthCode with day", "ce", 2019); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..27b9841d2ca9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/infinity-throws-rangeerror.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { era: "ad", month: 5, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainYearMonth.from({ ...base, eraYear: inf }, { overflow }), `eraYear property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.PlainYearMonth.from({ ...base, eraYear: obj }, { overflow })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/from/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..e6d7c849f46b --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5, "gregory"); +const base = { era: "ad", month: 5, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/equals/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/era/branding.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/era/branding.js rename to js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/prop-desc.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/prop-desc.js new file mode 100644 index 000000000000..bd1893d0605f --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.era +description: The "era" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "era"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/era/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/eraYear/branding.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/PlainYearMonth/prototype/eraYear/branding.js rename to js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/calendar-returns-infinity.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/calendar-returns-infinity.js new file mode 100644 index 000000000000..9059a19eaa50 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.erayear +description: Getter throws if the calendar returns ±∞ from its eraYear method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + eraYear() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.PlainYearMonth(2000, 5, pos); +assert.throws(RangeError, () => instance1.eraYear); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.PlainYearMonth(2000, 5, neg); +assert.throws(RangeError, () => instance2.eraYear); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/prop-desc.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/prop-desc.js new file mode 100644 index 000000000000..5b234dbd8ca2 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plainyearmonth.prototype.erayear +description: The "eraYear" property of Temporal.PlainYearMonth.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainYearMonth.prototype, "eraYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/eraYear/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..fdaaee6ba834 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.prototype.since +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5, "gregory"); +const base = { era: "ad", month: 5, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.since({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.since({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/since/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/locales-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/locales-undefined.js new file mode 100644 index 000000000000..648137e364f0 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/locales-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: Omitting the locales argument defaults to the DateTimeFormat default +features: [Temporal] +---*/ + +const defaultFormatter = new Intl.DateTimeFormat([], Object.create(null)); +const { calendar } = defaultFormatter.resolvedOptions(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +const expected = defaultFormatter.format(yearmonth); + +const actualExplicit = yearmonth.toLocaleString(undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = yearmonth.toLocaleString(); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-undefined.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-undefined.js new file mode 100644 index 000000000000..67b78f085a33 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const defaultFormatter = new Intl.DateTimeFormat('en', Object.create(null)); +const { calendar } = defaultFormatter.resolvedOptions(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +const expected = defaultFormatter.format(yearmonth); + +const actualExplicit = yearmonth.toLocaleString('en', undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = yearmonth.toLocaleString('en'); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/resolved-time-zone.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/resolved-time-zone.js new file mode 100644 index 000000000000..3c3ec56a5afd --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/resolved-time-zone.js @@ -0,0 +1,16 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: A time zone in resolvedOptions with a large offset still produces the correct string +locale: [en] +features: [Temporal] +---*/ + +const month = new Temporal.PlainYearMonth(2021, 8, "gregory"); +const result = month.toLocaleString("en", { timeZone: "Pacific/Apia" }); +assert.sameValue(result, "8/2021"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..753bbe8bc950 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5); +Temporal.TimeZone.prototype.getPossibleInstantsFor = function () { + return []; +}; + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + Temporal.TimeZone.prototype.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => instance.toLocaleString(undefined, { calendar: "iso8601" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/browser.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..9d41767cbad0 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.plainyearmonth.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainYearMonth(2000, 5, "gregory"); +const base = { era: "ad", month: 5, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.until({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.until({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/prototype/until/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/PlainYearMonth/shell.js b/js/src/tests/test262/intl402/Temporal/PlainYearMonth/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/basic.js b/js/src/tests/test262/intl402/Temporal/TimeZone/basic.js new file mode 100644 index 000000000000..b4485385a2d6 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/basic.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Basic tests for the Temporal.TimeZone constructor. +features: [Temporal] +---*/ + +const valid = [ + ["Europe/Vienna"], + ["America/New_York"], + ["Africa/CAIRO", "Africa/Cairo"], + ["Asia/Ulan_Bator", "Asia/Ulaanbaatar"], + ["GMT", "UTC"], +]; +for (const [zone, id = zone] of valid) { + const result = new Temporal.TimeZone(zone); + assert.sameValue(typeof result, "object", `object should be created for ${zone}`); + assert.sameValue(result.id, id, `id for ${zone} should be ${id}`); +} + +const invalid = ["+00:01.1", "-01.1"]; +for (const zone of invalid) { + assert.throws(RangeError, () => new Temporal.TimeZone(zone), `should throw for ${zone}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/browser.js b/js/src/tests/test262/intl402/Temporal/TimeZone/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/etc-timezone.js b/js/src/tests/test262/intl402/Temporal/TimeZone/etc-timezone.js new file mode 100644 index 000000000000..405309cc7565 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/etc-timezone.js @@ -0,0 +1,82 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Some Etc/GMT{+/-}{0}N timezones are valid, but not all +features: [Temporal] +---*/ + +// "Etc/GMT-0" through "Etc/GMT-14" are OK + +assert.sameValue( + (new Temporal.TimeZone("Etc/GMT-0")).toString(), + "UTC", // if the offset is -0, we say "UTC" rather than "GMT" + "Etc/GMT-0 is a valid timezone" +); + +[1,2,3,4,5,6,7,8,9,10,11,12,13,14].forEach((n) => { + let tz = "Etc/GMT-" + n; + let instance = new Temporal.TimeZone(tz); + assert.sameValue( + instance.toString(), + tz, + tz + " is a valid timezone" + ); +}); + +let gmtMinus24TZ = "Etc/GMT-24"; +assert.throws( + RangeError, + () => { new Temporal.TimeZone(gmtMinus24TZ); }, + gmtMinus24TZ + " is an invalid timezone" +); + +// "Etc/GMT-0N" is not OK (1 ≤ N ≤ 9) +[1,2,3,4,5,6,7,8,9].forEach((n) => { + let tz = "Etc/GMT-0" + n; + assert.throws( + RangeError, + () => { new Temporal.TimeZone(tz); }, + tz + " is an invalid timezone" + ); +}); + +// "Etc/GMT+0N" is not OK (0 ≤ N ≤ 9) +[0,1,2,3,4,5,6,7,8,9].forEach((n) => { + let tz = "Etc/GMT+0" + n; + assert.throws( + RangeError, + () => { new Temporal.TimeZone(tz); }, + tz + " is an invalid timezone" + ); +}); + +// Etc/GMT+0" through "Etc/GMT+12" are OK + +// zero is handled in its own way (say "UTC" rather than "GMT"): +assert.sameValue( + (new Temporal.TimeZone("Etc/GMT+0")).toString(), + "UTC", // if the offset is +0, we say "UTC" rather than "GMT" + "Etc/GMT+0 is a valid timezone" +); + +[1,2,3,4,5,6,7,8,9,10,11,12].forEach((n) => { + let tz = "Etc/GMT+" + n; + let instance = new Temporal.TimeZone(tz); + assert.sameValue( + instance.toString(), + tz, + tz + " is a valid timezone" + ); +}); + +let gmtPlus24TZ = "Etc/GMT+24"; +assert.throws( + RangeError, + () => { new Temporal.TimeZone(gmtPlus24TZ); }, + gmtPlus24TZ + " is an invalid timezone" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/from/argument-object.js b/js/src/tests/test262/intl402/Temporal/TimeZone/from/argument-object.js new file mode 100644 index 000000000000..ad72c866f056 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/from/argument-object.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: An object is returned unchanged +features: [Temporal] +---*/ + +class CustomTimeZone extends Temporal.TimeZone {} + +const objects = [ + new Temporal.TimeZone("Europe/Madrid"), + new CustomTimeZone("Africa/Accra"), +]; + +const thisValues = [ + Temporal.TimeZone, + CustomTimeZone, + {}, + null, + undefined, + 7, +]; + +for (const thisValue of thisValues) { + for (const object of objects) { + const result = Temporal.TimeZone.from.call(thisValue, object); + assert.sameValue(result, object); + } + + const zdt = new Temporal.ZonedDateTime(0n, "Africa/Cairo"); + const fromZdt = Temporal.TimeZone.from.call(thisValue, zdt); + assert.sameValue(fromZdt, zdt.timeZone); + assert.sameValue(fromZdt.id, "Africa/Cairo"); + + const tz = new Temporal.TimeZone("Africa/Cairo"); + const fromPropertyBagObject = Temporal.TimeZone.from.call(thisValue, { timeZone: tz }); + assert.sameValue(fromPropertyBagObject, tz); + assert.sameValue(fromPropertyBagObject.id, "Africa/Cairo"); + + const fromPropertyBagString = Temporal.TimeZone.from.call(thisValue, { timeZone: "Africa/Cairo" }); + assert(fromPropertyBagString instanceof Temporal.TimeZone); + assert.sameValue(fromPropertyBagString.id, "Africa/Cairo"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/from/argument-valid.js b/js/src/tests/test262/intl402/Temporal/TimeZone/from/argument-valid.js new file mode 100644 index 000000000000..d6f2d5ee03d4 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/from/argument-valid.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Built-in time zones are parsed correctly out of valid strings +features: [Temporal] +---*/ + +const valids = [ + ["Africa/Bissau"], + ["America/Belem"], + ["Europe/Vienna"], + ["America/New_York"], + ["Africa/CAIRO", "Africa/Cairo"], + ["Asia/Ulan_Bator", "Asia/Ulaanbaatar"], + ["GMT", "UTC"], + ["etc/gmt", "UTC"], + ["1994-11-05T08:15:30-05:00[America/New_York]", "America/New_York"], + ["1994-11-05T08:15:30-05[America/New_York]", "America/New_York"], + ["1994-11-05T08:15:30\u221205:00[America/New_York]", "America/New_York"], + ["1994-11-05T08:15:30\u221205[America/New_York]", "America/New_York"], +]; + +for (const [valid, canonical = valid] of valids) { + const result = Temporal.TimeZone.from(valid); + assert.sameValue(Object.getPrototypeOf(result), Temporal.TimeZone.prototype); + assert.sameValue(result.id, canonical); + assert.sameValue(result.toString(), canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/from/browser.js b/js/src/tests/test262/intl402/Temporal/TimeZone/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/from/shell.js b/js/src/tests/test262/intl402/Temporal/TimeZone/from/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/from/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/TimeZone/from/timezone-string-datetime.js new file mode 100644 index 000000000000..422e5fa85fe8 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/from/timezone-string-datetime.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.from +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result1.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result2.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result3.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result4.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = Temporal.TimeZone.from(timeZone); +assert.sameValue(result5.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = Temporal.TimeZone.from({ timeZone }); +assert.sameValue(result6.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/browser.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..cfa06cc72068 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.timezone.prototype.getinstantfor +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.getInstantFor({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.getInstantFor({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/shell.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getInstantFor/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/browser.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js new file mode 100644 index 000000000000..6e0c65c025bc --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor +description: Conversion of ISO date-time strings to Temporal.Instant instances +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("America/Vancouver"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.getOffsetNanosecondsFor(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[America/Vancouver]"; +assert.throws(RangeError, () => instance.getOffsetNanosecondsFor(str), "date-time + IANA annotation is not an instant"); + +// The following are all valid strings so should not throw: + +const valids = [ + "1970-01-01T00:00Z", + "1970-01-01T00:00+01:00", + "1970-01-01T00:00Z[America/Vancouver]", + "1970-01-01T00:00+01:00[America/Vancouver]", +]; +for (const str of valids) { + const result = instance.getOffsetNanosecondsFor(str); + assert.sameValue(result, -28800e9); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/browser.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js new file mode 100644 index 000000000000..32ed18c24aaa --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getoffsetstringfor +description: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("America/Vancouver"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.getOffsetStringFor(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[America/Vancouver]"; +assert.throws(RangeError, () => instance.getOffsetStringFor(str), "date-time + IANA annotation is not an instant"); + +// The following are all valid strings so should not throw: + +const valids = [ + "1970-01-01T00:00Z", + "1970-01-01T00:00+01:00", + "1970-01-01T00:00Z[America/Vancouver]", + "1970-01-01T00:00+01:00[America/Vancouver]", +]; +for (const str of valids) { + const result = instance.getOffsetStringFor(str); + assert.sameValue(result, "-08:00"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js new file mode 100644 index 000000000000..68d31838ba83 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone.prototype.getplaindatetimefor +description: Conversion of ISO date-time strings to Temporal.Instant instances +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("America/Vancouver"); + +let str = "1970-01-01T00:00"; +assert.throws(RangeError, () => instance.getPlainDateTimeFor(str), "bare date-time string is not an instant"); +str = "1970-01-01T00:00[America/Vancouver]"; +assert.throws(RangeError, () => instance.getPlainDateTimeFor(str), "date-time + IANA annotation is not an instant"); + +str = "1970-01-01T00:00Z"; +const result1 = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result1, 1969, 12, "M12", 31, 16, 0, 0, 0, 0, 0, "date-time + Z preserves exact time"); + +str = "1970-01-01T00:00+01:00"; +const result2 = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result2, 1969, 12, "M12", 31, 15, 0, 0, 0, 0, 0, "date-time + offset preserves exact time with offset"); + +str = "1970-01-01T00:00Z[America/Vancouver]"; +const result3 = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result3, 1969, 12, "M12", 31, 16, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation ignores the IANA annotation"); + +str = "1970-01-01T00:00+01:00[America/Vancouver]"; +const result4 = instance.getPlainDateTimeFor(str); +TemporalHelpers.assertPlainDateTime(result4, 1969, 12, "M12", 31, 15, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation ignores the IANA annotation"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/browser.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f69d13dbc37d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.timezone.prototype.getpossibleinstantsfor +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.TimeZone("UTC"); +const base = { era: "ad", month: 5, day: 2, hour: 15, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.getPossibleInstantsFor({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.getPossibleInstantsFor({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/TimeZone/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/TimeZone/shell.js b/js/src/tests/test262/intl402/Temporal/TimeZone/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..a1565a6ac0f2 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/infinity-throws-rangeerror.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.compare +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const other = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "gregory"); +const base = { era: "ad", month: 5, day: 2, hour: 15, timeZone: "UTC", calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare({ ...base, eraYear: inf }, other), `eraYear property cannot be ${inf}`); + + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(other, { ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare({ ...base, eraYear: obj1 }, other)); + assert.compareArray(calls1, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.ZonedDateTime.compare(other, { ...base, eraYear: obj2 })); + assert.compareArray(calls2, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/compare/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..d8fd2d6134e2 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/infinity-throws-rangeerror.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { era: "ad", month: 5, day: 2, hour: 15, timeZone: "UTC", calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.ZonedDateTime.from({ ...base, eraYear: inf }, { overflow }), `eraYear property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => Temporal.ZonedDateTime.from({ ...base, eraYear: obj }, { overflow })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/timezone-string-datetime.js new file mode 100644 index 000000000000..3e7757c02319 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/from/timezone-string-datetime.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +const result1 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result1.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone"); +const result2 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result2.timeZone.id, "America/Vancouver", "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +const result3 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result3.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone"); +const result4 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result4.timeZone.id, "America/Vancouver", "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +const result5 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +assert.sameValue(result5.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone"); +const result6 = Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone: { timeZone } }); +assert.sameValue(result6.timeZone.id, "America/Vancouver", "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..cb117f6e52b5 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.equals +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "gregory"); +const base = { era: "ad", month: 5, day: 2, hour: 15, timeZone: "UTC", calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.equals({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/timezone-string-datetime.js new file mode 100644 index 000000000000..51a14fdea07e --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/equals/timezone-string-datetime.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const expectedTimeZone = "America/Vancouver"; +const instance = new Temporal.ZonedDateTime(0n, expectedTimeZone); +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +assert(instance.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone }), "date-time + IANA annotation is the IANA time zone"); +assert(instance.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone: { timeZone } }), "date-time + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +assert(instance.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone }), "date-time + Z + IANA annotation is the IANA time zone"); +assert(instance.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone: { timeZone } }), "date-time + Z + IANA annotation is the IANA time zone (string in property bag)"); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +assert(instance.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone }), "date-time + offset + IANA annotation is the IANA time zone"); +assert(instance.equals({ year: 1969, month: 12, day: 31, hour: 16, timeZone: { timeZone } }), "date-time + offset + IANA annotation is the IANA time zone (string in property bag)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/era/branding.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/era/branding.js rename to js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/prop-desc.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/prop-desc.js new file mode 100644 index 000000000000..af51869f2dfd --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.era +description: The "era" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "era"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..c70670bca463 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.era +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.era); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..979f76f2726d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.era +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.era, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..8df12c564703 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.era +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.era); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..bbe42f6d314e --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/era/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.era +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.era); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/eraYear/branding.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/branding.js similarity index 100% rename from js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/eraYear/branding.js rename to js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/branding.js diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/calendar-returns-infinity.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/calendar-returns-infinity.js new file mode 100644 index 000000000000..888d29d1be6c --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/calendar-returns-infinity.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.erayear +description: Getter throws if the calendar returns ±∞ from its eraYear method +features: [Temporal] +---*/ + +class InfinityCalendar extends Temporal.Calendar { + constructor(positive) { + super("iso8601"); + this.positive = positive; + } + + eraYear() { + return this.positive ? Infinity : -Infinity; + } +} + +const pos = new InfinityCalendar(true); +const instance1 = new Temporal.ZonedDateTime(0n, "UTC", pos); +assert.throws(RangeError, () => instance1.eraYear); + +const neg = new InfinityCalendar(false); +const instance2 = new Temporal.ZonedDateTime(0n, "UTC", neg); +assert.throws(RangeError, () => instance2.eraYear); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/prop-desc.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/prop-desc.js new file mode 100644 index 000000000000..53ddcc1be639 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.erayear +description: The "eraYear" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "eraYear"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 000000000000..47db35da8539 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.erayear +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.eraYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 000000000000..cc19087ae57e --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.erayear +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.eraYear, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 000000000000..c9b041d1765d --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.erayear +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.eraYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 000000000000..7020148119e3 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/eraYear/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.erayear +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.eraYear); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..c2d028b83d22 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.since +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "gregory"); +const base = { era: "ad", month: 5, day: 2, hour: 15, timeZone: "UTC", calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.since({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.since({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/timezone-string-datetime.js new file mode 100644 index 000000000000..1c87ef5ee68b --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/since/timezone-string-datetime.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const expectedTimeZone = "America/Vancouver"; +const instance = new Temporal.ZonedDateTime(0n, expectedTimeZone); +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +instance.since({ year: 2020, month: 5, day: 2, timeZone }); +instance.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +instance.since({ year: 2020, month: 5, day: 2, timeZone }); +instance.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +instance.since({ year: 2020, month: 5, day: 2, timeZone }); +instance.since({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/locales-undefined.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/locales-undefined.js new file mode 100644 index 000000000000..27f0e248c9e9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/locales-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: Omitting the locales argument defaults to the DateTimeFormat default +features: [BigInt, Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC"); +const defaultFormatter = new Intl.DateTimeFormat([], Object.create(null)); +const expected = defaultFormatter.format(datetime); + +const actualExplicit = datetime.toLocaleString(undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = datetime.toLocaleString(); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict.js new file mode 100644 index 000000000000..3eda971d0ded --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-temporal.zoneddatetime.prototype.tolocalestring +description: > + Conflicting properties of dateStyle must be rejected with a TypeError for the options argument +info: | + Using sec-temporal-getdatetimeformatpattern: + GetDateTimeFormatPattern ( dateStyle, timeStyle, matcher, opt, dataLocaleData, hc ) + + 1. If dateStyle is not undefined or timeStyle is not undefined, then + a. For each row in Table 7, except the header row, do + i. Let prop be the name given in the Property column of the row. + ii. Let p be opt.[[]]. + iii. If p is not undefined, then + 1. Throw a TypeError exception. +features: [BigInt, Temporal] +---*/ + +// Table 14 - Supported fields + example value for each field +const conflictingOptions = [ + [ "weekday", "short" ], + [ "era", "short" ], + [ "year", "numeric" ], + [ "month", "numeric" ], + [ "day", "numeric" ], + [ "hour", "numeric" ], + [ "minute", "numeric" ], + [ "second", "numeric" ], + [ "dayPeriod", "short" ], + [ "fractionalSecondDigits", 3 ], + [ "timeZoneName", "short" ], +]; +const datetime = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC"); + +assert.sameValue(typeof datetime.toLocaleString("en", { dateStyle: "short" }), "string"); +assert.sameValue(typeof datetime.toLocaleString("en", { timeStyle: "short" }), "string"); + +for (const [ option, value ] of conflictingOptions) { + assert.throws(TypeError, function() { + datetime.toLocaleString("en", { [option]: value, dateStyle: "short" }); + }, `datetime.toLocaleString("en", { ${option}: "${value}", dateStyle: "short" }) throws TypeError`); + + assert.throws(TypeError, function() { + datetime.toLocaleString("en", { [option]: value, timeStyle: "short" }); + }, `datetime.toLocaleString("en", { ${option}: "${value}", timeStyle: "short" }) throws TypeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-undefined.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-undefined.js new file mode 100644 index 000000000000..557205cfc40b --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-undefined.js @@ -0,0 +1,21 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: Verify that undefined options are handled correctly. +features: [BigInt, Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC"); +const defaultFormatter = new Intl.DateTimeFormat('en', Object.create(null)); +const expected = defaultFormatter.format(datetime); + +const actualExplicit = datetime.toLocaleString('en', undefined); +assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +const actualImplicit = datetime.toLocaleString('en'); +assert.sameValue(actualImplicit, expected, "default locale is determined by Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..06379383ee84 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "gregory"); +const base = { era: "ad", month: 5, day: 2, hour: 15, timeZone: "UTC", calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.until({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.until({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/timezone-string-datetime.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/timezone-string-datetime.js new file mode 100644 index 000000000000..47ed816e28e4 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/until/timezone-string-datetime.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: Conversion of ISO date-time strings to Temporal.TimeZone instances (with Intl time zones) +features: [Temporal] +---*/ + +const expectedTimeZone = "America/Vancouver"; +const instance = new Temporal.ZonedDateTime(0n, expectedTimeZone); +let timeZone = "2021-08-19T17:30[America/Vancouver]"; +instance.until({ year: 2020, month: 5, day: 2, timeZone }); +instance.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +timeZone = "2021-08-19T17:30Z[America/Vancouver]"; +instance.until({ year: 2020, month: 5, day: 2, timeZone }); +instance.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +timeZone = "2021-08-19T17:30-07:00[America/Vancouver]"; +instance.until({ year: 2020, month: 5, day: 2, timeZone }); +instance.until({ year: 2020, month: 5, day: 2, timeZone: { timeZone } }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/browser.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js new file mode 100644 index 000000000000..f0e58e596165 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/infinity-throws-rangeerror.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Temporal is not supported +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if eraYear in the property bag is Infinity or -Infinity +esid: sec-temporal.zoneddatetime.prototype.withplaindate +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.withPlainDate({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.withPlainDate({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/shell.js new file mode 100644 index 000000000000..1d70b7579ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/prototype/withPlainDate/shell.js @@ -0,0 +1,1498 @@ +// GENERATED, DO NOT EDIT +// file: temporalHelpers.js +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + This defines helper objects and functions for testing Temporal. +defines: [TemporalHelpers] +features: [Symbol.species, Symbol.iterator, Temporal] +---*/ + +var TemporalHelpers = { + /* + * assertDuration(duration, years, ..., nanoseconds[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * an expected value. + */ + assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") { + assert(duration instanceof Temporal.Duration, `${description} instanceof`); + assert.sameValue(duration.years, years, `${description} years result`); + assert.sameValue(duration.months, months, `${description} months result`); + assert.sameValue(duration.weeks, weeks, `${description} weeks result`); + assert.sameValue(duration.days, days, `${description} days result`); + assert.sameValue(duration.hours, hours, `${description} hours result`); + assert.sameValue(duration.minutes, minutes, `${description} minutes result`); + assert.sameValue(duration.seconds, seconds, `${description} seconds result`); + assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`); + assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`); + assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`); + }, + + /* + * assertDurationsEqual(actual, expected[, description]): + * + * Shorthand for asserting that each field of a Temporal.Duration is equal to + * the corresponding field in another Temporal.Duration. + */ + assertDurationsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`); + TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description); + }, + + /* + * assertInstantsEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.Instants are of the correct type + * and equal according to their equals() methods. + */ + assertInstantsEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`); + assert(actual instanceof Temporal.Instant, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDate is equal to + * an expected value. (Except the `calendar` property, since callers may want + * to assert either object equality with an object they put in there, or the + * result of date.calendar.toString().) + */ + assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) { + assert(date instanceof Temporal.PlainDate, `${description} instanceof`); + assert.sameValue(date.era, era, `${description} era result`); + assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(date.year, year, `${description} year result`); + assert.sameValue(date.month, month, `${description} month result`); + assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(date.day, day, `${description} day result`); + }, + + /* + * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainDateTime is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of datetime.calendar.toString().) + */ + assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) { + assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert.sameValue(datetime.era, era, `${description} era result`); + assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(datetime.year, year, `${description} year result`); + assert.sameValue(datetime.month, month, `${description} month result`); + assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(datetime.day, day, `${description} day result`); + assert.sameValue(datetime.hour, hour, `${description} hour result`); + assert.sameValue(datetime.minute, minute, `${description} minute result`); + assert.sameValue(datetime.second, second, `${description} second result`); + assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their calendars are the same value. + */ + assertPlainDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`); + assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainMonthDay is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of monthDay.calendar.toString().) + */ + assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) { + assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`); + assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`); + assert.sameValue(monthDay.day, day, `${description} day result`); + assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`); + }, + + /* + * assertPlainTime(time, hour, ..., nanosecond[, description]): + * + * Shorthand for asserting that each field of a Temporal.PlainTime is equal to + * an expected value. + */ + assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") { + assert(time instanceof Temporal.PlainTime, `${description} instanceof`); + assert.sameValue(time.hour, hour, `${description} hour result`); + assert.sameValue(time.minute, minute, `${description} minute result`); + assert.sameValue(time.second, second, `${description} second result`); + assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`); + assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`); + assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`); + }, + + /* + * assertPlainTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.PlainTimes are of the correct + * type and equal according to their equals() methods. + */ + assertPlainTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`); + assert(actual instanceof Temporal.PlainTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + }, + + /* + * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear]]): + * + * Shorthand for asserting that each field of a Temporal.PlainYearMonth is + * equal to an expected value. (Except the `calendar` property, since callers + * may want to assert either object equality with an object they put in there, + * or the result of yearMonth.calendar.toString().) + */ + assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined) { + assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`); + assert.sameValue(yearMonth.era, era, `${description} era result`); + assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`); + assert.sameValue(yearMonth.year, year, `${description} year result`); + assert.sameValue(yearMonth.month, month, `${description} month result`); + assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`); + }, + + /* + * assertZonedDateTimesEqual(actual, expected[, description]): + * + * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct + * type, equal according to their equals() methods, and additionally that + * their time zones and calendars are the same value. + */ + assertZonedDateTimesEqual(actual, expected, description = "") { + assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`); + assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`); + assert(actual.equals(expected), `${description} equals method`); + assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`); + assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`); + }, + + /* + * assertUnreachable(description): + * + * Helper for asserting that code is not executed. This is useful for + * assertions that methods of user calendars and time zones are not called. + */ + assertUnreachable(description) { + let message = "This code should not be executed"; + if (description) { + message = `${message}: ${description}`; + } + throw new Test262Error(message); + }, + + /* + * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls): + * + * When an options object with a largestUnit property is synthesized inside + * Temporal and passed to user code such as calendar.dateUntil(), the value of + * the largestUnit property should be in the singular form, even if the input + * was given in the plural form. + * (This doesn't apply when the options object is passed through verbatim.) + * + * func(calendar, largestUnit, index) is the operation under test. It's called + * with an instance of a calendar that keeps track of which largestUnit is + * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and + * the key's numerical index in case the function needs to generate test data + * based on the index. At the end, the actual values passed to dateUntil() are + * compared with the array values of expectedLargestUnitCalls. + */ + checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) { + const actual = []; + + class DateUntilOptionsCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil(earlier, later, options) { + actual.push(options.largestUnit); + return super.dateUntil(earlier, later, options); + } + + toString() { + return "date-until-options"; + } + } + + const calendar = new DateUntilOptionsCalendar(); + Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => { + func(calendar, largestUnit, index); + assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`); + actual.splice(0, actual.length); // empty it for the next check + }); + }, + + /* + * checkFractionalSecondDigitsOptionWrongType(temporalObject): + * + * Checks the string-or-number type handling of the fractionalSecondDigits + * option to the various types' toString() methods. temporalObject is an + * instance of the Temporal type under test. + */ + checkFractionalSecondDigitsOptionWrongType(temporalObject) { + // null is not a number, and converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); + // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); + // Symbols are not numbers and cannot convert to strings + assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); + // BigInts are not numbers and convert to strings which are invalid + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); + + // Objects are not numbers and prefer their toString() methods when converting to a string + assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); + + const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); + const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); + const result = temporalObject.toString({ fractionalSecondDigits: observer }); + assert.sameValue(result, toStringExpected, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkPlainDateTimeConversionFastPath(func): + * + * ToTemporalDate and ToTemporalTime should both, if given a + * Temporal.PlainDateTime instance, convert to the desired type by reading the + * PlainDateTime's internal slots, rather than calling any getters. + * + * func(datetime, calendar) is the actual operation to test, that must + * internally call the abstract operation ToTemporalDate or ToTemporalTime. + * It is passed a Temporal.PlainDateTime instance, as well as the instance's + * calendar object (so that it doesn't have to call the calendar getter itself + * if it wants to make any assertions about the calendar.) + */ + checkPlainDateTimeConversionFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype); + ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(datetime, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); + }); + Object.defineProperty(datetime, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(datetime, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * Check that an options bag that accepts units written in the singular form, + * also accepts the same units written in the plural form. + * func(unit) should call the method with the appropriate options bag + * containing unit as a value. This will be called twice for each element of + * validSingularUnits, once with singular and once with plural, and the + * results of each pair should be the same (whether a Temporal object or a + * primitive value.) + */ + checkPluralUnitsAccepted(func, validSingularUnits) { + const plurals = { + year: 'years', + month: 'months', + week: 'weeks', + day: 'days', + hour: 'hours', + minute: 'minutes', + second: 'seconds', + millisecond: 'milliseconds', + microsecond: 'microseconds', + nanosecond: 'nanoseconds', + }; + + validSingularUnits.forEach((unit) => { + const singularValue = func(unit); + const pluralValue = func(plurals[unit]); + const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`; + if (singularValue instanceof Temporal.Duration) { + TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.Instant) { + TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainDateTime) { + TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.PlainTime) { + TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc); + } else if (singularValue instanceof Temporal.ZonedDateTime) { + TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc); + } else { + assert.sameValue(pluralValue, singularValue); + } + }); + }, + + /* + * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc): + * + * Checks the type handling of the roundingIncrement option. + * checkFunc(roundingIncrement) is a function which takes the value of + * roundingIncrement to test, and calls the method under test with it, + * returning the result. assertTrueResultFunc(result, description) should + * assert that result is the expected result with roundingIncrement: true, and + * assertObjectResultFunc(result, description) should assert that result is + * the expected result with roundingIncrement being an object with a valueOf() + * method. + */ + checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) { + // null converts to 0, which is out of range + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to either 0 or 1, and 1 is allowed + const trueResult = checkFunc(true); + assertTrueResultFunc(trueResult, "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols and BigInts cannot convert to numbers + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + assert.throws(TypeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their valueOf() methods when converting to a number + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + "get roundingIncrement.valueOf", + "call roundingIncrement.valueOf", + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement"); + const objectResult = checkFunc(observer); + assertObjectResultFunc(objectResult, "object with valueOf"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc): + * + * Checks the type handling of a string option, of which there are several in + * Temporal. + * propertyName is the name of the option, and value is the value that + * assertFunc should expect it to have. + * checkFunc(value) is a function which takes the value of the option to test, + * and calls the method under test with it, returning the result. + * assertFunc(result, description) should assert that result is the expected + * result with the option value being an object with a toString() method + * which returns the given value. + */ + checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) { + // null converts to the string "null", which is an invalid string value + assert.throws(RangeError, () => checkFunc(null), "null"); + // Booleans convert to the strings "true" or "false", which are invalid + assert.throws(RangeError, () => checkFunc(true), "true"); + assert.throws(RangeError, () => checkFunc(false), "false"); + // Symbols cannot convert to strings + assert.throws(TypeError, () => checkFunc(Symbol()), "symbol"); + // Numbers convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2), "number"); + // BigInts convert to strings which are invalid + assert.throws(RangeError, () => checkFunc(2n), "bigint"); + + // Objects prefer their toString() methods when converting to a string + assert.throws(RangeError, () => checkFunc({}), "plain object"); + + const expected = [ + `get ${propertyName}.toString`, + `call ${propertyName}.toString`, + ]; + const actual = []; + const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName); + const result = checkFunc(observer); + assertFunc(result, "object with toString"); + assert.compareArray(actual, expected, "order of operations"); + }, + + /* + * checkSubclassingIgnored(construct, constructArgs, method, methodArgs, + * resultAssertions): + * + * Methods of Temporal classes that return a new instance of the same class, + * must not take the constructor of a subclass into account, nor the @@species + * property. This helper runs tests to ensure this. + * + * construct(...constructArgs) must yield a valid instance of the Temporal + * class. instance[method](...methodArgs) is the method call under test, which + * must also yield a valid instance of the same Temporal class, not a + * subclass. See below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnored(...args) { + this.checkSubclassConstructorNotObject(...args); + this.checkSubclassConstructorUndefined(...args); + this.checkSubclassConstructorThrows(...args); + this.checkSubclassConstructorNotCalled(...args); + this.checkSubclassSpeciesInvalidResult(...args); + this.checkSubclassSpeciesNotAConstructor(...args); + this.checkSubclassSpeciesNull(...args); + this.checkSubclassSpeciesUndefined(...args); + this.checkSubclassSpeciesThrows(...args); + }, + + /* + * Checks that replacing the 'constructor' property of the instance with + * various primitive values does not affect the returned new instance. + */ + checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = value; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + }, + + /* + * Checks that replacing the 'constructor' property of the subclass with + * undefined does not affect the returned new instance. + */ + checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = undefined; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that making the 'constructor' property of the instance throw when + * called does not affect the returned new instance. + */ + checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + const instance = new construct(...constructArgs); + Object.defineProperty(instance, "constructor", { + get() { + throw new CustomError(); + } + }); + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Checks that when subclassing, the subclass constructor is not called by + * the method under test. + */ + checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's a + * constructor that returns a non-object value. + */ + checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: function() { + return value; + }, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's not a + * constructor. + */ + checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) { + function check(value, description) { + const instance = new construct(...constructArgs); + instance.constructor = { + [Symbol.species]: value, + }; + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description); + resultAssertions(result); + } + + check(true, "true"); + check("test", "string"); + check(Symbol(), "Symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "plain object"); + }, + + /* + * Check that the constructor's @@species property is ignored when it's null. + */ + checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: null, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it's + * undefined. + */ + checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) { + let called = 0; + + class MySubclass extends construct { + constructor() { + ++called; + super(...constructArgs); + } + } + + const instance = new MySubclass(); + assert.sameValue(called, 1); + + MySubclass.prototype.constructor = { + [Symbol.species]: undefined, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(called, 1); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that the constructor's @@species property is ignored when it throws, + * i.e. it is not called at all. + */ + checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) { + function CustomError() {} + + const instance = new construct(...constructArgs); + instance.constructor = { + get [Symbol.species]() { + throw new CustomError(); + }, + }; + + const result = instance[method](...methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + }, + + /* + * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions): + * + * Static methods of Temporal classes that return a new instance of the class, + * must not use the this-value as a constructor. This helper runs tests to + * ensure this. + * + * construct[method](...methodArgs) is the static method call under test, and + * must yield a valid instance of the Temporal class, not a subclass. See + * below for the individual tests that this runs. + * resultAssertions() is a function that performs additional assertions on the + * instance returned by the method under test. + */ + checkSubclassingIgnoredStatic(...args) { + this.checkStaticInvalidReceiver(...args); + this.checkStaticReceiverNotCalled(...args); + this.checkThisValueNotCalled(...args); + }, + + /* + * Check that calling the static method with a receiver that's not callable, + * still calls the intrinsic constructor. + */ + checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const result = construct[method].apply(value, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that calling the static method with a receiver that returns a value + * that's not callable, still calls the intrinsic constructor. + */ + checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) { + function check(value, description) { + const receiver = function () { + return value; + }; + const result = construct[method].apply(receiver, methodArgs); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + } + + check(undefined, "undefined"); + check(null, "null"); + check(true, "true"); + check("test", "string"); + check(Symbol(), "symbol"); + check(7, "number"); + check(7n, "bigint"); + check({}, "Non-callable object"); + }, + + /* + * Check that the receiver isn't called. + */ + checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) { + let called = false; + + class MySubclass extends construct { + constructor(...args) { + called = true; + super(...args); + } + } + + const result = MySubclass[method](...methodArgs); + assert.sameValue(called, false); + assert.sameValue(Object.getPrototypeOf(result), construct.prototype); + resultAssertions(result); + }, + + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + + /* + * Check that any calendar-carrying Temporal object has its [[Calendar]] + * internal slot read by ToTemporalCalendar, and does not fetch the calendar + * by calling getters. + * The custom calendar object is passed in to func() so that it can do its + * own additional assertions involving the calendar if necessary. (Sometimes + * there is nothing to assert as the calendar isn't stored anywhere that can + * be asserted about.) + */ + checkToTemporalCalendarFastPath(func) { + class CalendarFastPathCheck extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + toString() { + return "fast-path-check"; + } + } + const calendar = new CalendarFastPathCheck(); + + const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar); + const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); + const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar); + const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); + const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + + [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => { + const actual = []; + const expected = []; + + Object.defineProperty(temporalObject, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(temporalObject, calendar); + assert.compareArray(actual, expected, "calendar getter not called"); + }); + }, + + checkToTemporalInstantFastPath(func) { + const actual = []; + const expected = []; + + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); + Object.defineProperty(datetime, 'toString', { + get() { + actual.push("get toString"); + return function (options) { + actual.push("call toString"); + return Temporal.ZonedDateTime.prototype.toString.call(this, options); + }; + }, + }); + + func(datetime); + assert.compareArray(actual, expected, "toString not called"); + }, + + checkToTemporalPlainDateTimeFastPath(func) { + const actual = []; + const expected = []; + + const calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2, calendar); + const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype); + ["year", "month", "monthCode", "day"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return TemporalHelpers.toPrimitiveObserver(actual, value, property); + }, + }); + }); + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => { + Object.defineProperty(date, property, { + get() { + actual.push(`get ${property}`); + return undefined; + }, + }); + }); + Object.defineProperty(date, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + func(date, calendar); + assert.compareArray(actual, expected, "property getters not called"); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with the + * options parameter having the value undefined. + */ + calendarDateAddUndefinedOptions() { + class CalendarDateAddUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + } + + toString() { + return "dateadd-undef-options"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert.sameValue(options, undefined, "dateAdd shouldn't be called with options"); + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddUndefinedOptions(); + }, + + /* + * A custom calendar that asserts its dateAdd() method is called with a + * PlainDate instance. Optionally, it also asserts that the PlainDate instance + * is the specific object `this.specificPlainDate`, if it is set by the + * calling code. + */ + calendarDateAddPlainDateInstance() { + class CalendarDateAddPlainDateInstance extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateAddCallCount = 0; + this.specificPlainDate = undefined; + } + + toString() { + return "dateadd-plain-date-instance"; + } + + dateAdd(date, duration, options) { + this.dateAddCallCount++; + assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance"); + if (this.dateAddCallCount === 1 && this.specificPlainDate) { + assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`); + } + return super.dateAdd(date, duration, options); + } + } + return new CalendarDateAddPlainDateInstance(); + }, + + /* + * A custom calendar that returns @returnValue from its dateUntil() method, + * recording the call in @calls. + */ + calendarDateUntilObservable(calls, returnValue) { + class CalendarDateUntilObservable extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateUntil() { + calls.push("call dateUntil"); + return returnValue; + } + } + + return new CalendarDateUntilObservable(); + }, + + /* + * A custom calendar that returns an iterable instead of an array from its + * fields() method, otherwise identical to the ISO calendar. + */ + calendarFieldsIterable() { + class CalendarFieldsIterable extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.fieldsCallCount = 0; + this.fieldsCalledWith = []; + this.iteratorExhausted = []; + } + + toString() { + return "fields-iterable"; + } + + fields(fieldNames) { + this.fieldsCallCount++; + this.fieldsCalledWith.push(fieldNames.slice()); + this.iteratorExhausted.push(false); + return { + callIndex: this.fieldsCallCount - 1, + calendar: this, + *[Symbol.iterator]() { + yield* this.calendar.fieldsCalledWith[this.callIndex]; + this.calendar.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + return new CalendarFieldsIterable(); + }, + + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + + /* + * A custom calendar that modifies the fields object passed in to + * dateFromFields, sabotaging its time properties. + */ + calendarMakeInfinityTime() { + class CalendarMakeInfinityTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + fields.hour = Infinity; + fields.minute = Infinity; + fields.second = Infinity; + fields.millisecond = Infinity; + fields.microsecond = Infinity; + fields.nanosecond = Infinity; + return retval; + } + } + return new CalendarMakeInfinityTime(); + }, + + /* + * A custom calendar that defines getters on the fields object passed into + * dateFromFields that throw, sabotaging its time properties. + */ + calendarMakeInvalidGettersTime() { + class CalendarMakeInvalidGettersTime extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + + dateFromFields(fields, options) { + const retval = super.dateFromFields(fields, options); + const throwingDescriptor = { + get() { + throw new Test262Error("reading a sabotaged time field"); + }, + }; + Object.defineProperties(fields, { + hour: throwingDescriptor, + minute: throwingDescriptor, + second: throwingDescriptor, + millisecond: throwingDescriptor, + microsecond: throwingDescriptor, + nanosecond: throwingDescriptor, + }); + return retval; + } + } + return new CalendarMakeInvalidGettersTime(); + }, + + /* + * A custom calendar whose mergeFields() method returns a proxy object with + * all of its Get and HasProperty operations observable, as well as adding a + * "shouldNotBeCopied": true property. + */ + calendarMergeFieldsGetters() { + class CalendarMergeFieldsGetters extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.mergeFieldsReturnOperations = []; + } + + toString() { + return "merge-fields-getters"; + } + + dateFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied"); + return super.monthDayFromFields(fields, options); + } + + mergeFields(fields, additionalFields) { + const retval = super.mergeFields(fields, additionalFields); + retval._calendar = this; + retval.shouldNotBeCopied = true; + return new Proxy(retval, { + get(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`get ${key}`); + const result = target[key]; + if (result === undefined) { + return undefined; + } + return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key); + }, + has(target, key) { + target._calendar.mergeFieldsReturnOperations.push(`has ${key}`); + return key in target; + }, + }); + } + } + return new CalendarMergeFieldsGetters(); + }, + + /* + * A custom calendar whose mergeFields() method returns a primitive value, + * given by @primitive, and which records the number of calls made to its + * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods. + */ + calendarMergeFieldsReturnsPrimitive(primitive) { + class CalendarMergeFieldsPrimitive extends Temporal.Calendar { + constructor(mergeFieldsReturnValue) { + super("iso8601"); + this._mergeFieldsReturnValue = mergeFieldsReturnValue; + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "merge-fields-primitive"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + return super.monthDayFromFields(fields, options); + } + + mergeFields() { + return this._mergeFieldsReturnValue; + } + } + return new CalendarMergeFieldsPrimitive(primitive); + }, + + /* + * observeProperty(calls, object, propertyName, value): + * + * Defines an own property @object.@propertyName with value @value, that + * will log any calls to its accessors to the array @calls. + */ + observeProperty(calls, object, propertyName, value) { + let displayName = propertyName; + if (typeof propertyName === 'symbol') { + if (Symbol.keyFor(propertyName) !== undefined) { + displayName = `[Symbol.for('${Symbol.keyFor(propertyName)}')]`; + } else if (propertyName.description.startsWith('Symbol.')) { + displayName = `[${propertyName.description}]`; + } else { + displayName = `[Symbol('${propertyName.description}')]` + } + } + Object.defineProperty(object, propertyName, { + get() { + calls.push(`get ${displayName}`); + return value; + }, + set(v) { + calls.push(`set ${displayName}`); + } + }); + }, + + /* + * A custom calendar that does not allow any of its methods to be called, for + * the purpose of asserting that a particular operation does not call into + * user code. + */ + calendarThrowEverything() { + class CalendarThrowEverything extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + TemporalHelpers.assertUnreachable("toString should not be called"); + } + dateFromFields() { + TemporalHelpers.assertUnreachable("dateFromFields should not be called"); + } + yearMonthFromFields() { + TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called"); + } + monthDayFromFields() { + TemporalHelpers.assertUnreachable("monthDayFromFields should not be called"); + } + dateAdd() { + TemporalHelpers.assertUnreachable("dateAdd should not be called"); + } + dateUntil() { + TemporalHelpers.assertUnreachable("dateUntil should not be called"); + } + era() { + TemporalHelpers.assertUnreachable("era should not be called"); + } + eraYear() { + TemporalHelpers.assertUnreachable("eraYear should not be called"); + } + year() { + TemporalHelpers.assertUnreachable("year should not be called"); + } + month() { + TemporalHelpers.assertUnreachable("month should not be called"); + } + monthCode() { + TemporalHelpers.assertUnreachable("monthCode should not be called"); + } + day() { + TemporalHelpers.assertUnreachable("day should not be called"); + } + fields() { + TemporalHelpers.assertUnreachable("fields should not be called"); + } + mergeFields() { + TemporalHelpers.assertUnreachable("mergeFields should not be called"); + } + } + + return new CalendarThrowEverything(); + }, + + /* + * oneShiftTimeZone(shiftInstant, shiftNanoseconds): + * + * In the case of a spring-forward time zone offset transition (skipped time), + * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a + * negative number of nanoseconds from a PlainDateTime, which should balance + * with the microseconds field. + * + * This returns an instance of a custom time zone class which skips a length + * of time equal to shiftNanoseconds (a number), at the Temporal.Instant + * shiftInstant. Before shiftInstant, it's identical to UTC, and after + * shiftInstant it's a constant-offset time zone. + * + * It provides a getPossibleInstantsForCalledWith member which is an array + * with the result of calling toString() on any PlainDateTimes passed to + * getPossibleInstantsFor(). + */ + oneShiftTimeZone(shiftInstant, shiftNanoseconds) { + class OneShiftTimeZone extends Temporal.TimeZone { + constructor(shiftInstant, shiftNanoseconds) { + super("+00:00"); + this._shiftInstant = shiftInstant; + this._epoch1 = shiftInstant.epochNanoseconds; + this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds); + this._shiftNanoseconds = shiftNanoseconds; + this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds); + this.getPossibleInstantsForCalledWith = []; + } + + _isBeforeShift(instant) { + return instant.epochNanoseconds < this._epoch1; + } + + getOffsetNanosecondsFor(instant) { + return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds; + } + + getPossibleInstantsFor(plainDateTime) { + this.getPossibleInstantsForCalledWith.push(plainDateTime.toString()); + const [instant] = super.getPossibleInstantsFor(plainDateTime); + if (this._shiftNanoseconds > 0) { + if (this._isBeforeShift(instant)) return [instant]; + if (instant.epochNanoseconds < this._epoch2) return []; + return [instant.subtract(this._shift)]; + } + if (instant.epochNanoseconds < this._epoch2) return [instant]; + const shifted = instant.subtract(this._shift); + if (this._isBeforeShift(instant)) return [instant, shifted]; + return [shifted]; + } + + getNextTransition(instant) { + return this._isBeforeShift(instant) ? this._shiftInstant : null; + } + + getPreviousTransition(instant) { + return this._isBeforeShift(instant) ? null : this._shiftInstant; + } + + toString() { + return "Custom/One_Shift"; + } + } + return new OneShiftTimeZone(shiftInstant, shiftNanoseconds); + }, + + /* + * specificOffsetTimeZone(): + * + * This returns an instance of a custom time zone class, which returns a + * specific custom value from its getOffsetNanosecondsFrom() method. This is + * for the purpose of testing the validation of what this method returns. + * + * It also returns an empty array from getPossibleInstantsFor(), so as to + * trigger calls to getOffsetNanosecondsFor() when used from the + * BuiltinTimeZoneGetInstantFor operation. + */ + specificOffsetTimeZone(offsetValue) { + class SpecificOffsetTimeZone extends Temporal.TimeZone { + constructor(offsetValue) { + super("UTC"); + this._offsetValue = offsetValue; + } + + getOffsetNanosecondsFor() { + return this._offsetValue; + } + + getPossibleInstantsFor() { + return []; + } + } + return new SpecificOffsetTimeZone(offsetValue); + }, + + /* + * springForwardFallBackTimeZone(): + * + * This returns an instance of a custom time zone class that implements one + * single spring-forward/fall-back transition, for the purpose of testing the + * disambiguation option, without depending on system time zone data. + * + * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00 + * local) and goes from offset -08:00 to -07:00. + * + * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and + * goes from offset -07:00 to -08:00. + */ + springForwardFallBackTimeZone() { + const { compare } = Temporal.PlainDateTime; + const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2); + const springForwardEpoch = 954669600_000_000_000n; + const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1); + const fallBackEpoch = 972810000_000_000_000n; + const winterOffset = new Temporal.TimeZone('-08:00'); + const summerOffset = new Temporal.TimeZone('-07:00'); + + class SpringForwardFallBackTimeZone extends Temporal.TimeZone { + constructor() { + super("-08:00"); + } + + getOffsetNanosecondsFor(instant) { + if (instant.epochNanoseconds < springForwardEpoch || + instant.epochNanoseconds >= fallBackEpoch) { + return winterOffset.getOffsetNanosecondsFor(instant); + } + return summerOffset.getOffsetNanosecondsFor(instant); + } + + getPossibleInstantsFor(datetime) { + if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) { + return []; + } + if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) { + return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)]; + } + if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) { + return [winterOffset.getInstantFor(datetime)]; + } + return [summerOffset.getInstantFor(datetime)]; + } + + getPreviousTransition(instant) { + if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + return null; + } + + getNextTransition(instant) { + if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch); + if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch); + return null; + } + + toString() { + return "Custom/Spring_Fall"; + } + } + return new SpringForwardFallBackTimeZone(); + }, + + /* + * Returns an object that will append logs of any Gets or Calls of its valueOf + * or toString properties to the array calls. Both valueOf and toString will + * return the actual primitiveValue. propertyName is used in the log. + */ + toPrimitiveObserver(calls, primitiveValue, propertyName) { + return { + get valueOf() { + calls.push(`get ${propertyName}.valueOf`); + return function () { + calls.push(`call ${propertyName}.valueOf`); + return primitiveValue; + }; + }, + get toString() { + calls.push(`get ${propertyName}.toString`); + return function () { + calls.push(`call ${propertyName}.toString`); + if (primitiveValue === undefined) return undefined; + return primitiveValue.toString(); + }; + }, + }; + }, +}; diff --git a/js/src/tests/test262/intl402/Temporal/ZonedDateTime/shell.js b/js/src/tests/test262/intl402/Temporal/ZonedDateTime/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/browser.js b/js/src/tests/test262/intl402/Temporal/browser.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/Temporal/shell.js b/js/src/tests/test262/intl402/Temporal/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/tests/test262/intl402/shell.js b/js/src/tests/test262/intl402/shell.js index be288d57ec92..bda2e955367b 100644 --- a/js/src/tests/test262/intl402/shell.js +++ b/js/src/tests/test262/intl402/shell.js @@ -21,7 +21,12 @@ defines: - getInvalidLocaleArguments - testOption - testForUnwantedRegExpChanges + - allCalendars + - allCollations + - allNumberingSystems - isValidNumberingSystem + - numberingSystemDigits + - allSimpleSanctionedUnits - testNumberFormat - getDateTimeComponents - getDateTimeComponentValues @@ -2031,17 +2036,71 @@ function testForUnwantedRegExpChanges(testFunc) { /** - * Tests whether name is a valid BCP 47 numbering system name - * and not excluded from use in the ECMAScript Internationalization API. - * @param {string} name the name to be tested. - * @return {boolean} whether name is a valid BCP 47 numbering system name and - * allowed for use in the ECMAScript Internationalization API. + * Returns an array of all known calendars. */ +function allCalendars() { + // source: CLDR file common/bcp47/number.xml; version CLDR 39. + // https://github.com/unicode-org/cldr/blob/master/common/bcp47/calendar.xml + return [ + "buddhist", + "chinese", + "coptic", + "dangi", + "ethioaa", + "ethiopic", + "gregory", + "hebrew", + "indian", + "islamic", + "islamic-umalqura", + "islamic-tbla", + "islamic-civil", + "islamic-rgsa", + "iso8601", + "japanese", + "persian", + "roc", + ]; +} -function isValidNumberingSystem(name) { - // source: CLDR file common/bcp47/number.xml; version CLDR 36.1. - var numberingSystems = [ +/** + * Returns an array of all known collations. + */ +function allCollations() { + // source: CLDR file common/bcp47/collation.xml; version CLDR 39. + // https://github.com/unicode-org/cldr/blob/master/common/bcp47/collation.xml + return [ + "big5han", + "compat", + "dict", + "direct", + "ducet", + "emoji", + "eor", + "gb2312", + "phonebk", + "phonetic", + "pinyin", + "reformed", + "search", + "searchjl", + "standard", + "stroke", + "trad", + "unihan", + "zhuyin", + ]; +} + + +/** + * Returns an array of all known numbering systems. + */ +function allNumberingSystems() { + // source: CLDR file common/bcp47/number.xml; version CLDR 39. + // https://github.com/unicode-org/cldr/blob/master/common/bcp47/number.xml + return [ "adlm", "ahom", "arab", @@ -2130,6 +2189,20 @@ function isValidNumberingSystem(name) { "wara", "wcho", ]; +} + + +/** + * Tests whether name is a valid BCP 47 numbering system name + * and not excluded from use in the ECMAScript Internationalization API. + * @param {string} name the name to be tested. + * @return {boolean} whether name is a valid BCP 47 numbering system name and + * allowed for use in the ECMAScript Internationalization API. + */ + +function isValidNumberingSystem(name) { + + var numberingSystems = allNumberingSystems(); var excluded = [ "finance", @@ -2217,6 +2290,59 @@ var numberingSystemDigits = { }; +/** + * Returns an array of all simple, sanctioned unit identifiers. + */ +function allSimpleSanctionedUnits() { + // https://tc39.es/ecma402/#table-sanctioned-simple-unit-identifiers + return [ + "acre", + "bit", + "byte", + "celsius", + "centimeter", + "day", + "degree", + "fahrenheit", + "fluid-ounce", + "foot", + "gallon", + "gigabit", + "gigabyte", + "gram", + "hectare", + "hour", + "inch", + "kilobit", + "kilobyte", + "kilogram", + "kilometer", + "liter", + "megabit", + "megabyte", + "meter", + "mile", + "mile-scandinavian", + "milliliter", + "millimeter", + "millisecond", + "minute", + "month", + "ounce", + "percent", + "petabyte", + "pound", + "second", + "stone", + "terabit", + "terabyte", + "week", + "yard", + "year", + ]; +} + + /** * Tests that number formatting is handled correctly. The function checks that the * digit sequences in formatted output are as specified, converted to the diff --git a/js/src/tests/test262/language/block-scope/syntax/for-in/acquire-properties-from-array.js b/js/src/tests/test262/language/block-scope/syntax/for-in/acquire-properties-from-array.js index 80f13ea6d794..66a0be39ddc4 100644 --- a/js/src/tests/test262/language/block-scope/syntax/for-in/acquire-properties-from-array.js +++ b/js/src/tests/test262/language/block-scope/syntax/for-in/acquire-properties-from-array.js @@ -4,21 +4,40 @@ es6id: 13.1 description: > for-in to acquire properties from array -includes: [arrayContains.js] ---*/ function props(x) { var array = []; for (let p in x) array.push(p); return array; } +var subject; -assert.sameValue(props([]).length, 0); -assert.sameValue(props([1]).length, 1); -assert.sameValue(props([1,2]).length, 2); -assert.sameValue(props([1,2,3]).length, 3); +subject = props([]); +assert.sameValue(subject.length, 0, "[]: length"); +assert.sameValue(subject[0], undefined, "[]: first property"); +assert.sameValue(subject[1], undefined, "[]: second property"); +assert.sameValue(subject[2], undefined, "[]: third property"); +assert.sameValue(subject[3], undefined, "[]: fourth property"); -assert(arrayContains(props([1]), ["0"])); -assert(arrayContains(props([1,2]), ["0", "1"])); -assert(arrayContains(props([1,2,3]), ["0", "1", "2"])); +subject = props([1]); +assert.sameValue(subject.length, 1, "[1]: length"); +assert.sameValue(subject[0], "0", "[1]: first property"); +assert.sameValue(subject[1], undefined, "[1]: second property"); +assert.sameValue(subject[2], undefined, "[1]: third property"); +assert.sameValue(subject[3], undefined, "[1]: fourth property"); + +subject = props([1, 2]); +assert.sameValue(subject.length, 2, "[1, 2]: length"); +assert.sameValue(subject[0], "0", "[1, 2]: first property"); +assert.sameValue(subject[1], "1", "[1, 2]: second property"); +assert.sameValue(subject[2], undefined, "[1, 2]: third property"); +assert.sameValue(subject[3], undefined, "[1, 2]: fourth property"); + +subject = props([1, 2, 3]); +assert.sameValue(subject.length, 3, "[1, 2, 3]: length"); +assert.sameValue(subject[0], "0", "[1, 2, 3]: first property"); +assert.sameValue(subject[1], "1", "[1, 2, 3]: second property"); +assert.sameValue(subject[2], "2", "[1, 2, 3]: third property"); +assert.sameValue(subject[3], undefined, "[1, 2, 3]: fourth property"); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/block-scope/syntax/for-in/acquire-properties-from-object.js b/js/src/tests/test262/language/block-scope/syntax/for-in/acquire-properties-from-object.js index 235c78c960c1..9016fb3b1dff 100644 --- a/js/src/tests/test262/language/block-scope/syntax/for-in/acquire-properties-from-object.js +++ b/js/src/tests/test262/language/block-scope/syntax/for-in/acquire-properties-from-object.js @@ -4,21 +4,40 @@ es6id: 13.1 description: > for-in to acquire properties from object -includes: [arrayContains.js] ---*/ function props(x) { var array = []; for (let p in x) array.push(p); return array; } +var subject; -assert.sameValue(props({}).length, 0); -assert.sameValue(props({x:1}).length, 1); -assert.sameValue(props({x:1, y:2}).length, 2); -assert.sameValue(props({x:1, y:2, zoom:3}).length, 3); +subject = props({}); +assert.sameValue(subject.length, 0, "{}: length"); +assert.sameValue(subject[0], undefined, "{}: first property"); +assert.sameValue(subject[1], undefined, "{}: second property"); +assert.sameValue(subject[2], undefined, "{}: third property"); +assert.sameValue(subject[3], undefined, "{}: fourth property"); -assert(arrayContains(props({x:1}), ["x"])); -assert(arrayContains(props({x:1, y:2}), ["x", "y"])); -assert(arrayContains(props({x:1, y:2, zoom:3}), ["x", "y", "zoom"])); +subject = props({x:1}); +assert.sameValue(subject.length, 1, "{x:1}: length"); +assert.sameValue(subject[0], "x", "{x:1}: first property"); +assert.sameValue(subject[1], undefined, "{x:1}: second property"); +assert.sameValue(subject[2], undefined, "{x:1}: third property"); +assert.sameValue(subject[3], undefined, "{x:1}: fourth property"); + +subject = props({x:1, y:2}); +assert.sameValue(subject.length, 2, "{x:1, y:2}: length"); +assert.sameValue(subject[0], "x", "{x:1, y:2}: first property"); +assert.sameValue(subject[1], "y", "{x:1, y:2}: second property"); +assert.sameValue(subject[2], undefined, "{x:1, y:2}: third property"); +assert.sameValue(subject[3], undefined, "{x:1, y:2}: fourth property"); + +subject = props({x:1, y:2, zoom:3}); +assert.sameValue(subject.length, 3, "{x:1, y:2, zoom:3}: length"); +assert.sameValue(subject[0], "x", "{x:1, y:2, zoom:3}: first property"); +assert.sameValue(subject[1], "y", "{x:1, y:2, zoom:3}: second property"); +assert.sameValue(subject[2], "zoom", "{x:1, y:2, zoom:3}: third property"); +assert.sameValue(subject[3], undefined, "{x:1, y:2, zoom:3}: fourth property"); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/block-scope/syntax/for-in/shell.js b/js/src/tests/test262/language/block-scope/syntax/for-in/shell.js index 40bfce343709..e69de29bb2d1 100644 --- a/js/src/tests/test262/language/block-scope/syntax/for-in/shell.js +++ b/js/src/tests/test262/language/block-scope/syntax/for-in/shell.js @@ -1,31 +0,0 @@ -// GENERATED, DO NOT EDIT -// file: arrayContains.js -// Copyright (C) 2017 Ecma International. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -description: | - Verify that a subArray is contained within an array. -defines: [arrayContains] ----*/ - -/** - * @param {Array} array - * @param {Array} subArray - */ - -function arrayContains(array, subArray) { - var found; - for (var i = 0; i < subArray.length; i++) { - found = false; - for (var j = 0; j < array.length; j++) { - if (subArray[i] === array[j]) { - found = true; - break; - } - } - if (!found) { - return false; - } - } - return true; -} diff --git a/js/src/tests/test262/language/comments/S7.4_A5.js b/js/src/tests/test262/language/comments/S7.4_A5.js index 07bbfff6910a..933e8e4db83c 100644 --- a/js/src/tests/test262/language/comments/S7.4_A5.js +++ b/js/src/tests/test262/language/comments/S7.4_A5.js @@ -11,9 +11,6 @@ description: > characters ---*/ -//CHECK -var errorCount = 0; -var count = 0; var hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]; for (var i1 = 0; i1 < 16; i1++) { for (var i2 = 0; i2 < 16; i2++) { @@ -28,26 +25,18 @@ for (var i1 = 0; i1 < 16; i1++) { if (LineTerminators !== true) { if (yy !== 0) { throw new Test262Error('#' + uu + ' '); - errorCount++; } } else { if (yy !== -1) { throw new Test262Error('#' + uu + ' '); - errorCount++; } } } catch (e){ throw new Test262Error('#' + uu + ' '); - errorCount++; } - count++; } } } } -if (errorCount > 0) { - throw new Test262Error('Total error: ' + errorCount + ' bad Unicode character in ' + count); -} - reportCompare(0, 0); diff --git a/js/src/tests/test262/language/comments/S7.4_A6.js b/js/src/tests/test262/language/comments/S7.4_A6.js index 8a86561044a6..e91a6f571057 100644 --- a/js/src/tests/test262/language/comments/S7.4_A6.js +++ b/js/src/tests/test262/language/comments/S7.4_A6.js @@ -7,53 +7,20 @@ info: | character es5id: 7.4_A6 description: "\"var\"+ yy+ \"xx = 1\", insert instead of yy all Unicode characters" +includes: [decimalToHexString.js] ---*/ -//CHECK -var errorCount = 0; -var count = 0; for (var indexI = 0; indexI <= 65535; indexI++) { try { var xx = 0; eval("/*var " + String.fromCharCode(indexI) + "xx = 1*/"); - var hex = decimalToHexString(indexI); - if (xx !== 0) { - throw new Test262Error('#' + hex + ' '); - errorCount++; - } + var differs = xx !== 0; } catch (e){ - throw new Test262Error('#' + hex + ' '); - errorCount++; + throw new Test262Error('#' + decimalToHexString(indexI) + ' throws'); } - count++; -} - -if (errorCount > 0) { - throw new Test262Error('Total error: ' + errorCount + ' bad Unicode character in ' + count); -} - -function decimalToHexString(n) { - n = Number(n); - var h = ""; - for (var i = 3; i >= 0; i--) { - if (n >= Math.pow(16, i)) { - var t = Math.floor(n / Math.pow(16, i)); - n -= t * Math.pow(16, i); - if ( t >= 10 ) { - if ( t == 10 ) { h += "A"; } - if ( t == 11 ) { h += "B"; } - if ( t == 12 ) { h += "C"; } - if ( t == 13 ) { h += "D"; } - if ( t == 14 ) { h += "E"; } - if ( t == 15 ) { h += "F"; } - } else { - h += String(t); - } - } else { - h += "0"; - } + if (differs) { + throw new Test262Error('#' + decimalToHexString(indexI) + ' differs'); } - return h; } reportCompare(0, 0); diff --git a/js/src/tests/test262/language/comments/shell.js b/js/src/tests/test262/language/comments/shell.js index e69de29bb2d1..a8ffe3a68028 100644 --- a/js/src/tests/test262/language/comments/shell.js +++ b/js/src/tests/test262/language/comments/shell.js @@ -0,0 +1,28 @@ +// GENERATED, DO NOT EDIT +// file: decimalToHexString.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of various encoding operations. +defines: [decimalToHexString, decimalToPercentHexString] +---*/ + +function decimalToHexString(n) { + var hex = "0123456789ABCDEF"; + n >>>= 0; + var s = ""; + while (n) { + s = hex[n & 0xf] + s; + n >>>= 4; + } + while (s.length < 4) { + s = "0" + s; + } + return s; +} + +function decimalToPercentHexString(n) { + var hex = "0123456789ABCDEF"; + return "%" + hex[(n >> 4) & 0xf] + hex[n & 0xf]; +} diff --git a/js/src/tests/test262/language/computed-property-names/basics/number.js b/js/src/tests/test262/language/computed-property-names/basics/number.js index 1face66c6d13..264918d0c09b 100644 --- a/js/src/tests/test262/language/computed-property-names/basics/number.js +++ b/js/src/tests/test262/language/computed-property-names/basics/number.js @@ -21,9 +21,9 @@ assert.sameValue(object.a, 'A', "The value of `object.a` is `'A'`. Defined in `o assert.sameValue(object[1], 'B', "The value of `object[1]` is `'B'`. Defined in `object` as `[1]: 'B'`"); assert.sameValue(object.c, 'C', "The value of `object.c` is `'C'`. Defined in `object` as `c: 'C'`"); assert.sameValue(object[2], 'D', "The value of `object[2]` is `'D'`. Defined in `object` as `[ID(2)]: 'D'`"); -assert( - compareArray(Object.getOwnPropertyNames(object), ['1', '2', 'a', 'c']), - "`compareArray(Object.getOwnPropertyNames(object), ['1', '2', 'a', 'c'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(object), + ['1', '2', 'a', 'c'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/basics/string.js b/js/src/tests/test262/language/computed-property-names/basics/string.js index 9613511635c1..f4cc83a088e0 100644 --- a/js/src/tests/test262/language/computed-property-names/basics/string.js +++ b/js/src/tests/test262/language/computed-property-names/basics/string.js @@ -20,9 +20,9 @@ assert.sameValue(object.a, 'A', "The value of `object.a` is `'A'`. Defined in `o assert.sameValue(object.b, 'B', "The value of `object.b` is `'B'`. Defined in `object` as `['b']: 'B'`"); assert.sameValue(object.c, 'C', "The value of `object.c` is `'C'`. Defined in `object` as `c: 'C'`"); assert.sameValue(object.d, 'D', "The value of `object.d` is `'D'`. Defined in `object` as `[ID('d')]: 'D'`"); -assert( - compareArray(Object.getOwnPropertyNames(object), ['a', 'b', 'c', 'd']), - "`compareArray(Object.getOwnPropertyNames(object), ['a', 'b', 'c', 'd'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(object), + ['a', 'b', 'c', 'd'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/basics/symbol.js b/js/src/tests/test262/language/computed-property-names/basics/symbol.js index df100090d021..75d857f4c4c7 100644 --- a/js/src/tests/test262/language/computed-property-names/basics/symbol.js +++ b/js/src/tests/test262/language/computed-property-names/basics/symbol.js @@ -24,13 +24,13 @@ assert.sameValue(object.a, 'A', "The value of `object.a` is `'A'`. Defined in `o assert.sameValue(object[sym1], 'B', "The value of `object[sym1]` is `'B'`. Defined in `object` as `[sym1]: 'B'`"); assert.sameValue(object.c, 'C', "The value of `object.c` is `'C'`. Defined in `object` as `c: 'C'`"); assert.sameValue(object[sym2], 'D', "The value of `object[sym2]` is `'D'`. Defined in `object` as `[ID(sym2)]: 'D'`"); -assert( - compareArray(Object.getOwnPropertyNames(object), ['a', 'c']), - "`compareArray(Object.getOwnPropertyNames(object), ['a', 'c'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(object), + ['a', 'c'] ); -assert( - compareArray(Object.getOwnPropertySymbols(object), [sym1, sym2]), - "`compareArray(Object.getOwnPropertySymbols(object), [sym1, sym2])` returns `true`" +assert.compareArray( + Object.getOwnPropertySymbols(object), + [sym1, sym2] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/class/method/generator.js b/js/src/tests/test262/language/computed-property-names/class/method/generator.js index 5fa7ef454b47..cfd471bc8c7b 100644 --- a/js/src/tests/test262/language/computed-property-names/class/method/generator.js +++ b/js/src/tests/test262/language/computed-property-names/class/method/generator.js @@ -17,9 +17,9 @@ assert.sameValue( 0, "The value of `Object.keys(C.prototype).length` is `0`" ); -assert( - compareArray(Object.getOwnPropertyNames(C.prototype), ['constructor', 'a']), - "`compareArray(Object.getOwnPropertyNames(C.prototype), ['constructor', 'a'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(C.prototype), + ['constructor', 'a'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/class/method/number.js b/js/src/tests/test262/language/computed-property-names/class/method/number.js index 1a022be11967..e9ee5e12bcac 100644 --- a/js/src/tests/test262/language/computed-property-names/class/method/number.js +++ b/js/src/tests/test262/language/computed-property-names/class/method/number.js @@ -24,9 +24,9 @@ assert.sameValue(new C()[2](), 'D', "`new C()[2]()` returns `'D'`, from `[ID(2)] assert.sameValue(Object.keys(C.prototype).length, 0, "No enum keys from C.prototype"); -assert( - compareArray(Object.getOwnPropertyNames(C.prototype), ['1', '2', 'constructor', 'a', 'c']), - "`compareArray(Object.getOwnPropertyNames(C.prototype), ['1', '2', 'constructor', 'a', 'c'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(C.prototype), + ['1', '2', 'constructor', 'a', 'c'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/class/method/string.js b/js/src/tests/test262/language/computed-property-names/class/method/string.js index 5a3ca2bfb609..c152bc6c033d 100644 --- a/js/src/tests/test262/language/computed-property-names/class/method/string.js +++ b/js/src/tests/test262/language/computed-property-names/class/method/string.js @@ -22,9 +22,9 @@ assert.sameValue(new C().b(), 'B', "`new C().b()` returns `'B'`. Defined as `['b assert.sameValue(new C().c(), 'C', "`new C().c()` returns `'C'`. Defined as `c() { return 'C'; }`"); assert.sameValue(new C().d(), 'D', "`new C().d()` returns `'D'`. Defined as `[ID('d')]() { return 'D'; }`"); assert.sameValue(Object.keys(C.prototype).length, 0, "No enum keys from C.prototype"); -assert( - compareArray(Object.getOwnPropertyNames(C.prototype), ['constructor', 'a', 'b', 'c', 'd']), - "`compareArray(Object.getOwnPropertyNames(C.prototype), ['constructor', 'a', 'b', 'c', 'd'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(C.prototype), + ['constructor', 'a', 'b', 'c', 'd'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/class/method/symbol.js b/js/src/tests/test262/language/computed-property-names/class/method/symbol.js index f71b359cc322..07bac0c9cd80 100644 --- a/js/src/tests/test262/language/computed-property-names/class/method/symbol.js +++ b/js/src/tests/test262/language/computed-property-names/class/method/symbol.js @@ -25,13 +25,13 @@ assert.sameValue(new C()[sym1](), 'B', "`new C()[sym1]()` returns `'B'`. Defined assert.sameValue(new C().c(), 'C', "`new C().c()` returns `'C'`. Defined as `c() { return 'C'; }`"); assert.sameValue(new C()[sym2](), 'D', "`new C()[sym2]()` returns `'D'`. Defined as `[ID(sym2)]() { return 'D'; }`"); assert.sameValue(Object.keys(C.prototype).length, 0, "No enum keys from C.prototype"); -assert( - compareArray(Object.getOwnPropertyNames(C.prototype), ['constructor', 'a', 'c']), - "`compareArray(Object.getOwnPropertyNames(C.prototype), ['constructor', 'a', 'c'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(C.prototype), + ['constructor', 'a', 'c'] ); -assert( - compareArray(Object.getOwnPropertySymbols(C.prototype), [sym1, sym2]), - "`compareArray(Object.getOwnPropertySymbols(C.prototype), [sym1, sym2])` returns `true`" +assert.compareArray( + Object.getOwnPropertySymbols(C.prototype), + [sym1, sym2] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/object/method/generator.js b/js/src/tests/test262/language/computed-property-names/object/method/generator.js index a78e310da70d..f52d807bcb6f 100644 --- a/js/src/tests/test262/language/computed-property-names/object/method/generator.js +++ b/js/src/tests/test262/language/computed-property-names/object/method/generator.js @@ -12,9 +12,9 @@ var object = { yield 2; } }; -assert( - compareArray(Object.keys(object), ['a']), - "`compareArray(Object.keys(object), ['a'])` returns `true`" +assert.compareArray( + Object.keys(object), + ['a'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/object/method/number.js b/js/src/tests/test262/language/computed-property-names/object/method/number.js index f8c75c2d41f3..446f6f4a77cd 100644 --- a/js/src/tests/test262/language/computed-property-names/object/method/number.js +++ b/js/src/tests/test262/language/computed-property-names/object/method/number.js @@ -21,9 +21,9 @@ assert.sameValue(object.a(), 'A', "`object.a()` returns `'A'`. Defined as `a() { assert.sameValue(object[1](), 'B', "`object[1]()` returns `'B'`. Defined as `[1]() { return 'B'; }`"); assert.sameValue(object.c(), 'C', "`object.c()` returns `'C'`. Defined as `c() { return 'C'; }`"); assert.sameValue(object[2](), 'D', "`object[2]()` returns `'D'`. Defined as `[ID(2)]() { return 'D'; }`"); -assert( - compareArray(Object.getOwnPropertyNames(object), ['1', '2', 'a', 'c']), - "`compareArray(Object.getOwnPropertyNames(object), ['1', '2', 'a', 'c'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(object), + ['1', '2', 'a', 'c'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/object/method/string.js b/js/src/tests/test262/language/computed-property-names/object/method/string.js index 6a25cd49a6f9..fc165ffbe4b0 100644 --- a/js/src/tests/test262/language/computed-property-names/object/method/string.js +++ b/js/src/tests/test262/language/computed-property-names/object/method/string.js @@ -21,9 +21,9 @@ assert.sameValue(object.a(), 'A', "`object.a()` returns `'A'`. Defined as `a() { assert.sameValue(object.b(), 'B', "`object.b()` returns `'B'`. Defined as `['b']() { return 'B'; }`"); assert.sameValue(object.c(), 'C', "`object.c()` returns `'C'`. Defined as `c() { return 'C'; }`"); assert.sameValue(object.d(), 'D', "`object.d()` returns `'D'`. Defined as `[ID('d')]() { return 'D'; }`"); -assert( - compareArray(Object.getOwnPropertyNames(object), ['a', 'b', 'c', 'd']), - "`compareArray(Object.getOwnPropertyNames(object), ['a', 'b', 'c', 'd'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(object), + ['a', 'b', 'c', 'd'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/object/method/symbol.js b/js/src/tests/test262/language/computed-property-names/object/method/symbol.js index f5631a2c79e2..6cef8af58594 100644 --- a/js/src/tests/test262/language/computed-property-names/object/method/symbol.js +++ b/js/src/tests/test262/language/computed-property-names/object/method/symbol.js @@ -24,13 +24,13 @@ assert.sameValue(object.a(), 'A', "`object.a()` returns `'A'`. Defined as `a() { assert.sameValue(object[sym1](), 'B', "`object[sym1]()` returns `'B'`. Defined as `[sym1]() { return 'B'; }`"); assert.sameValue(object.c(), 'C', "`object.c()` returns `'C'`. Defined as `c() { return 'C'; }`"); assert.sameValue(object[sym2](), 'D', "`object[sym2]()` returns `'D'`. Defined as `[ID(sym2)]() { return 'D'; }`"); -assert( - compareArray(Object.getOwnPropertyNames(object), ['a', 'c']), - "`compareArray(Object.getOwnPropertyNames(object), ['a', 'c'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(object), + ['a', 'c'] ); -assert( - compareArray(Object.getOwnPropertySymbols(object), [sym1, sym2]), - "`compareArray(Object.getOwnPropertySymbols(object), [sym1, sym2])` returns `true`" +assert.compareArray( + Object.getOwnPropertySymbols(object), + [sym1, sym2] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/to-name-side-effects/numbers-object.js b/js/src/tests/test262/language/computed-property-names/to-name-side-effects/numbers-object.js index 041787dbef64..686924033359 100644 --- a/js/src/tests/test262/language/computed-property-names/to-name-side-effects/numbers-object.js +++ b/js/src/tests/test262/language/computed-property-names/to-name-side-effects/numbers-object.js @@ -33,9 +33,9 @@ assert.sameValue(object.a, 'A', "The value of `object.a` is `'A'`. Defined as `a assert.sameValue(object[1], 'B', "The value of `object[1]` is `'B'`. Defined as `[key1]: 'B'`"); assert.sameValue(object.c, 'C', "The value of `object.c` is `'C'`. Defined as `c: 'C'`"); assert.sameValue(object[2], 'D', "The value of `object[2]` is `'D'`. Defined as `[key2]: 'D'`"); -assert( - compareArray(Object.getOwnPropertyNames(object), ['1', '2', 'a', 'c']), - "`compareArray(Object.getOwnPropertyNames(object), ['1', '2', 'a', 'c'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(object), + ['1', '2', 'a', 'c'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/computed-property-names/to-name-side-effects/object.js b/js/src/tests/test262/language/computed-property-names/to-name-side-effects/object.js index 3dddef9b1a4d..06ccd5476bfa 100644 --- a/js/src/tests/test262/language/computed-property-names/to-name-side-effects/object.js +++ b/js/src/tests/test262/language/computed-property-names/to-name-side-effects/object.js @@ -30,9 +30,9 @@ assert.sameValue(object.a(), 'A', "`object.a()` returns `'A'`. Defined as `a() { assert.sameValue(object.b(), 'B', "`object.b()` returns `'B'`. Defined as `[key1]() { return 'B'; }`"); assert.sameValue(object.c(), 'C', "`object.c()` returns `'C'`. Defined as `c() { return 'C'; }`"); assert.sameValue(object.d(), 'D', "`object.d()` returns `'D'`. Defined as `[key2]() { return 'D'; }`"); -assert( - compareArray(Object.getOwnPropertyNames(object), ['a', 'b', 'c', 'd']), - "`compareArray(Object.getOwnPropertyNames(object), ['a', 'b', 'c', 'd'])` returns `true`" +assert.compareArray( + Object.getOwnPropertyNames(object), + ['a', 'b', 'c', 'd'] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/addition/coerce-bigint-to-string.js b/js/src/tests/test262/language/expressions/addition/coerce-bigint-to-string.js index eff75fff29e6..4fb927520aa3 100644 --- a/js/src/tests/test262/language/expressions/addition/coerce-bigint-to-string.js +++ b/js/src/tests/test262/language/expressions/addition/coerce-bigint-to-string.js @@ -21,8 +21,6 @@ info: | features: [BigInt] ---*/ -function ToString(x) { return x + ""; } - assert.sameValue(-1n + "", "-1"); assert.sameValue("" + -1n, "-1"); assert.sameValue(0n + "", "0"); diff --git a/js/src/tests/test262/language/expressions/array/spread-obj-spread-order.js b/js/src/tests/test262/language/expressions/array/spread-obj-spread-order.js index 5ddeca8b6abf..3e15329cfbdf 100644 --- a/js/src/tests/test262/language/expressions/array/spread-obj-spread-order.js +++ b/js/src/tests/test262/language/expressions/array/spread-obj-spread-order.js @@ -42,7 +42,7 @@ Object.defineProperty(o, Symbol('foo'), { get: () => { calls.push("Symbol(foo)") var callCount = 0; (function(obj) { - assert(compareArray(calls, [1, 'z', 'a', "Symbol(foo)"])); + assert.compareArray(calls, [1, 'z', 'a', "Symbol(foo)"]); assert.sameValue(Object.keys(obj).length, 3); callCount += 1; }.apply(null, [{...o}])); diff --git a/js/src/tests/test262/language/expressions/assignment/dstr/array-rest-iter-rtrn-close-err.js b/js/src/tests/test262/language/expressions/assignment/dstr/array-rest-iter-rtrn-close-err.js index 93b96e12092c..9eae05c5983d 100644 --- a/js/src/tests/test262/language/expressions/assignment/dstr/array-rest-iter-rtrn-close-err.js +++ b/js/src/tests/test262/language/expressions/assignment/dstr/array-rest-iter-rtrn-close-err.js @@ -41,7 +41,6 @@ info: | ---*/ var returnCount = 0; var unreachable = 0; -function ReturnError() {} var iterable = {}; var iterator = { return: function() { diff --git a/js/src/tests/test262/language/expressions/assignment/dstr/obj-rest-order.js b/js/src/tests/test262/language/expressions/assignment/dstr/obj-rest-order.js index 5e2af3039fdc..ebe5ee76fbcc 100644 --- a/js/src/tests/test262/language/expressions/assignment/dstr/obj-rest-order.js +++ b/js/src/tests/test262/language/expressions/assignment/dstr/obj-rest-order.js @@ -27,7 +27,7 @@ var vals = o; result = {...rest} = vals; -assert(compareArray(calls, [1, 'z', 'a', "Symbol(foo)"])); +assert.compareArray(calls, [1, 'z', 'a', "Symbol(foo)"]); assert.sameValue(Object.keys(rest).length, 3); assert.sameValue(result, vals); diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-0.js index b2ce1c4790a5..c923a74e49a1 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x - y = 1; -} - +x - y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-1.js index e0903e334e16..18cd0c47daf9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 - 2 = 1; -} - +1 - 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-2.js index 87fdfc4ece86..5c8fcebf56c7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-minus-multiplicativeexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true - false = 1; -} - +true - false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-0.js index 54c3e8855e26..b594893d3ffd 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x + y = 1; -} - +x + y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-1.js index 90344ea9279e..df5b0796c33d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 + 2 = 1; -} - +1 + 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-2.js index 1d1e5336b95c..c0ed684edc7b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-additiveexpression-plus-multiplicativeexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true + false = 1; -} - +true + false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-0.js index b92edbfa8acf..237513ed188e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - () => {} = 1; -} - +() => {} = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-1.js index 499d79b6d6b2..1d8792cb50f0 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - () => ({}) = 1; -} - +() => ({}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-2.js index 44d4a596e6a7..d9f3231c95bc 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x => x) = 1; -} - +(x => x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-3.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-3.js index 10d13b7df443..d889ddf6c7ac 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-3.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-3.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x) => x) = 1; -} - +((x) => x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-4.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-4.js index a7a215c9bb44..83be1e3c9293 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-4.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-4.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (() => 1) = 1; -} - +(() => 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-5.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-5.js index 5467134de122..af0f5e0c305b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-5.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-5.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (() => true) = 1; -} - +(() => true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-6.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-6.js index 0225e1d59256..b7128196815a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-6.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-arrowfunction-6.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (() => 1) = 1; -} - +(() => 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-0.js index 75cdc87c0d16..4de735d2a79d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - async () => {} = 1; -} - +async () => {} = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-1.js index af5de950d542..72d33e9883b2 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - async () => ({}) = 1; -} - +async () => ({}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-2.js index 500d31befa0a..80cf45925bcb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async x => x) = 1; -} - +(async x => x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-3.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-3.js index a2eab2d70af7..18b982fc4e49 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-3.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-3.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async (x) => x) = 1; -} - +(async (x) => x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-4.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-4.js index 5971a76c4184..1f76a7cd9326 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-4.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-4.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async () => 1) = 1; -} - +(async () => 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-5.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-5.js index 893952b665a4..f97facb3b154 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-5.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-5.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async () => true) = 1; -} - +(async () => true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-6.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-6.js index 373d3e0ebba4..cd54db777cc7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-6.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-asyncarrowfunction-6.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async () => 1) = 1; -} - +(async () => 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-0.js index 2e6c76271947..7e4ad534e04b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x & y = 1; -} - +x & y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-1.js index 4e1771cef00d..40656a84e947 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 & 2 = 1; -} - +1 & 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-2.js index f7bce2fa6cd5..f33a1acd89dc 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseandexpression-bitwise-and-equalityexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true & false = 1; -} - +true & false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-0.js index f854c3d42d67..94441f0f8fed 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x | y = 1; -} - +x | y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-1.js index 653f0da3e9df..216414c87775 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 | 2 = 1; -} - +1 | 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-2.js index df1c9fb045c5..de9cf492abc3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwiseorexpression-bitwise-or-bitwisexorexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true | false = 1; -} - +true | false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-0.js index a3922dca80b0..d889583ca843 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x ^ y = 1; -} - +x ^ y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-1.js index b618a3b53703..ee974f213d74 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 ^ 2 = 1; -} - +1 ^ 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-2.js index 953a61a3a34b..9a3a18b51954 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-bitwisexorexpression-bitwise-xor-bitwiseandexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true ^ false = 1; -} - +true ^ false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-callexpression-arguments.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-callexpression-arguments.js index 431b829c4dcd..0b89359d9efe 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-callexpression-arguments.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-callexpression-arguments.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - f() = 1; -} - +f() = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-callexpression-templateliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-callexpression-templateliteral.js index f77fc96ee4ab..8a5c79f8c1bc 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-callexpression-templateliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-callexpression-templateliteral.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - f()`` = 1; -} - +f()`` = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-0.js index ea3216729422..f74c9fad2dc2 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x ?? y = 1; -} - +x ?? y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-1.js index 0fe9df1d38c6..fb8108446192 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 ?? 2 = 1; -} - +1 ?? 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-2.js index cfcd332455da..a3bdb79659f9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-coalesceexpressionhead-coalesce-bitwiseorexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true ?? false = 1; -} - +true ?? false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-0.js index b0abb463cc02..f4a4723b4191 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x == y = 1; -} - +x == y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-1.js index 1dde6889eaf5..b6ca14b657a1 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 == 2 = 1; -} - +1 == 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-2.js index a3d4f7e5faa7..8977c56b9b4c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-equal-relationalexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true == false = 1; -} - +true == false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-0.js index f8a5265793ba..b5c660250a6a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x != y = 1; -} - +x != y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-1.js index e2691c51e837..e48299cf8e6d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 != 2 = 1; -} - +1 != 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-2.js index a9d935777b28..8c8f71b07beb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-abstract-not-equal-relationalexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true != false = 1; -} - +true != false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-0.js index ccda06cbb44f..e5368c6cc223 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x == y = 1; -} - +x == y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-1.js index e2146d696733..5650e860ccfb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 == 2 = 1; -} - +1 == 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-2.js index 931e37253260..734357d15db7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-equal-relationalexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true == false = 1; -} - +true == false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-0.js index deee067c01fe..56ed763bca93 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x !== y = 1; -} - +x !== y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-1.js index fe1b0b5c07ab..a76976c29c8d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 !== 2 = 1; -} - +1 !== 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-2.js index ac670ac434f3..d000cff2c20f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-equalityexpression-strict-not-equal-relationalexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true !== false = 1; -} - +true !== false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-0.js index fdcb9a7c0236..8a72fdd6a064 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x, y = z) = 1; -} - +(x, y = z) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-1.js index 642bb9d9e88e..efc1a3926c0e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x, y = 1) = 1; -} - +(x, y = 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-2.js index 74346b134e30..a449ffbccf00 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-expression-comma-assignmentexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x, y = true) = 1; -} - +(x, y = true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-identifierreference-arguments-strict-strict.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-identifierreference-arguments-strict-strict.js index 2d3e49575bc5..25874528bbe3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-identifierreference-arguments-strict-strict.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-identifierreference-arguments-strict-strict.js @@ -15,7 +15,4 @@ info: | $DONOTEVALUATE(); -function _() { - arguments = 1; -} - +arguments = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-identifierreference-eval-strict-strict.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-identifierreference-eval-strict-strict.js index 4965a5f094c6..19cb581b3bbd 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-identifierreference-eval-strict-strict.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-identifierreference-eval-strict-strict.js @@ -15,7 +15,4 @@ info: | $DONOTEVALUATE(); -function _() { - eval = 1; -} - +eval = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-import.meta.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-import.meta.js index cfaac9a25a82..c7280331057b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-import.meta.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-import.meta.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - import.meta = 1; -} - +import.meta = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-importcall.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-importcall.js index d29df054e3a4..5e45a325bf42 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-importcall.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-importcall.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - import() = 1; -} - +import() = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-0.js index a5086bf14dca..db2c980fbb14 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x = y) = 1; -} - +(x = y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-1.js index b784130a9cd4..f112454a5bbb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x = 1) = 1; -} - +(x = 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-2.js index f1229d24094a..23a48e6f75a1 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-assignment-assignmentexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x = true) = 1; -} - +(x = true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-0.js index 313603787499..de1b6b53f9bb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ??= y) = 1; -} - +(x ??= y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-1.js index 60d46f62a29b..552903286669 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ??= 1) = 1; -} - +(x ??= 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-2.js index 250dd07e816c..e34830b303c7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-coalesce-assignment-assignmentexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ??= true) = 1; -} - +(x ??= true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-0.js index a470df77f159..4e204d29da8a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x &&= y) = 1; -} - +(x &&= y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-1.js index 07ed9c7c93ad..5cf90937f437 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x &&= 1) = 1; -} - +(x &&= 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-2.js index 0f443e58cc28..e2cbbb079d00 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-and-assignment-assignmentexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x &&= true) = 1; -} - +(x &&= true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-0.js index 4288c8bef8a8..d96d2d81442f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ||= y) = 1; -} - +(x ||= y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-1.js index 4c1a4a102174..26f112aca154 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ||= 1) = 1; -} - +(x ||= 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-2.js index b33df44a927e..ada85abf34c5 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-logical-or-assignment-assignmentexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ||= true) = 1; -} - +(x ||= true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-minus-minus.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-minus-minus.js index 3c8046c7cb29..5974ad0d0fcd 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-minus-minus.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-minus-minus.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x-- = 1; -} - +x-- = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-plus-plus.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-plus-plus.js index 3268ce54641f..7745d60f624a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-plus-plus.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-lefthandsideexpression-plus-plus.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x++ = 1; -} - +x++ = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-0.js index caa79ea94457..16aba3e697e3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x && y = 1; -} - +x && y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-1.js index e1d93f1e8d50..41859a7b264f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 && 2 = 1; -} - +1 && 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-2.js index fce78c11b79d..71c8558f9c99 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalandexpression-logical-and-bitwiseorexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true && false = 1; -} - +true && false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-0.js index c6152e339e21..e6432da48981 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x || y = 1; -} - +x || y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-1.js index 2749bd178231..28462a02821d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 || 2 = 1; -} - +1 || 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-2.js index 642ba96877f0..49f676d981c7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-logicalorexpression-logical-or-logicalandexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true || false = 1; -} - +true || false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-memberexpression-templateliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-memberexpression-templateliteral.js index 89687abb11da..1ad3095f1949 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-memberexpression-templateliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-memberexpression-templateliteral.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - o.f()`` = 1; -} - +o.f()`` = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-minus-minus-unaryexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-minus-minus-unaryexpression.js index 3b744e1184e4..aef2f56c1e62 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-minus-minus-unaryexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-minus-minus-unaryexpression.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - --x = 1; -} - +--x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-0.js index d18e9652ba9a..835028c16af3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x * y = 1; -} - +x * y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-1.js index 9983809571d7..593289fc7a57 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 * 2 = 1; -} - +1 * 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-2.js index 7751230f34b5..a1ee2b78f33d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true * false = 1; -} - +true * false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-3.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-3.js index db47825c56bb..2e4af3467bd3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-3.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-3.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x / y = 1; -} - +x / y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-4.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-4.js index c0496255749a..221956131a78 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-4.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-4.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 / 2 = 1; -} - +1 / 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-5.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-5.js index 52748022b949..7412a58f78ee 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-5.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-5.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true / false = 1; -} - +true / false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-new-memberexpression-arguments.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-new-memberexpression-arguments.js index 4786552836e2..c0bbe9fc8209 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-new-memberexpression-arguments.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-new-memberexpression-arguments.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - new f() = 1; -} - +new f() = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-new-newexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-new-newexpression.js index 18aa72122b18..61beb6d60371 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-new-newexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-new-newexpression.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - new f = 1; -} - +new f = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-optionalexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-optionalexpression.js index 8359338a2c85..1b8945857253 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-optionalexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-optionalexpression.js @@ -19,7 +19,4 @@ info: | $DONOTEVALUATE(); -function _() { - x?.y = 1; -} - +x?.y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-plus-plus-unaryexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-plus-plus-unaryexpression.js index 0c7faa9f4445..066a8898cb6c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-plus-plus-unaryexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-plus-plus-unaryexpression.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - ++x = 1; -} - +++x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-asyncfunctionexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-asyncfunctionexpression.js index 3c2154ba2967..edb05be2d831 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-asyncfunctionexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-asyncfunctionexpression.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - async function () {} = 1; -} - +async function () {} = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-asyncgeneratorexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-asyncgeneratorexpression.js index 42f1cc6845f8..c165a2a58d44 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-asyncgeneratorexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-asyncgeneratorexpression.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - async function () {} = 1; -} - +async function () {} = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-classexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-classexpression.js index 648cc3186344..ee90fe884994 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-classexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-classexpression.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - class {} = 1; -} - +class {} = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-functionexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-functionexpression.js index 5b10b57dec5e..7e4e4a3e2b8a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-functionexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-functionexpression.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - function() {} = 1; -} - +function() {} = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-generatorexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-generatorexpression.js index 780de28588fb..ed919f5fff79 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-generatorexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-generatorexpression.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - function * () {} = 1; -} - +function * () {} = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-boolean.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-boolean.js index c5bf797053e3..9589ddfe5aa0 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-boolean.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-boolean.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - true = 1; -} - +true = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-null.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-null.js index 8fc164762fd1..143619507c62 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-null.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-null.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - null = 1; -} - +null = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-numeric.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-numeric.js index 328f28c0f364..98f1f0153a0c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-numeric.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-numeric.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - 0 = 1; -} - +0 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-string.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-string.js index 6b536b402958..11315f9e360f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-string.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-literal-string.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - '' = 1; -} - +'' = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-objectliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-objectliteral.js index 2e22e84626f3..38074ca00dc0 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-objectliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-objectliteral.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - {} = 1; -} - +{} = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-regularexpressionliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-regularexpressionliteral.js index 32ba224e64f6..5fa84419754d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-regularexpressionliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-regularexpressionliteral.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - /1/ = 1; -} - +/1/ = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-templateliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-templateliteral.js index 8890a1357573..4969115e939f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-templateliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-templateliteral.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - `` = 1; -} - +`` = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-this.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-this.js index 684c44f1a485..46be392d6f01 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-this.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-primaryexpression-this.js @@ -14,7 +14,4 @@ info: | $DONOTEVALUATE(); -function _() { - this = 1; -} - +this = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-0.js index 27b7bfb7d191..c4aee6224e9a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x >= y = 1; -} - +x >= y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-1.js index f9b3ffcc08cd..e56dcb1ed615 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 >= 2 = 1; -} - +1 >= 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-2.js index cf2594c9e182..f50beb562d75 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-or-equal-to-shiftexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true >= false = 1; -} - +true >= false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-0.js index 7f0de2ce4569..91b645d8ea72 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x > y = 1; -} - +x > y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-1.js index e3afee3f7d9a..d5a02ddf03c7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 > 2 = 1; -} - +1 > 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-2.js index 65acef2feabe..bbc30a6fa381 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-greater-than-shiftexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true > false = 1; -} - +true > false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-0.js index 7fce459c73a5..45b07d1b1cb6 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x in y = 1; -} - +x in y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-1.js index 9ec1d77d489f..277ebde21a26 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 in 2 = 1; -} - +1 in 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-2.js index f2b1c9165430..0ded44ee9514 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-in-shiftexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true in false = 1; -} - +true in false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-0.js index 06cb53cd7493..5aadccfc6845 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x instanceof y = 1; -} - +x instanceof y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-1.js index 288fc3272d0a..119f5df5a137 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 instanceof 2 = 1; -} - +1 instanceof 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-2.js index 8d3703940ec3..db8261dbd745 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-instanceof-shiftexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true instanceof false = 1; -} - +true instanceof false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-0.js index f9265453b7a8..b8d53e1d5b2c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x <= y = 1; -} - +x <= y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-1.js index 54369df8c0de..fa2604884146 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 <= 2 = 1; -} - +1 <= 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-2.js index 2be30dcaa400..f26e7b89524a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-or-equal-to-shiftexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true <= false = 1; -} - +true <= false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-0.js index 3c9f2fe7d260..1304ecc8635f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x < y = 1; -} - +x < y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-1.js index d1b530e07ae1..96be4cbf5384 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 < 2 = 1; -} - +1 < 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-2.js index 54fbe32fa536..551aafcfa935 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-relationalexpression-less-than-shiftexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true < false = 1; -} - +true < false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-0.js index 046f60d180bc..8a39888ceb86 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x << y = 1; -} - +x << y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-1.js index ab81e037b1f5..d0b9aac2bad9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 << 2 = 1; -} - +1 << 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-2.js index c30e7db601c9..9b7511052698 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-left-additiveexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true << false = 1; -} - +true << false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-0.js index 2e32882ac1aa..ae29e98de0ba 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x >> y = 1; -} - +x >> y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-1.js index 8949b3ed7f56..d0a008639229 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 >> 2 = 1; -} - +1 >> 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-2.js index f8a8d9f0015a..8e21ce2514a2 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-bitwise-right-additiveexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true >> false = 1; -} - +true >> false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-0.js index a9b795900e10..d266bdff36cd 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x >>> y = 1; -} - +x >>> y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-1.js index f8f7a42828e4..cbf4cca44a12 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 >>> 2 = 1; -} - +1 >>> 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-2.js index 1618fcd80f09..54bf950ee400 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shiftexpression-unsigned-bitwise-right-additiveexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true >>> false = 1; -} - +true >>> false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-0.js index b50b8aa348b4..3ba11d625b68 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ? y : z) = 1; -} - +(x ? y : z) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-1.js index bc02024e1bfa..11b69bba48e2 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 ? 2 : 3) = 1; -} - +(1 ? 2 : 3) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-2.js index e474a48cc6b9..f0d3067cca2e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true ? false : true) = 1; -} - +(true ? false : true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-delete-unaryexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-delete-unaryexpression.js index 857cf03edf87..c7e1f9f06372 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-delete-unaryexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-delete-unaryexpression.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - delete x.y = 1; -} - +delete x.y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-0.js index 132032a0a95d..8a0485ba0e1b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - !x = 1; -} - +!x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-1.js index 4573a5128687..42f5b8f9543e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - !1 = 1; -} - +!1 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-2.js index 3e3b05e479da..94f4e88dc7b1 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-exclamation-unaryexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - !true = 1; -} - +!true = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-0.js index fc3ae6ac7d7b..ac195ce3af9c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - -x = 1; -} - +-x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-1.js index fa6557f9591d..f6e37a35e57d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - -1 = 1; -} - +-1 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-2.js index 0bd8d0cb60d2..60470125cd85 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-minus-unaryexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - -true = 1; -} - +-true = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-0.js index 467814708c65..beb9c8900af7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - +x = 1; -} - ++x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-1.js index ac8dcea64f03..fcc62936ac2f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - +1 = 1; -} - ++1 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-2.js index 87116946ba77..02e0e8a72abe 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-plus-unaryexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - +true = 1; -} - ++true = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-0.js index a1c6a8696374..8bb4fba1b358 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - ~x = 1; -} - +~x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-1.js index aa9253521843..2d7795f4193b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - ~1 = 1; -} - +~1 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-2.js index f5b708a1bf24..c1195b53caae 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-tilde-unaryexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - ~true = 1; -} - +~true = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-0.js index 50f0b8eab3cb..62f950c9b4e8 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - typeof x = 1; -} - +typeof x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-1.js index 4ec1741470b8..fc7db0282570 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - typeof 1 = 1; -} - +typeof 1 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-2.js index 92e58f500f33..e57f785fecb3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-typeof-unaryexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - typeof true = 1; -} - +typeof true = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-0.js index c8aab46130d9..beb038b68630 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - void x = 1; -} - +void x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-1.js index a413eca798ef..5912b41028eb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - void 1 = 1; -} - +void 1 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-2.js index c032526f9947..995ef8d1aa76 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-unaryexpression-void-unaryexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - void true = 1; -} - +void true = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-0.js index 77842b0534c1..b096cc5590f3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - x ** y = 1; -} - +x ** y = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-1.js index 821d97167a03..e2259e95e9ee 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - 1 ** 2 = 1; -} - +1 ** 2 = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-2.js index 4837b4d8fa55..3b4567028514 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-updateexpression-star-star-exponentiationexpression-2.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - true ** false = 1; -} - +true ** false = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-yieldexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-yieldexpression-0.js index 419ba62ca6d9..cf25897ad81b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-yieldexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-yieldexpression-0.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - yield x = 1; -} - +yield x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-yieldexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-yieldexpression-1.js index da1f613cefc0..f4d19bea26fb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/direct-yieldexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/direct-yieldexpression-1.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - yield * x = 1; -} - +yield * x = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-0.js index 7b83459b2d84..94f421eb0251 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x - y) = 1; -} - +(x - y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-1.js index 45d3219d00e2..685bde6bbeeb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 - 2) = 1; -} - +(1 - 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-2.js index 032242dcee60..e78757381c78 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-minus-multiplicativeexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true - false) = 1; -} - +(true - false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-0.js index b5c554cafe9f..2b3875f5e90a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x + y) = 1; -} - +(x + y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-1.js index 72c1403f88e6..e1cfc6b3f729 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 + 2) = 1; -} - +(1 + 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-2.js index 4b05ecfd30d6..9e231f7d9aed 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-additiveexpression-plus-multiplicativeexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true + false) = 1; -} - +(true + false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-0.js index 393220153ad1..96ba3369a251 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (() => {}) = 1; -} - +(() => {}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-1.js index 7926677891be..800504dccbb5 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (() => ({})) = 1; -} - +(() => ({})) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-2.js index 1450bdb72047..1d4be742dbbb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x => x)) = 1; -} - +((x => x)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-3.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-3.js index 4b6f91fdf81f..a9b566c765c1 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-3.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-3.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (((x) => x)) = 1; -} - +(((x) => x)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-4.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-4.js index 49a86c56fa74..bff81380212b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-4.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-4.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((() => 1)) = 1; -} - +((() => 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-5.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-5.js index dadbadc78efe..f022f6e75389 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-5.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-5.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((() => true)) = 1; -} - +((() => true)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-6.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-6.js index 104f71fe752b..a15c64fc743b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-6.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-arrowfunction-6.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((() => 1)) = 1; -} - +((() => 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-0.js index 512f00c25d5f..48d411ae355a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async () => {}) = 1; -} - +(async () => {}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-1.js index 062165bb4c79..7e59540a870c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async () => ({})) = 1; -} - +(async () => ({})) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-2.js index 160caeb19e34..7b3a1bfe34ea 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((async x => x)) = 1; -} - +((async x => x)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-3.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-3.js index 7b9ffce30db2..02958bb7dbe8 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-3.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-3.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((async (x) => x)) = 1; -} - +((async (x) => x)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-4.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-4.js index cd6bc64dbbf3..7627bc9cdfe7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-4.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-4.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((async () => 1)) = 1; -} - +((async () => 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-5.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-5.js index b61869e65143..8c8daacace01 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-5.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-5.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((async () => true)) = 1; -} - +((async () => true)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-6.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-6.js index d34aa1e00fe2..56aca576e0d5 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-6.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-asyncarrowfunction-6.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((async () => 1)) = 1; -} - +((async () => 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-0.js index 79b9a614f639..ff50fe4a9a47 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x & y) = 1; -} - +(x & y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-1.js index f44b002461f4..93b55a94dac6 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 & 2) = 1; -} - +(1 & 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-2.js index ec771420a7f5..d621316bd8ab 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseandexpression-bitwise-and-equalityexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true & false) = 1; -} - +(true & false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-0.js index e9e1c8e05743..c18626b16b52 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x | y) = 1; -} - +(x | y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-1.js index 66a6a8c0f802..f7c18340d9bc 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 | 2) = 1; -} - +(1 | 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-2.js index acf6fff9c7d0..1866e4b6575a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwiseorexpression-bitwise-or-bitwisexorexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true | false) = 1; -} - +(true | false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-0.js index a8fa0a3b794c..b09b707a691d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ^ y) = 1; -} - +(x ^ y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-1.js index cfaf587ff1e0..f13d6d5a0261 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 ^ 2) = 1; -} - +(1 ^ 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-2.js index b735065454c7..11f4341f5150 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-bitwisexorexpression-bitwise-xor-bitwiseandexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true ^ false) = 1; -} - +(true ^ false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-callexpression-arguments.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-callexpression-arguments.js index 6da32a75e681..194196750b92 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-callexpression-arguments.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-callexpression-arguments.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (f()) = 1; -} - +(f()) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-callexpression-templateliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-callexpression-templateliteral.js index 3a869c57d0a3..672e8872254b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-callexpression-templateliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-callexpression-templateliteral.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (f()``) = 1; -} - +(f()``) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-0.js index e9e66b0a696b..85bba8cc13b8 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ?? y) = 1; -} - +(x ?? y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-1.js index a1d082fd4036..135065be452e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 ?? 2) = 1; -} - +(1 ?? 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-2.js index b632dcd01ade..e4f6f1448c3a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-coalesceexpressionhead-coalesce-bitwiseorexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true ?? false) = 1; -} - +(true ?? false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-0.js index 026892bafa6e..b19c3e04e036 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x == y) = 1; -} - +(x == y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-1.js index 2ba89c2541b6..5b82bb5124d3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 == 2) = 1; -} - +(1 == 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-2.js index 25ae803604aa..5923d4ad4acc 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-equal-relationalexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true == false) = 1; -} - +(true == false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-0.js index 3d02e9d9bdf4..54f2955dad7b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x != y) = 1; -} - +(x != y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-1.js index 5b6b9e8e0829..bfe4a030aa1a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 != 2) = 1; -} - +(1 != 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-2.js index 297c2c19239a..aecdeddd119d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-abstract-not-equal-relationalexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true != false) = 1; -} - +(true != false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-0.js index 09ccfd231e7a..3b145874a458 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x == y) = 1; -} - +(x == y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-1.js index 98365f79dc16..627efc4a1268 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 == 2) = 1; -} - +(1 == 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-2.js index e8141d38e64a..25e0eef0acb3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-equal-relationalexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true == false) = 1; -} - +(true == false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-0.js index 2593b84b5eb2..2acd3bd3a579 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x !== y) = 1; -} - +(x !== y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-1.js index 3f3c3733c82d..4dce4a520655 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 !== 2) = 1; -} - +(1 !== 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-2.js index 730c8b188827..98f758b3fd4c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-equalityexpression-strict-not-equal-relationalexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true !== false) = 1; -} - +(true !== false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-0.js index 847ad70a0581..c6653c0d8ad0 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x, y = z)) = 1; -} - +((x, y = z)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-1.js index f1dc863a2bf8..2a40106ff06c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x, y = 1)) = 1; -} - +((x, y = 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-2.js index 1a7e74b8673d..e4b10c9bf68a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-expression-comma-assignmentexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x, y = true)) = 1; -} - +((x, y = true)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-identifierreference-arguments-strict-strict.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-identifierreference-arguments-strict-strict.js index 077dbf20d1ea..dccc3ac38290 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-identifierreference-arguments-strict-strict.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-identifierreference-arguments-strict-strict.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (arguments) = 1; -} - +(arguments) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-identifierreference-eval-strict-strict.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-identifierreference-eval-strict-strict.js index 986a3a3f50c3..c3f9aa703af3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-identifierreference-eval-strict-strict.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-identifierreference-eval-strict-strict.js @@ -18,7 +18,4 @@ info: | $DONOTEVALUATE(); -function _() { - (eval) = 1; -} - +(eval) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-import.meta.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-import.meta.js index 5ed675401abe..3b9bd6eb0087 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-import.meta.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-import.meta.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (import.meta) = 1; -} - +(import.meta) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-importcall.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-importcall.js index ce21141738b4..6bfedf14b302 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-importcall.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-importcall.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (import()) = 1; -} - +(import()) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-0.js index 90c826baa8e2..69ed85e46eea 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x = y)) = 1; -} - +((x = y)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-1.js index 079cd248ee9a..0d6cf6a5cc67 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x = 1)) = 1; -} - +((x = 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-2.js index 164a9b97d3f4..e983ebdfc188 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-assignment-assignmentexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x = true)) = 1; -} - +((x = true)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-0.js index b6fc0314e7bc..965893068b02 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x ??= y)) = 1; -} - +((x ??= y)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-1.js index 45e822d3552c..64fbc2b20028 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x ??= 1)) = 1; -} - +((x ??= 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-2.js index 1de242cf4583..473e60760e9c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-coalesce-assignment-assignmentexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x ??= true)) = 1; -} - +((x ??= true)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-0.js index 88718eba9f5f..3468fb6b9a72 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x &&= y)) = 1; -} - +((x &&= y)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-1.js index c617595d48ca..cc687f3a54b3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x &&= 1)) = 1; -} - +((x &&= 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-2.js index b1561036b388..e7e1e9a44351 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-and-assignment-assignmentexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x &&= true)) = 1; -} - +((x &&= true)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-0.js index 00ffcd13b47f..6cf570e90077 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x ||= y)) = 1; -} - +((x ||= y)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-1.js index 3f0bc76f7b65..bd374e10e54d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x ||= 1)) = 1; -} - +((x ||= 1)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-2.js index 95d896078164..fe2e00af288f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-logical-or-assignment-assignmentexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x ||= true)) = 1; -} - +((x ||= true)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-minus-minus.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-minus-minus.js index 89d4182a5b44..6d4693b21b85 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-minus-minus.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-minus-minus.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x--) = 1; -} - +(x--) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-plus-plus.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-plus-plus.js index 656556853d6d..94fc0b7834e7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-plus-plus.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-lefthandsideexpression-plus-plus.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x++) = 1; -} - +(x++) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-0.js index 7ae631514734..ae56b272dea5 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x && y) = 1; -} - +(x && y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-1.js index 27c237aa05d0..8f4ffcbb5a66 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 && 2) = 1; -} - +(1 && 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-2.js index 45d571e0250a..70dc2b1b2be9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalandexpression-logical-and-bitwiseorexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true && false) = 1; -} - +(true && false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-0.js index 4d51427ec34a..b816e1cab7d6 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x || y) = 1; -} - +(x || y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-1.js index 2c73e698c8c0..da75ec942f0d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 || 2) = 1; -} - +(1 || 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-2.js index b9fa247ad83c..cf261889447f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-logicalorexpression-logical-or-logicalandexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true || false) = 1; -} - +(true || false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-memberexpression-templateliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-memberexpression-templateliteral.js index ea015c00324c..673d4b953f92 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-memberexpression-templateliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-memberexpression-templateliteral.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (o.f()``) = 1; -} - +(o.f()``) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-minus-minus-unaryexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-minus-minus-unaryexpression.js index 0ae2982fb46a..66b07fcc1a34 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-minus-minus-unaryexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-minus-minus-unaryexpression.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (--x) = 1; -} - +(--x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-0.js index 5f69e27f6fc3..8f82be4f5f9d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x * y) = 1; -} - +(x * y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-1.js index 0dec7b67ab5a..645169d1dccd 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 * 2) = 1; -} - +(1 * 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-2.js index 32b84009e37e..59093029441b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true * false) = 1; -} - +(true * false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-3.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-3.js index a6d6cf36a5e6..5a16471849a4 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-3.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-3.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x / y) = 1; -} - +(x / y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-4.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-4.js index afff2165c79e..66177688b5b1 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-4.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-4.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 / 2) = 1; -} - +(1 / 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-5.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-5.js index 1cc93fb4c834..8ab4d4f87e7f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-5.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-multiplicativeexpression-multiplicativeoperator-exponentiationexpression-5.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true / false) = 1; -} - +(true / false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-new-memberexpression-arguments.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-new-memberexpression-arguments.js index 0d481d2f0920..f496a122334b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-new-memberexpression-arguments.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-new-memberexpression-arguments.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (new f()) = 1; -} - +(new f()) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-new-newexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-new-newexpression.js index 30fee42efde4..f15374cd2427 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-new-newexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-new-newexpression.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (new f) = 1; -} - +(new f) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-optionalexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-optionalexpression.js index 3c58711ef9d2..9ce49a883f64 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-optionalexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-optionalexpression.js @@ -22,7 +22,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x?.y) = 1; -} - +(x?.y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-plus-plus-unaryexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-plus-plus-unaryexpression.js index 8294e69aca7f..f383021fee7d 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-plus-plus-unaryexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-plus-plus-unaryexpression.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (++x) = 1; -} - +(++x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-asyncfunctionexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-asyncfunctionexpression.js index ba83d88d46cc..19860969c6b2 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-asyncfunctionexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-asyncfunctionexpression.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async function () {}) = 1; -} - +(async function () {}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-asyncgeneratorexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-asyncgeneratorexpression.js index d404cd3323fb..47627a8805a4 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-asyncgeneratorexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-asyncgeneratorexpression.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (async function () {}) = 1; -} - +(async function () {}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-classexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-classexpression.js index 26f2de85eb0e..3eb97ec5a2b7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-classexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-classexpression.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (class {}) = 1; -} - +(class {}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-functionexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-functionexpression.js index 81f729d2ebab..992a35b619fe 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-functionexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-functionexpression.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (function() {}) = 1; -} - +(function() {}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-generatorexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-generatorexpression.js index a0aeb20a7a5f..5aed2db1a36a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-generatorexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-generatorexpression.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (function * () {}) = 1; -} - +(function * () {}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-boolean.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-boolean.js index 74b41fb3fc8f..614c50d03642 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-boolean.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-boolean.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true) = 1; -} - +(true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-null.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-null.js index 4e6edb7b7259..f0254f552232 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-null.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-null.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (null) = 1; -} - +(null) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-numeric.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-numeric.js index 56339a1b9b93..e4cb9514bc85 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-numeric.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-numeric.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (0) = 1; -} - +(0) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-string.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-string.js index 536146a1cdc0..019f7b3d74c9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-string.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-literal-string.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - ('') = 1; -} - +('') = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-objectliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-objectliteral.js index 4156d12715d2..227be22bd78f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-objectliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-objectliteral.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - ({}) = 1; -} - +({}) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-regularexpressionliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-regularexpressionliteral.js index 3eb25b8f5544..5dee5676eb16 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-regularexpressionliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-regularexpressionliteral.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (/1/) = 1; -} - +(/1/) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-templateliteral.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-templateliteral.js index ef0eb7448991..1d6117099539 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-templateliteral.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-templateliteral.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (``) = 1; -} - +(``) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-this.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-this.js index bf0f6299ef3f..c36825468d0f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-this.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-this.js @@ -17,7 +17,4 @@ info: | $DONOTEVALUATE(); -function _() { - (this) = 1; -} - +(this) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-0.js index d5f2bc84ffd0..98321a09056b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x >= y) = 1; -} - +(x >= y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-1.js index c0a85eda759c..742c393ef1fb 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 >= 2) = 1; -} - +(1 >= 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-2.js index e4244693b71c..cab5a8221316 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-or-equal-to-shiftexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true >= false) = 1; -} - +(true >= false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-0.js index ca1088196a68..160d6eeff041 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x > y) = 1; -} - +(x > y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-1.js index fc467a35a077..db9f68c48cea 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 > 2) = 1; -} - +(1 > 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-2.js index d7a826788007..4c9ecf16f503 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-greater-than-shiftexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true > false) = 1; -} - +(true > false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-0.js index da0f99d0e6f4..d38c5556de13 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x in y) = 1; -} - +(x in y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-1.js index 3bccc23f17f8..0df0fa2a5559 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 in 2) = 1; -} - +(1 in 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-2.js index 13b734d65ae3..5471a52b4c17 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-in-shiftexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true in false) = 1; -} - +(true in false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-0.js index d5a0e7827114..70d4718ac08c 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x instanceof y) = 1; -} - +(x instanceof y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-1.js index 320e0b4fdc43..e80922ea44b1 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 instanceof 2) = 1; -} - +(1 instanceof 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-2.js index 62894b581897..531e5e1939a3 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-instanceof-shiftexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true instanceof false) = 1; -} - +(true instanceof false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-0.js index e93502fb2d9f..01982e5255ea 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x <= y) = 1; -} - +(x <= y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-1.js index ef469ab93e71..e28a31efe494 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 <= 2) = 1; -} - +(1 <= 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-2.js index 1d6a0050d611..64ad32cd972b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-or-equal-to-shiftexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true <= false) = 1; -} - +(true <= false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-0.js index 2361393b541b..67f46c919ac9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x < y) = 1; -} - +(x < y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-1.js index ebe420d417d1..ebcb8eae3d59 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 < 2) = 1; -} - +(1 < 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-2.js index 6c789e125711..c24389711f6e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-relationalexpression-less-than-shiftexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true < false) = 1; -} - +(true < false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-0.js index 6dd115cc5ac7..670bc75eb862 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x << y) = 1; -} - +(x << y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-1.js index fbf519fcf276..01881dcbd3ca 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 << 2) = 1; -} - +(1 << 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-2.js index cab175f6ad7e..1b399462c479 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-left-additiveexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true << false) = 1; -} - +(true << false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-0.js index b0c4b4c58d49..a16c7815553b 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x >> y) = 1; -} - +(x >> y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-1.js index c33bc28914f2..b04eaf95c383 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 >> 2) = 1; -} - +(1 >> 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-2.js index 620b5d33d377..eca24aecd1d0 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-bitwise-right-additiveexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true >> false) = 1; -} - +(true >> false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-0.js index d89defdfcee0..3d489ec61844 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x >>> y) = 1; -} - +(x >>> y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-1.js index 347eb49c109f..2ad51b637d5a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 >>> 2) = 1; -} - +(1 >>> 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-2.js index 669f42095326..772f4f2b4429 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shiftexpression-unsigned-bitwise-right-additiveexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true >>> false) = 1; -} - +(true >>> false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-0.js index d39391d2585c..9b69798a5868 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((x ? y : z)) = 1; -} - +((x ? y : z)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-1.js index 5640b4f72f28..d542d9aba17f 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((1 ? 2 : 3)) = 1; -} - +((1 ? 2 : 3)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-2.js index 9765bd2f21c7..acac9876c60a 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-shortcircuitexpression-question-assignmentexpression-else-assignmentexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - ((true ? false : true)) = 1; -} - +((true ? false : true)) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-delete-unaryexpression.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-delete-unaryexpression.js index b1080c4cef1d..9703bc530819 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-delete-unaryexpression.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-delete-unaryexpression.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (delete x.y) = 1; -} - +(delete x.y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-0.js index 6f31016b0456..a4863a7e54be 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (!x) = 1; -} - +(!x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-1.js index 23688b5e2f86..cec221dcafc0 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (!1) = 1; -} - +(!1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-2.js index 20eb231ed1ab..d48a33ca5b99 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-exclamation-unaryexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (!true) = 1; -} - +(!true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-0.js index 3c03f834c44a..ab9d29c9ff6e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (-x) = 1; -} - +(-x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-1.js index 87744c8bcfd6..348df171802e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (-1) = 1; -} - +(-1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-2.js index fd5da8eba1ae..b352f1e87099 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-minus-unaryexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (-true) = 1; -} - +(-true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-0.js index 4293e7d05bdc..9720bc0344f1 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (+x) = 1; -} - +(+x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-1.js index 1042834fca03..cf6d77193b49 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (+1) = 1; -} - +(+1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-2.js index cf524b11d175..eb2e841612b7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-plus-unaryexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (+true) = 1; -} - +(+true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-0.js index f6b5b07987e5..35f153ecb001 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (~x) = 1; -} - +(~x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-1.js index bae3109d1c57..69e2eacacba2 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (~1) = 1; -} - +(~1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-2.js index b90ef634c3a2..fef2d67bd5d9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-tilde-unaryexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (~true) = 1; -} - +(~true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-0.js index ab054812c498..7b8e41192c76 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (typeof x) = 1; -} - +(typeof x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-1.js index 48374774feca..82cbb0edc487 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (typeof 1) = 1; -} - +(typeof 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-2.js index 0498dc7334ed..89542f3aa55e 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-typeof-unaryexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (typeof true) = 1; -} - +(typeof true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-0.js index fc1ef9cf63aa..5d372ed97ccc 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (void x) = 1; -} - +(void x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-1.js index 0ac404cf0bb6..434ba8c9a3b9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (void 1) = 1; -} - +(void 1) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-2.js index fa392ed084a8..1638cc4690a9 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-unaryexpression-void-unaryexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (void true) = 1; -} - +(void true) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-0.js index f1e3e64ab556..ccbbe6321a78 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (x ** y) = 1; -} - +(x ** y) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-1.js index def98353c0a7..81d5c29de913 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (1 ** 2) = 1; -} - +(1 ** 2) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-2.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-2.js index b8a2eabc3028..b05ae97107f2 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-2.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-updateexpression-star-star-exponentiationexpression-2.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (true ** false) = 1; -} - +(true ** false) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-yieldexpression-0.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-yieldexpression-0.js index b1400598fc75..a8ff571c6ce7 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-yieldexpression-0.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-yieldexpression-0.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (yield x) = 1; -} - +(yield x) = 1; diff --git a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-yieldexpression-1.js b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-yieldexpression-1.js index 3514bd3fdbf6..e4d31ec786fd 100644 --- a/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-yieldexpression-1.js +++ b/js/src/tests/test262/language/expressions/assignmenttargettype/parenthesized-yieldexpression-1.js @@ -21,7 +21,4 @@ info: | $DONOTEVALUATE(); -function _() { - (yield * x) = 1; -} - +(yield * x) = 1; diff --git a/js/src/tests/test262/language/expressions/async-generator/named-yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/async-generator/named-yield-spread-arr-multiple.js index 50c960ea2ef3..ddc969ef1e05 100644 --- a/js/src/tests/test262/language/expressions/async-generator/named-yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/async-generator/named-yield-spread-arr-multiple.js @@ -42,7 +42,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/expressions/async-generator/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/async-generator/yield-spread-arr-multiple.js index f7251e425da1..4dbf565258b6 100644 --- a/js/src/tests/test262/language/expressions/async-generator/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/async-generator/yield-spread-arr-multiple.js @@ -42,7 +42,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/expressions/await/await-throws-rejections.js b/js/src/tests/test262/language/expressions/await/await-throws-rejections.js index 2e771b769982..3a8e6c668082 100644 --- a/js/src/tests/test262/language/expressions/await/await-throws-rejections.js +++ b/js/src/tests/test262/language/expressions/await/await-throws-rejections.js @@ -1,3 +1,4 @@ +// |reftest| async // Copyright 2016 Microsoft, Inc. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. @@ -6,6 +7,7 @@ author: Brian Terlson esid: pending description: > Await throws errors from rejected promises +flags: [async] ---*/ async function foo() { @@ -21,5 +23,4 @@ async function foo() { assert(caught); } - -reportCompare(0, 0); +foo().then($DONE, $DONE); diff --git a/js/src/tests/test262/language/expressions/call/spread-obj-spread-order.js b/js/src/tests/test262/language/expressions/call/spread-obj-spread-order.js index eed2516331f1..e0136c6593e6 100644 --- a/js/src/tests/test262/language/expressions/call/spread-obj-spread-order.js +++ b/js/src/tests/test262/language/expressions/call/spread-obj-spread-order.js @@ -40,7 +40,7 @@ Object.defineProperty(o, Symbol('foo'), { get: () => { calls.push("Symbol(foo)") var callCount = 0; (function(obj) { - assert(compareArray(calls, [1, 'z', 'a', "Symbol(foo)"])); + assert.compareArray(calls, [1, 'z', 'a', "Symbol(foo)"]); assert.sameValue(Object.keys(obj).length, 3); callCount += 1; }({...o})); diff --git a/js/src/tests/test262/language/expressions/call/tco-cross-realm-class-construct.js b/js/src/tests/test262/language/expressions/call/tco-cross-realm-class-construct.js deleted file mode 100644 index 99abda9b34a0..000000000000 --- a/js/src/tests/test262/language/expressions/call/tco-cross-realm-class-construct.js +++ /dev/null @@ -1,42 +0,0 @@ -// |reftest| skip -- tail-call-optimization is not supported -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-function-calls-runtime-semantics-evaluation -description: > - Check TypeError is thrown from correct realm with tco-call to class constructor from derived - class [[Construct]] invocation. -info: | - 12.3.4.3 Runtime Semantics: EvaluateDirectCall( func, thisValue, arguments, tailPosition ) - ... - 4. If tailPosition is true, perform PrepareForTailCall(). - 5. Let result be Call(func, thisValue, argList). - 6. Assert: If tailPosition is true, the above call will not return here, but instead evaluation will continue as if the following return has already occurred. - 7. Assert: If result is not an abrupt completion, then Type(result) is an ECMAScript language type. - 8. Return result. - - 9.2.1 [[Call]] ( thisArgument, argumentsList) - ... - 2. If F.[[FunctionKind]] is "classConstructor", throw a TypeError exception. - 3. Let callerContext be the running execution context. - 4. Let calleeContext be PrepareForOrdinaryCall(F, undefined). - 5. Assert: calleeContext is now the running execution context. - ... - -features: [tail-call-optimization, class, cross-realm] ----*/ - -// - The class constructor call is in a valid tail-call position, which means PrepareForTailCall is performed. -// - The function call returns from `otherRealm` and proceeds the tail-call in this realm. -// - Calling the class constructor throws a TypeError from the current realm, that means this realm and not `otherRealm`. -var code = "(class { constructor() { return (class {})(); } });"; - -var otherRealm = $262.createRealm(); -var tco = otherRealm.evalScript(code); - -assert.throws(TypeError, function() { - new tco(); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/call/tco-cross-realm-class-derived-construct.js b/js/src/tests/test262/language/expressions/call/tco-cross-realm-class-derived-construct.js deleted file mode 100644 index 78fbd194921b..000000000000 --- a/js/src/tests/test262/language/expressions/call/tco-cross-realm-class-derived-construct.js +++ /dev/null @@ -1,42 +0,0 @@ -// |reftest| skip -- tail-call-optimization is not supported -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-function-calls-runtime-semantics-evaluation -description: > - Check TypeError is thrown from correct realm with tco-call to class constructor from - class [[Construct]] invocation. -info: | - 12.3.4.3 Runtime Semantics: EvaluateDirectCall( func, thisValue, arguments, tailPosition ) - ... - 4. If tailPosition is true, perform PrepareForTailCall(). - 5. Let result be Call(func, thisValue, argList). - 6. Assert: If tailPosition is true, the above call will not return here, but instead evaluation will continue as if the following return has already occurred. - 7. Assert: If result is not an abrupt completion, then Type(result) is an ECMAScript language type. - 8. Return result. - - 9.2.1 [[Call]] ( thisArgument, argumentsList) - ... - 2. If F.[[FunctionKind]] is "classConstructor", throw a TypeError exception. - 3. Let callerContext be the running execution context. - 4. Let calleeContext be PrepareForOrdinaryCall(F, undefined). - 5. Assert: calleeContext is now the running execution context. - ... - -features: [tail-call-optimization, class, cross-realm] ----*/ - -// - The class constructor call is in a valid tail-call position, which means PrepareForTailCall is performed. -// - The function call returns from `otherRealm` and proceeds the tail-call in this realm. -// - Calling the class constructor throws a TypeError from the current realm, that means this realm and not `otherRealm`. -var code = "(class extends Object { constructor() { return (class {})(); } });"; - -var otherRealm = $262.createRealm(); -var tco = otherRealm.evalScript(code); - -assert.throws(TypeError, function() { - new tco(); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/call/tco-cross-realm-fun-call.js b/js/src/tests/test262/language/expressions/call/tco-cross-realm-fun-call.js deleted file mode 100644 index 3429c8496f1a..000000000000 --- a/js/src/tests/test262/language/expressions/call/tco-cross-realm-fun-call.js +++ /dev/null @@ -1,41 +0,0 @@ -// |reftest| skip -- tail-call-optimization is not supported -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-function-calls-runtime-semantics-evaluation -description: > - Check TypeError is thrown from correct realm with tco-call to class constructor from [[Call]] invocation. -info: | - 12.3.4.3 Runtime Semantics: EvaluateDirectCall( func, thisValue, arguments, tailPosition ) - ... - 4. If tailPosition is true, perform PrepareForTailCall(). - 5. Let result be Call(func, thisValue, argList). - 6. Assert: If tailPosition is true, the above call will not return here, but instead evaluation will continue as if the following return has already occurred. - 7. Assert: If result is not an abrupt completion, then Type(result) is an ECMAScript language type. - 8. Return result. - - 9.2.1 [[Call]] ( thisArgument, argumentsList) - ... - 2. If F.[[FunctionKind]] is "classConstructor", throw a TypeError exception. - 3. Let callerContext be the running execution context. - 4. Let calleeContext be PrepareForOrdinaryCall(F, undefined). - 5. Assert: calleeContext is now the running execution context. - ... - -features: [tail-call-optimization, class, cross-realm] ----*/ - -// - The class constructor call is in a valid tail-call position, which means PrepareForTailCall is performed. -// - The function call returns from `otherRealm` and proceeds the tail-call in this realm. -// - Calling the class constructor throws a TypeError from the current realm, that means this realm and not `otherRealm`. -var code = "'use strict'; (function() { return (class {})(); });"; - -var otherRealm = $262.createRealm(); -var tco = otherRealm.evalScript(code); - -assert.throws(TypeError, function() { - tco(); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/call/tco-cross-realm-fun-construct.js b/js/src/tests/test262/language/expressions/call/tco-cross-realm-fun-construct.js deleted file mode 100644 index e270c8078877..000000000000 --- a/js/src/tests/test262/language/expressions/call/tco-cross-realm-fun-construct.js +++ /dev/null @@ -1,41 +0,0 @@ -// |reftest| skip -- tail-call-optimization is not supported -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-function-calls-runtime-semantics-evaluation -description: > - Check TypeError is thrown from correct realm with tco-call to class constructor from [[Construct]] invocation. -info: | - 12.3.4.3 Runtime Semantics: EvaluateDirectCall( func, thisValue, arguments, tailPosition ) - ... - 4. If tailPosition is true, perform PrepareForTailCall(). - 5. Let result be Call(func, thisValue, argList). - 6. Assert: If tailPosition is true, the above call will not return here, but instead evaluation will continue as if the following return has already occurred. - 7. Assert: If result is not an abrupt completion, then Type(result) is an ECMAScript language type. - 8. Return result. - - 9.2.1 [[Call]] ( thisArgument, argumentsList) - ... - 2. If F.[[FunctionKind]] is "classConstructor", throw a TypeError exception. - 3. Let callerContext be the running execution context. - 4. Let calleeContext be PrepareForOrdinaryCall(F, undefined). - 5. Assert: calleeContext is now the running execution context. - ... - -features: [tail-call-optimization, class, cross-realm] ----*/ - -// - The class constructor call is in a valid tail-call position, which means PrepareForTailCall is performed. -// - The function call returns from `otherRealm` and proceeds the tail-call in this realm. -// - Calling the class constructor throws a TypeError from the current realm, that means this realm and not `otherRealm`. -var code = "'use strict'; (function() { return (class {})(); });"; - -var otherRealm = $262.createRealm(); -var tco = otherRealm.evalScript(code); - -assert.throws(TypeError, function() { - new tco(); -}); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/class/async-gen-method-static/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/class/async-gen-method-static/yield-spread-arr-multiple.js index f367ee6910eb..5b3687ddad5c 100644 --- a/js/src/tests/test262/language/expressions/class/async-gen-method-static/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/class/async-gen-method-static/yield-spread-arr-multiple.js @@ -49,7 +49,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/expressions/class/async-gen-method/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/class/async-gen-method/yield-spread-arr-multiple.js index af56719c7cbc..142075c441c3 100644 --- a/js/src/tests/test262/language/expressions/class/async-gen-method/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/class/async-gen-method/yield-spread-arr-multiple.js @@ -49,7 +49,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/expressions/class/cpn-class-expr-accessors-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/expressions/class/cpn-class-expr-accessors-computed-property-name-from-yield-expression.js index 20c04fedbaed..16f20273dd7d 100644 --- a/js/src/tests/test262/language/expressions/class/cpn-class-expr-accessors-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/expressions/class/cpn-class-expr-accessors-computed-property-name-from-yield-expression.js @@ -92,5 +92,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/class/cpn-class-expr-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/expressions/class/cpn-class-expr-computed-property-name-from-yield-expression.js index 2a747547a1ea..95a9f1a3b0f8 100644 --- a/js/src/tests/test262/language/expressions/class/cpn-class-expr-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/expressions/class/cpn-class-expr-computed-property-name-from-yield-expression.js @@ -65,5 +65,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/class/cpn-class-expr-fields-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/expressions/class/cpn-class-expr-fields-computed-property-name-from-yield-expression.js index 1532f519a839..303614d03df0 100644 --- a/js/src/tests/test262/language/expressions/class/cpn-class-expr-fields-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/expressions/class/cpn-class-expr-fields-computed-property-name-from-yield-expression.js @@ -62,5 +62,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/class/cpn-class-expr-fields-methods-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/expressions/class/cpn-class-expr-fields-methods-computed-property-name-from-yield-expression.js index c7c1300f0e2b..2c2e82bf7ec1 100644 --- a/js/src/tests/test262/language/expressions/class/cpn-class-expr-fields-methods-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/expressions/class/cpn-class-expr-fields-methods-computed-property-name-from-yield-expression.js @@ -66,5 +66,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/class/elements/async-gen-private-method-static/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/class/elements/async-gen-private-method-static/yield-spread-arr-multiple.js index 821d7135dd1b..f147ef6e6fc3 100644 --- a/js/src/tests/test262/language/expressions/class/elements/async-gen-private-method-static/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/class/elements/async-gen-private-method-static/yield-spread-arr-multiple.js @@ -54,7 +54,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/expressions/class/elements/async-gen-private-method/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/class/elements/async-gen-private-method/yield-spread-arr-multiple.js index 3aea4791b530..b19b7eb86038 100644 --- a/js/src/tests/test262/language/expressions/class/elements/async-gen-private-method/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/class/elements/async-gen-private-method/yield-spread-arr-multiple.js @@ -57,7 +57,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/expressions/class/elements/gen-private-method-static/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/class/elements/gen-private-method-static/yield-spread-arr-multiple.js index 1241e4cbc673..801dbef0bb14 100644 --- a/js/src/tests/test262/language/expressions/class/elements/gen-private-method-static/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/class/elements/gen-private-method-static/yield-spread-arr-multiple.js @@ -49,7 +49,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/expressions/class/elements/gen-private-method/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/class/elements/gen-private-method/yield-spread-arr-multiple.js index 75187ca71605..8a1c3504f138 100644 --- a/js/src/tests/test262/language/expressions/class/elements/gen-private-method/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/class/elements/gen-private-method/yield-spread-arr-multiple.js @@ -52,7 +52,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/expressions/class/elements/redeclaration-symbol.js b/js/src/tests/test262/language/expressions/class/elements/redeclaration-symbol.js index 76543d77662e..a123ec3ccec3 100644 --- a/js/src/tests/test262/language/expressions/class/elements/redeclaration-symbol.js +++ b/js/src/tests/test262/language/expressions/class/elements/redeclaration-symbol.js @@ -52,6 +52,6 @@ verifyProperty(c, y, { configurable: true }); -assert(compareArray(x, ["a", "b", "c"])); +assert.compareArray(x, ["a", "b", "c"]); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/class/elements/redeclaration.js b/js/src/tests/test262/language/expressions/class/elements/redeclaration.js index 14352deff3eb..f3509ee8364a 100644 --- a/js/src/tests/test262/language/expressions/class/elements/redeclaration.js +++ b/js/src/tests/test262/language/expressions/class/elements/redeclaration.js @@ -52,6 +52,6 @@ verifyProperty(c, "y", { configurable: true }); -assert(compareArray(x, ["a", "b", "c", "d"])); +assert.compareArray(x, ["a", "b", "c", "d"]); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/class/gen-method-static/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/class/gen-method-static/yield-spread-arr-multiple.js index eaed1a7f806f..52aa870694a9 100644 --- a/js/src/tests/test262/language/expressions/class/gen-method-static/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/class/gen-method-static/yield-spread-arr-multiple.js @@ -44,7 +44,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/expressions/class/gen-method/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/class/gen-method/yield-spread-arr-multiple.js index d1ee8b09e07e..6e1fa9a34ec2 100644 --- a/js/src/tests/test262/language/expressions/class/gen-method/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/class/gen-method/yield-spread-arr-multiple.js @@ -44,7 +44,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-add.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-add.js new file mode 100644 index 000000000000..0adbe1dc311a --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-add.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/add.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound addition assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 1; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field += 2; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 3, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 3, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitand.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitand.js new file mode 100644 index 000000000000..c9683a4b0de1 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitand.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitand.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound bitwise-and assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 0b0101; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field &= 0b1010; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b0000, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 0b0000, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitor.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitor.js new file mode 100644 index 000000000000..b14e2bb21773 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitor.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitor.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound bitwise-or assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 0b0101; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field |= 0b1010; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b1111, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 0b1111, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitxor.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitxor.js new file mode 100644 index 000000000000..28d203b234c8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-bitxor.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitxor.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound bitwise-xor assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 0x1111; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field ^= 0x1010; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0x0101, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 0x0101, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-div.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-div.js new file mode 100644 index 000000000000..99eb2feda50e --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-div.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/div.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound division assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 1; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field /= 2; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0.5, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 0.5, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-exp.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-exp.js new file mode 100644 index 000000000000..12ea34b2e389 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-exp.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/exp.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound exponentiation assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 10; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field **= 3; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1000, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 1000, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-lshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-lshift.js new file mode 100644 index 000000000000..d65158443966 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-lshift.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/lshift.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound left-shift assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 0b0110; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field <<= 4; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b01100000, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 0b01100000, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-mod.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-mod.js new file mode 100644 index 000000000000..1b54a87119d2 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-mod.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/mod.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound modulo assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 3; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field %= 2; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 1, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-mult.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-mult.js new file mode 100644 index 000000000000..788535e82863 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-mult.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/mult.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound multiplication assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 2; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field *= 3; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 6, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 6, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-rshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-rshift.js new file mode 100644 index 000000000000..9f5720e5766b --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-rshift.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/rshift.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound right-shift assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 0b1100; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field >>>= 2; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b0011, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 0b0011, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-srshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-srshift.js new file mode 100644 index 000000000000..29ee0aa6a155 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-srshift.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/srshift.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound signed-right-shift assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 0b1100; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field >>= 2; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b0011, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 0b0011, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-sub.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-sub.js new file mode 100644 index 000000000000..43269fb79751 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-accessor-property-sub.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/sub.case +// - src/compound-assignment-private/default/getter-setter.template +/*--- +description: Compound subtraction assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + +---*/ + + +class C { + #setterCalledWith; + get #field() { + return 3; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field -= 2; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 1, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-add.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-add.js new file mode 100644 index 000000000000..da3f639be3e3 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-add.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/add.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound addition assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 1; + compoundAssignment() { + return this.#field += 2; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 3, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 3, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitand.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitand.js new file mode 100644 index 000000000000..5c2b4747a2e8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitand.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitand.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound bitwise-and assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 0b0101; + compoundAssignment() { + return this.#field &= 0b1010; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b0000, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 0b0000, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitor.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitor.js new file mode 100644 index 000000000000..653c0cff81c9 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitor.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitor.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound bitwise-or assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 0b0101; + compoundAssignment() { + return this.#field |= 0b1010; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b1111, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 0b1111, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitxor.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitxor.js new file mode 100644 index 000000000000..499df6df355a --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-bitxor.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitxor.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound bitwise-xor assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 0x1111; + compoundAssignment() { + return this.#field ^= 0x1010; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0x0101, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 0x0101, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-div.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-div.js new file mode 100644 index 000000000000..2906c7dddb27 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-div.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/div.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound division assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 1; + compoundAssignment() { + return this.#field /= 2; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0.5, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 0.5, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-exp.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-exp.js new file mode 100644 index 000000000000..87b83fa4626d --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-exp.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/exp.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound exponentiation assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 10; + compoundAssignment() { + return this.#field **= 3; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1000, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 1000, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-lshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-lshift.js new file mode 100644 index 000000000000..7f1730963558 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-lshift.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/lshift.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound left-shift assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 0b0110; + compoundAssignment() { + return this.#field <<= 4; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b01100000, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 0b01100000, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-mod.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-mod.js new file mode 100644 index 000000000000..8104ea3b7686 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-mod.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/mod.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound modulo assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 3; + compoundAssignment() { + return this.#field %= 2; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 1, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-mult.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-mult.js new file mode 100644 index 000000000000..731a259be90a --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-mult.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/mult.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound multiplication assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 2; + compoundAssignment() { + return this.#field *= 3; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 6, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 6, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-rshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-rshift.js new file mode 100644 index 000000000000..3969e09d86e8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-rshift.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/rshift.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound right-shift assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 0b1100; + compoundAssignment() { + return this.#field >>>= 2; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b0011, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 0b0011, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-srshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-srshift.js new file mode 100644 index 000000000000..ac5f3c8d0e86 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-srshift.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/srshift.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound signed-right-shift assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 0b1100; + compoundAssignment() { + return this.#field >>= 2; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 0b0011, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 0b0011, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-sub.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-sub.js new file mode 100644 index 000000000000..1d6d12de8cd3 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-data-property-sub.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/sub.case +// - src/compound-assignment-private/default/data-property.template +/*--- +description: Compound subtraction assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + +---*/ + + +class C { + #field = 3; + compoundAssignment() { + return this.#field -= 2; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 1, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-add.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-add.js new file mode 100644 index 000000000000..bc4584acf740 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-add.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/add.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound addition assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod += 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitand.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitand.js new file mode 100644 index 000000000000..88d4ba9fd248 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitand.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitand.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound bitwise-and assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod &= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitor.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitor.js new file mode 100644 index 000000000000..2b184c370e4d --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitor.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitor.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound bitwise-or assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod |= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitxor.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitxor.js new file mode 100644 index 000000000000..54a8597e5479 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-bitxor.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitxor.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound bitwise-xor assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod ^= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-div.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-div.js new file mode 100644 index 000000000000..af4370bba5d4 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-div.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/div.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound division assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod /= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-exp.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-exp.js new file mode 100644 index 000000000000..4eb7578fcf90 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-exp.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/exp.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound exponentiation assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod **= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-lshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-lshift.js new file mode 100644 index 000000000000..11af1cbb57f7 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-lshift.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/lshift.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound left-shift assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod <<= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-mod.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-mod.js new file mode 100644 index 000000000000..26e5d0b8d2ba --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-mod.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/mod.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound modulo assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod %= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-mult.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-mult.js new file mode 100644 index 000000000000..0edfcd0f7d67 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-mult.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/mult.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound multiplication assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod *= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-rshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-rshift.js new file mode 100644 index 000000000000..ba0727fb07a8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-rshift.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/rshift.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound right-shift assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod >>>= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-srshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-srshift.js new file mode 100644 index 000000000000..f7a5df37bd1f --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-srshift.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/srshift.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound signed-right-shift assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod >>= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-sub.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-sub.js new file mode 100644 index 000000000000..5f473bd99bb4 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-method-sub.js @@ -0,0 +1,50 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/sub.case +// - src/compound-assignment-private/default/method.template +/*--- +description: Compound subtraction assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod -= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-add.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-add.js new file mode 100644 index 000000000000..4bedca0b2520 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-add.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/add.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound addition assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field += 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitand.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitand.js new file mode 100644 index 000000000000..54c16908a652 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitand.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitand.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound bitwise-and assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field &= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitor.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitor.js new file mode 100644 index 000000000000..ab78b7df3793 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitor.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitor.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound bitwise-or assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field |= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitxor.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitxor.js new file mode 100644 index 000000000000..66e8cdb06198 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-bitxor.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/bitxor.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound bitwise-xor assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field ^= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-div.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-div.js new file mode 100644 index 000000000000..1378f4870e6b --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-div.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/div.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound division assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field /= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-exp.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-exp.js new file mode 100644 index 000000000000..912c7e48bc9a --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-exp.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/exp.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound exponentiation assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field **= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-lshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-lshift.js new file mode 100644 index 000000000000..c1fb6a728494 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-lshift.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/lshift.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound left-shift assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field <<= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-mod.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-mod.js new file mode 100644 index 000000000000..e1c2491bfc05 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-mod.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/mod.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound modulo assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field %= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-mult.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-mult.js new file mode 100644 index 000000000000..b611243ecb62 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-mult.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/mult.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound multiplication assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field *= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-rshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-rshift.js new file mode 100644 index 000000000000..5c969340f762 --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-rshift.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/rshift.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound right-shift assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field >>>= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-srshift.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-srshift.js new file mode 100644 index 000000000000..ac393d51a49a --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-srshift.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/srshift.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound signed-right-shift assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field >>= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-sub.js b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-sub.js new file mode 100644 index 000000000000..20067bd51f9f --- /dev/null +++ b/js/src/tests/test262/language/expressions/compound-assignment/left-hand-side-private-reference-readonly-accessor-property-sub.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/compound-assignment-private/sub.case +// - src/compound-assignment-private/default/getter.template +/*--- +description: Compound subtraction assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private] +flags: [generated] +info: | + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + ... + 7. Let _r_ be ApplyStringOrNumericBinaryOperator(_lval_, _opText_, _rval_). + 8. Perform ? PutValue(_lref_, _r_). + 9. Return _r_. + + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + +---*/ + + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field -= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/delete/11.4.1-4.a-11.js b/js/src/tests/test262/language/expressions/delete/11.4.1-4.a-11.js index 420ba93379a1..83304245cc1e 100644 --- a/js/src/tests/test262/language/expressions/delete/11.4.1-4.a-11.js +++ b/js/src/tests/test262/language/expressions/delete/11.4.1-4.a-11.js @@ -13,9 +13,6 @@ flags: [noStrict] ---*/ (function() { - function foo(a, b) { - return delete arguments.callee; - } var d = delete arguments.callee; assert.sameValue(d, true, 'd'); diff --git a/js/src/tests/test262/language/expressions/division/S11.5.2_A4_T8.js b/js/src/tests/test262/language/expressions/division/S11.5.2_A4_T8.js index c31836c6ae5f..899de572adf7 100644 --- a/js/src/tests/test262/language/expressions/division/S11.5.2_A4_T8.js +++ b/js/src/tests/test262/language/expressions/division/S11.5.2_A4_T8.js @@ -33,8 +33,8 @@ if (-0 / -1 !== +0) { if (+0 / 1 !== +0) { throw new Test262Error('#3.1: +0 / 1 === 0. Actual: ' + (+0 / 1)); } else { - if (1 / (+0 / -1) !== Number.NEGATIVE_INFINITY) { - throw new Test262Error('#3.2: +0 / -1 === + 0. Actual: -0'); + if (1 / (+0 / 1) !== Number.POSITIVE_INFINITY) { + throw new Test262Error('#3.2: +0 / 1 === + 0. Actual: -0'); } } diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-arrow-assignment-expression-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-arrow-assignment-expression-eval-script-code-host-resolves-module-code.js index 2534f6a9e911..1ed49170be81 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-arrow-assignment-expression-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-arrow-assignment-expression-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-arrow-assign-expr.template /*--- -description: import() from a ascript code can load a file with module code (nested arrow) +description: import() from a script code can load a file with module code (nested arrow) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-arrow-import-then-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-arrow-import-then-eval-script-code-host-resolves-module-code.js index 14ad83c884b0..3a8ce9e1b5ec 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-arrow-import-then-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-arrow-import-then-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-arrow.template /*--- -description: import() from a ascript code can load a file with module code (nested arrow) +description: import() from a script code can load a file with module code (nested arrow) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-arrow-function-await-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-arrow-function-await-eval-script-code-host-resolves-module-code.js index 5632cd774ce1..25de6fab42c2 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-arrow-function-await-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-arrow-function-await-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-async-arrow-fn-await.template /*--- -description: import() from a ascript code can load a file with module code (nested in async arrow function, awaited) +description: import() from a script code can load a file with module code (nested in async arrow function, awaited) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-arrow-function-return-await-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-arrow-function-return-await-eval-script-code-host-resolves-module-code.js index e8baa8da551f..db72fe4aa315 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-arrow-function-return-await-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-arrow-function-return-await-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-async-arrow-fn-return-await.template /*--- -description: import() from a ascript code can load a file with module code (nested in async arrow function, returned) +description: import() from a script code can load a file with module code (nested in async arrow function, returned) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-await-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-await-eval-script-code-host-resolves-module-code.js index 89d2fd6db844..372fb5433748 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-await-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-await-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-async-function-await.template /*--- -description: import() from a ascript code can load a file with module code (nested in async function, awaited) +description: import() from a script code can load a file with module code (nested in async function, awaited) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-eval-script-code-host-resolves-module-code.js index 9d30c1cb0381..184e0255053d 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-async-function.template /*--- -description: import() from a ascript code can load a file with module code (nested in async function) +description: import() from a script code can load a file with module code (nested in async function) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-return-await-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-return-await-eval-script-code-host-resolves-module-code.js index e2147c9ae195..d081e9c34e75 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-return-await-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-function-return-await-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-async-function-return-await.template /*--- -description: import() from a ascript code can load a file with module code (nested in async function, returns awaited) +description: import() from a script code can load a file with module code (nested in async function, returns awaited) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-gen-await-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-gen-await-eval-script-code-host-resolves-module-code.js index dfa2f574e7e2..7ee84dc436f2 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-gen-await-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-gen-await-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-async-generator-await.template /*--- -description: import() from a ascript code can load a file with module code (nested in async generator, awaited) +description: import() from a script code can load a file with module code (nested in async generator, awaited) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import, async-iteration] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-gen-return-await-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-gen-return-await-eval-script-code-host-resolves-module-code.js index 4a41264894be..e59a5c197374 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-gen-return-await-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-async-gen-return-await-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-async-generator-return-await.template /*--- -description: import() from a ascript code can load a file with module code (nested in async generator, returns awaited) +description: import() from a script code can load a file with module code (nested in async generator, returns awaited) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import, async-iteration] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-block-import-then-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-block-import-then-eval-script-code-host-resolves-module-code.js index da98786f8e45..ed0e01e870aa 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-block-import-then-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-block-import-then-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-block.template /*--- -description: import() from a ascript code can load a file with module code (nested block) +description: import() from a script code can load a file with module code (nested block) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-do-while-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-do-while-eval-script-code-host-resolves-module-code.js index 500c2b90179f..40d355791117 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-do-while-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-do-while-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-do-while.template /*--- -description: import() from a ascript code can load a file with module code (nested do while syntax) +description: import() from a script code can load a file with module code (nested do while syntax) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-else-import-then-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-else-import-then-eval-script-code-host-resolves-module-code.js index 5ad0d98a5bf3..0f77bf936e20 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-else-import-then-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-else-import-then-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-else.template /*--- -description: import() from a ascript code can load a file with module code (nested else) +description: import() from a script code can load a file with module code (nested else) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-function-import-then-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-function-import-then-eval-script-code-host-resolves-module-code.js index 2ddbb4c0b438..b2ef5536fb72 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-function-import-then-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-function-import-then-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-function.template /*--- -description: import() from a ascript code can load a file with module code (nested function) +description: import() from a script code can load a file with module code (nested function) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-if-braceless-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-if-braceless-eval-script-code-host-resolves-module-code.js index b49c181739f9..de8ca0aa1fb1 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-if-braceless-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-if-braceless-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-if-braceless.template /*--- -description: import() from a ascript code can load a file with module code (nested if syntax) +description: import() from a script code can load a file with module code (nested if syntax) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-if-import-then-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-if-import-then-eval-script-code-host-resolves-module-code.js index 954f6e5f08a5..bf587991d51f 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-if-import-then-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-if-import-then-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-if.template /*--- -description: import() from a ascript code can load a file with module code (nested if) +description: import() from a script code can load a file with module code (nested if) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-while-import-then-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-while-import-then-eval-script-code-host-resolves-module-code.js index 6aed400bdcfe..784b590666d5 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-while-import-then-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/nested-while-import-then-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-while.template /*--- -description: import() from a ascript code can load a file with module code (nested while) +description: import() from a script code can load a file with module code (nested while) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/syntax-nested-block-labeled-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/syntax-nested-block-labeled-eval-script-code-host-resolves-module-code.js index b7b36cec4c74..0ee09bea19df 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/syntax-nested-block-labeled-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/syntax-nested-block-labeled-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/nested-block-labeled.template /*--- -description: import() from a ascript code can load a file with module code (nested block syntax) +description: import() from a script code can load a file with module code (nested block syntax) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/dynamic-import/usage/top-level-import-then-eval-script-code-host-resolves-module-code.js b/js/src/tests/test262/language/expressions/dynamic-import/usage/top-level-import-then-eval-script-code-host-resolves-module-code.js index 78c530077ecc..d9eb3d40106e 100644 --- a/js/src/tests/test262/language/expressions/dynamic-import/usage/top-level-import-then-eval-script-code-host-resolves-module-code.js +++ b/js/src/tests/test262/language/expressions/dynamic-import/usage/top-level-import-then-eval-script-code-host-resolves-module-code.js @@ -3,7 +3,7 @@ // - src/dynamic-import/eval-script-code-host-resolves-module-code.case // - src/dynamic-import/default/top-level.template /*--- -description: import() from a ascript code can load a file with module code (top level) +description: import() from a script code can load a file with module code (top level) esid: sec-import-call-runtime-semantics-evaluation features: [dynamic-import] flags: [generated, async] diff --git a/js/src/tests/test262/language/expressions/exponentiation/applying-the-exp-operator_A15.js b/js/src/tests/test262/language/expressions/exponentiation/applying-the-exp-operator_A15.js index d9d1631ff325..9296481935f3 100644 --- a/js/src/tests/test262/language/expressions/exponentiation/applying-the-exp-operator_A15.js +++ b/js/src/tests/test262/language/expressions/exponentiation/applying-the-exp-operator_A15.js @@ -14,9 +14,7 @@ exponents[1] = -111; exponents[0] = -111111; for (var i = 0; i < exponents.length; i++) { - if ((base ** exponents[i]) !== -0) { - throw new Test262Error("(" + base + " ** " + exponents[i] + ") !== -0"); - } + assert.sameValue(base ** exponents[i], -0, base + " ** " + exponents[i]); } reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/exponentiation/applying-the-exp-operator_A19.js b/js/src/tests/test262/language/expressions/exponentiation/applying-the-exp-operator_A19.js index 5eb274580fd4..372870802902 100644 --- a/js/src/tests/test262/language/expressions/exponentiation/applying-the-exp-operator_A19.js +++ b/js/src/tests/test262/language/expressions/exponentiation/applying-the-exp-operator_A19.js @@ -14,9 +14,7 @@ exponents[1] = 111; exponents[2] = 111111; for (var i = 0; i < exponents.length; i++) { - if ((base ** exponents[i]) !== -0) { - throw new Test262Error("(" + base + " ** " + exponents[i] + ") !== -0"); - } + assert.sameValue(base ** exponents[i], -0, base + " ** " + exponents[i]); } reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/generators/named-yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/generators/named-yield-spread-arr-multiple.js index 3f2b0a44eaad..2b3bdbaa4d94 100644 --- a/js/src/tests/test262/language/expressions/generators/named-yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/generators/named-yield-spread-arr-multiple.js @@ -36,7 +36,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/expressions/generators/yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/generators/yield-spread-arr-multiple.js index 48c60690ea04..6e0f57d47c66 100644 --- a/js/src/tests/test262/language/expressions/generators/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/generators/yield-spread-arr-multiple.js @@ -36,7 +36,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-and.js new file mode 100644 index 000000000000..600b57571967 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-and.js @@ -0,0 +1,63 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/getter-setter.template +/*--- +description: Logical-and assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #setterCalledWith; + get #field() { + return true; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field &&= false; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), false, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-nullish.js new file mode 100644 index 000000000000..8bb644f29499 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-nullish.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/getter-setter.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +class C { + #setterCalledWith; + get #field() { + return null; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field ??= 1; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 1, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-or.js new file mode 100644 index 000000000000..769a1d4d1608 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-or.js @@ -0,0 +1,63 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/getter-setter.template +/*--- +description: Logical-or assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #setterCalledWith; + get #field() { + return false; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field ||= true; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), true, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-and.js new file mode 100644 index 000000000000..3fbc6760d851 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-and.js @@ -0,0 +1,64 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/getter-setter-short-circuit.template +/*--- +description: Logical-and assignment with target being a private reference (to an accessor property with getter and setter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + setterWasCalled = false; + get #field() { + return false; + } + set #field(value) { + this.setterWasCalled = true; + } + compoundAssignment() { + return this.#field &&= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the short-circuit value"); +assert(!o.setterWasCalled, "The setter should not be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-nullish.js new file mode 100644 index 000000000000..4933a5e99dea --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-nullish.js @@ -0,0 +1,63 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/getter-setter-short-circuit.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to an accessor property with getter and setter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + setterWasCalled = false; + get #field() { + return 1; + } + set #field(value) { + this.setterWasCalled = true; + } + compoundAssignment() { + return this.#field ??= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the short-circuit value"); +assert(!o.setterWasCalled, "The setter should not be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-or.js new file mode 100644 index 000000000000..ad8113b87519 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-or.js @@ -0,0 +1,64 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/getter-setter-short-circuit.template +/*--- +description: Logical-or assignment with target being a private reference (to an accessor property with getter and setter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + setterWasCalled = false; + get #field() { + return true; + } + set #field(value) { + this.setterWasCalled = true; + } + compoundAssignment() { + return this.#field ||= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the short-circuit value"); +assert(!o.setterWasCalled, "The setter should not be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-and.js new file mode 100644 index 000000000000..48f9da1452d7 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-and.js @@ -0,0 +1,55 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/data-property.template +/*--- +description: Logical-and assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #field = true; + compoundAssignment() { + return this.#field &&= false; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), false, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-nullish.js new file mode 100644 index 000000000000..895371b4edc1 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-nullish.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/data-property.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +class C { + #field = null; + compoundAssignment() { + return this.#field ??= 1; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 1, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-or.js new file mode 100644 index 000000000000..ecd05f0a85f9 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-or.js @@ -0,0 +1,55 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/data-property.template +/*--- +description: Logical-or assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #field = false; + compoundAssignment() { + return this.#field ||= true; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), true, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-and.js new file mode 100644 index 000000000000..b97a76a866a4 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-and.js @@ -0,0 +1,58 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/data-property-short-circuit.template +/*--- +description: Logical-and assignment with target being a private reference (to a field (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #field = false; + compoundAssignment() { + return this.#field &&= doNotCall(); + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-nullish.js new file mode 100644 index 000000000000..fa4568829b9d --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-nullish.js @@ -0,0 +1,57 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/data-property-short-circuit.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to a field (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #field = 1; + compoundAssignment() { + return this.#field ??= doNotCall(); + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-or.js new file mode 100644 index 000000000000..c1e2e206ec80 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-or.js @@ -0,0 +1,58 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/data-property-short-circuit.template +/*--- +description: Logical-or assignment with target being a private reference (to a field (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #field = true; + compoundAssignment() { + return this.#field ||= doNotCall(); + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-and.js new file mode 100644 index 000000000000..94168ea59d6f --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-and.js @@ -0,0 +1,51 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/method.template +/*--- +description: Logical-and assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod &&= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-nullish.js new file mode 100644 index 000000000000..aa1b7225c7e2 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-nullish.js @@ -0,0 +1,57 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/method-short-circuit.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to a private method (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod ??= doNotCall(); + } + getPrivateMethodFunctionObject() { + return this.#privateMethod; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), o.getPrivateMethodFunctionObject(), "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-or.js new file mode 100644 index 000000000000..b19dd8efe0ed --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-or.js @@ -0,0 +1,58 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/method-short-circuit.template +/*--- +description: Logical-or assignment with target being a private reference (to a private method (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod ||= doNotCall(); + } + getPrivateMethodFunctionObject() { + return this.#privateMethod; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), o.getPrivateMethodFunctionObject(), "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-and.js new file mode 100644 index 000000000000..6e47415ac7dd --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-and.js @@ -0,0 +1,53 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/getter.template +/*--- +description: Logical-and assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + get #field() { + return true; + } + compoundAssignment() { + return this.#field &&= false; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-nullish.js new file mode 100644 index 000000000000..45216d42a156 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-nullish.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/getter.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +class C { + get #field() { + return null; + } + compoundAssignment() { + return this.#field ??= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-or.js new file mode 100644 index 000000000000..8c9695032ed2 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-or.js @@ -0,0 +1,53 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/getter.template +/*--- +description: Logical-or assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + get #field() { + return false; + } + compoundAssignment() { + return this.#field ||= true; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-and.js new file mode 100644 index 000000000000..f99b2c1a3b62 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-and.js @@ -0,0 +1,57 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/getter-short-circuit.template +/*--- +description: Logical-and assignment with target being a private reference (to an accessor property with getter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + get #field() { + return false; + } + compoundAssignment() { + return this.#field &&= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-nullish.js new file mode 100644 index 000000000000..00569dc54616 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-nullish.js @@ -0,0 +1,56 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/getter-short-circuit.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to an accessor property with getter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field ??= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-or.js new file mode 100644 index 000000000000..b776af7911a8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-or.js @@ -0,0 +1,57 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/getter-short-circuit.template +/*--- +description: Logical-or assignment with target being a private reference (to an accessor property with getter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + get #field() { + return true; + } + compoundAssignment() { + return this.#field ||= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/new/spread-obj-spread-order.js b/js/src/tests/test262/language/expressions/new/spread-obj-spread-order.js index 94c8878399b4..980a894c41da 100644 --- a/js/src/tests/test262/language/expressions/new/spread-obj-spread-order.js +++ b/js/src/tests/test262/language/expressions/new/spread-obj-spread-order.js @@ -39,7 +39,7 @@ Object.defineProperty(o, Symbol('foo'), { get: () => { calls.push("Symbol(foo)") var callCount = 0; new function(obj) { - assert(compareArray(calls, [1, 'z', 'a', "Symbol(foo)"])); + assert.compareArray(calls, [1, 'z', 'a', "Symbol(foo)"]); assert.sameValue(Object.keys(obj).length, 3); callCount += 1; }({...o}); diff --git a/js/src/tests/test262/language/expressions/object/cpn-obj-lit-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/expressions/object/cpn-obj-lit-computed-property-name-from-yield-expression.js index 768fa8117fa5..0051ee14d72b 100644 --- a/js/src/tests/test262/language/expressions/object/cpn-obj-lit-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/expressions/object/cpn-obj-lit-computed-property-name-from-yield-expression.js @@ -39,5 +39,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/object/getter-body-strict-inside.js b/js/src/tests/test262/language/expressions/object/getter-body-strict-inside.js index a1762af50dde..3e37f09baa7a 100644 --- a/js/src/tests/test262/language/expressions/object/getter-body-strict-inside.js +++ b/js/src/tests/test262/language/expressions/object/getter-body-strict-inside.js @@ -8,8 +8,8 @@ description: > reserved word or a future reserved word is made inside a strict mode FunctionBody of a PropertyAssignment negative: - type: SyntaxError phase: parse + type: SyntaxError flags: [noStrict] ---*/ diff --git a/js/src/tests/test262/language/expressions/object/getter-body-strict-outside-strict.js b/js/src/tests/test262/language/expressions/object/getter-body-strict-outside-strict.js index e191ad45a3ed..3af4e0b9e226 100644 --- a/js/src/tests/test262/language/expressions/object/getter-body-strict-outside-strict.js +++ b/js/src/tests/test262/language/expressions/object/getter-body-strict-outside-strict.js @@ -8,8 +8,8 @@ description: > Strict Mode - SyntaxError is thrown when an assignment to a reserved word or a future reserved word is contained in strict code negative: - type: SyntaxError phase: parse + type: SyntaxError flags: [onlyStrict] ---*/ diff --git a/js/src/tests/test262/language/expressions/object/method-definition/async-gen-yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/object/method-definition/async-gen-yield-spread-arr-multiple.js index ae514f569e1a..557a65fcf6ad 100644 --- a/js/src/tests/test262/language/expressions/object/method-definition/async-gen-yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/object/method-definition/async-gen-yield-spread-arr-multiple.js @@ -42,7 +42,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/expressions/object/method-definition/gen-yield-spread-arr-multiple.js b/js/src/tests/test262/language/expressions/object/method-definition/gen-yield-spread-arr-multiple.js index 95a88085165b..1352d0507bcc 100644 --- a/js/src/tests/test262/language/expressions/object/method-definition/gen-yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/expressions/object/method-definition/gen-yield-spread-arr-multiple.js @@ -38,7 +38,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/expressions/object/setter-body-strict-inside.js b/js/src/tests/test262/language/expressions/object/setter-body-strict-inside.js index c78cd28836bf..ad0341354d3a 100644 --- a/js/src/tests/test262/language/expressions/object/setter-body-strict-inside.js +++ b/js/src/tests/test262/language/expressions/object/setter-body-strict-inside.js @@ -8,8 +8,8 @@ description: > reserved word is made in a strict FunctionBody of a PropertyAssignment negative: - type: SyntaxError phase: parse + type: SyntaxError flags: [noStrict] ---*/ diff --git a/js/src/tests/test262/language/expressions/object/setter-body-strict-outside-strict.js b/js/src/tests/test262/language/expressions/object/setter-body-strict-outside-strict.js index 4bf6750c9b3a..a3b0ac398939 100644 --- a/js/src/tests/test262/language/expressions/object/setter-body-strict-outside-strict.js +++ b/js/src/tests/test262/language/expressions/object/setter-body-strict-outside-strict.js @@ -8,8 +8,8 @@ description: > Strict Mode - SyntaxError is thrown when an assignment to a reserved word is contained in strict code negative: - type: SyntaxError phase: parse + type: SyntaxError flags: [onlyStrict] ---*/ diff --git a/js/src/tests/test262/language/expressions/object/setter-param-arguments-strict-inside.js b/js/src/tests/test262/language/expressions/object/setter-param-arguments-strict-inside.js index 1694961fb9c9..2c6e159ab681 100644 --- a/js/src/tests/test262/language/expressions/object/setter-param-arguments-strict-inside.js +++ b/js/src/tests/test262/language/expressions/object/setter-param-arguments-strict-inside.js @@ -8,8 +8,8 @@ description: > the Identifier in a PropertySetParameterList of a PropertyAssignment if its FunctionBody is strict code negative: - type: SyntaxError phase: parse + type: SyntaxError flags: [noStrict] ---*/ diff --git a/js/src/tests/test262/language/expressions/object/setter-param-arguments-strict-outside-strict.js b/js/src/tests/test262/language/expressions/object/setter-param-arguments-strict-outside-strict.js index 1932bf77d361..b1bfb8c5194e 100644 --- a/js/src/tests/test262/language/expressions/object/setter-param-arguments-strict-outside-strict.js +++ b/js/src/tests/test262/language/expressions/object/setter-param-arguments-strict-outside-strict.js @@ -9,8 +9,8 @@ description: > Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code negative: - type: SyntaxError phase: parse + type: SyntaxError flags: [onlyStrict] ---*/ diff --git a/js/src/tests/test262/language/expressions/object/setter-param-eval-strict-inside.js b/js/src/tests/test262/language/expressions/object/setter-param-eval-strict-inside.js index af5153019f80..b3c3db1caab2 100644 --- a/js/src/tests/test262/language/expressions/object/setter-param-eval-strict-inside.js +++ b/js/src/tests/test262/language/expressions/object/setter-param-eval-strict-inside.js @@ -8,8 +8,8 @@ description: > Identifier in a PropertySetParameterList of a PropertyAssignment if its FunctionBody is strict code negative: - type: SyntaxError phase: parse + type: SyntaxError flags: [noStrict] ---*/ diff --git a/js/src/tests/test262/language/expressions/object/setter-param-eval-strict-outside-strict.js b/js/src/tests/test262/language/expressions/object/setter-param-eval-strict-outside-strict.js index ad5aa2afd061..c92405d8b54f 100644 --- a/js/src/tests/test262/language/expressions/object/setter-param-eval-strict-outside-strict.js +++ b/js/src/tests/test262/language/expressions/object/setter-param-eval-strict-outside-strict.js @@ -9,8 +9,8 @@ description: > Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code negative: - type: SyntaxError phase: parse + type: SyntaxError flags: [onlyStrict] ---*/ diff --git a/js/src/tests/test262/language/expressions/optional-chaining/call-expression-super-no-base.js b/js/src/tests/test262/language/expressions/optional-chaining/call-expression-super-no-base.js index 96f037671232..da3a634bdf89 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/call-expression-super-no-base.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/call-expression-super-no-base.js @@ -11,8 +11,8 @@ info: | SuperCall OptionalChain features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-op-template-string-esi.js b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-op-template-string-esi.js index 9b65e72e44b2..ae830b130076 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-op-template-string-esi.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-op-template-string-esi.js @@ -14,8 +14,8 @@ info: | It is a Syntax Error if any code matches this production. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-op-template-string.js b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-op-template-string.js index 06df3a7c67c7..cb8361cd0c01 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-op-template-string.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-op-template-string.js @@ -14,8 +14,8 @@ info: | It is a Syntax Error if any code matches this production. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-optchain-template-string-esi.js b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-optchain-template-string-esi.js index ba87c7d6257e..9c992b00d4a5 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-optchain-template-string-esi.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-optchain-template-string-esi.js @@ -14,8 +14,8 @@ info: | It is a Syntax Error if any code matches this production. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-optchain-template-string.js b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-optchain-template-string.js index 0172c6483c7f..a74ca1cf3200 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-optchain-template-string.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-null-optchain-template-string.js @@ -14,8 +14,8 @@ info: | It is a Syntax Error if any code matches this production. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-op-template-string-esi.js b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-op-template-string-esi.js index 93d6a3d4889e..c1ec6d707d05 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-op-template-string-esi.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-op-template-string-esi.js @@ -14,8 +14,8 @@ info: | It is a Syntax Error if any code matches this production. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-op-template-string.js b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-op-template-string.js index dc9fd69f52ee..043bfb3da3f2 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-op-template-string.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-op-template-string.js @@ -14,8 +14,8 @@ info: | It is a Syntax Error if any code matches this production. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-optchain-template-string-esi.js b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-optchain-template-string-esi.js index d954dc368f3b..1aefaaec22bf 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-optchain-template-string-esi.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-optchain-template-string-esi.js @@ -14,8 +14,8 @@ info: | It is a Syntax Error if any code matches this production. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-optchain-template-string.js b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-optchain-template-string.js index 225ac9281611..277048e1aa80 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-optchain-template-string.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/early-errors-tail-position-optchain-template-string.js @@ -14,8 +14,8 @@ info: | It is a Syntax Error if any code matches this production. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/static-semantics-simple-assignment.js b/js/src/tests/test262/language/expressions/optional-chaining/static-semantics-simple-assignment.js index 1b9f013aee05..cbbcedba506f 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/static-semantics-simple-assignment.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/static-semantics-simple-assignment.js @@ -13,8 +13,8 @@ info: | Return false. features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/update-expression-postfix.js b/js/src/tests/test262/language/expressions/optional-chaining/update-expression-postfix.js index da195e26edd3..8b8fc68f9ad4 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/update-expression-postfix.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/update-expression-postfix.js @@ -13,8 +13,8 @@ info: | --UnaryExpression features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/optional-chaining/update-expression-prefix.js b/js/src/tests/test262/language/expressions/optional-chaining/update-expression-prefix.js index d849f4423aa4..ba65aadc0c51 100644 --- a/js/src/tests/test262/language/expressions/optional-chaining/update-expression-prefix.js +++ b/js/src/tests/test262/language/expressions/optional-chaining/update-expression-prefix.js @@ -13,8 +13,8 @@ info: | --UnaryExpression features: [optional-chaining] negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/property-accessors/non-identifier-name.js b/js/src/tests/test262/language/expressions/property-accessors/non-identifier-name.js index 8410715643ce..50721f92194c 100644 --- a/js/src/tests/test262/language/expressions/property-accessors/non-identifier-name.js +++ b/js/src/tests/test262/language/expressions/property-accessors/non-identifier-name.js @@ -12,8 +12,8 @@ description: > MemberExpression[?Yield, ?Await] . IdentifierName negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/expressions/super/call-spread-obj-spread-order.js b/js/src/tests/test262/language/expressions/super/call-spread-obj-spread-order.js index 96b6fe5a4720..096d65508b8e 100644 --- a/js/src/tests/test262/language/expressions/super/call-spread-obj-spread-order.js +++ b/js/src/tests/test262/language/expressions/super/call-spread-obj-spread-order.js @@ -38,7 +38,7 @@ var callCount = 0; class Test262ParentClass { constructor(obj) { - assert(compareArray(calls, [1, 'z', 'a', "Symbol(foo)"])); + assert.compareArray(calls, [1, 'z', 'a', "Symbol(foo)"]); assert.sameValue(Object.keys(obj).length, 3); callCount += 1; } diff --git a/js/src/tests/test262/language/expressions/unary-plus/S11.4.6_A3_T3.js b/js/src/tests/test262/language/expressions/unary-plus/S11.4.6_A3_T3.js index c811b7593da6..906bb290eace 100644 --- a/js/src/tests/test262/language/expressions/unary-plus/S11.4.6_A3_T3.js +++ b/js/src/tests/test262/language/expressions/unary-plus/S11.4.6_A3_T3.js @@ -13,13 +13,23 @@ if (+"1" !== 1) { } //CHECK#2 -if (isNaN(+"x") !== true) { - throw new Test262Error('#2: +"x" === Not-a-Number. Actual: ' + (+"x")); +if (+new Number("-1") !== -1) { + throw new Test262Error('#2: +new String("-1") === -1. Actual: ' + (+new String("-1"))); } //CHECK#3 -if (+new Number("-1") !== -1) { - throw new Test262Error('#3: +new String("-1") === -1. Actual: ' + (+new String("-1"))); +if (isNaN(+"x") !== true) { + throw new Test262Error('#3: +"x" === Not-a-Number. Actual: ' + (+"x")); +} + +//CHECK#4 +if (isNaN(+"INFINITY") !== true) { + throw new Test262Error('#4: +"INFINITY" === Not-a-Number. Actual: ' + (+"INFINITY")); +} + +//CHECK#5 +if (isNaN(+"infinity") !== true) { + throw new Test262Error('#5: +"infinity" === Not-a-Number. Actual: ' + (+"infinity")); } reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-class-escaped.js new file mode 100644 index 000000000000..d7b328abd1bc --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v10.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u0AFA\u0AFB\u0AFC\u0AFD\u0AFE\u0AFF\u0D00\u0D3B\u0D3C\u1CF7\u1DF6\u1DF7\u1DF8\u1DF9\u{11A01}\u{11A02}\u{11A03}\u{11A04}\u{11A05}\u{11A06}\u{11A07}\u{11A08}\u{11A09}\u{11A0A}\u{11A33}\u{11A34}\u{11A35}\u{11A36}\u{11A37}\u{11A38}\u{11A39}\u{11A3B}\u{11A3C}\u{11A3D}\u{11A3E}\u{11A47}\u{11A51}\u{11A52}\u{11A53}\u{11A54}\u{11A55}\u{11A56}\u{11A57}\u{11A58}\u{11A59}\u{11A5A}\u{11A5B}\u{11A8A}\u{11A8B}\u{11A8C}\u{11A8D}\u{11A8E}\u{11A8F}\u{11A90}\u{11A91}\u{11A92}\u{11A93}\u{11A94}\u{11A95}\u{11A96}\u{11A97}\u{11A98}\u{11A99}\u{11D31}\u{11D32}\u{11D33}\u{11D34}\u{11D35}\u{11D36}\u{11D3A}\u{11D3C}\u{11D3D}\u{11D3F}\u{11D40}\u{11D41}\u{11D42}\u{11D43}\u{11D44}\u{11D45}\u{11D47}\u{11D50}\u{11D51}\u{11D52}\u{11D53}\u{11D54}\u{11D55}\u{11D56}\u{11D57}\u{11D58}\u{11D59}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-class.js new file mode 100644 index 000000000000..69bea3af32ee --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v10.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_ૺૻૼ૽૾૿ഀ഻഼᳷᷹᷷᷸᷶𑨁𑨂𑨃𑨄𑨅𑨆𑨇𑨈𑨉𑨊𑨳𑨴𑨵𑨶𑨷𑨸𑨹𑨻𑨼𑨽𑨾𑩇𑩑𑩒𑩓𑩔𑩕𑩖𑩗𑩘𑩙𑩚𑩛𑪊𑪋𑪌𑪍𑪎𑪏𑪐𑪑𑪒𑪓𑪔𑪕𑪖𑪗𑪘𑪙𑴱𑴲𑴳𑴴𑴵𑴶𑴺𑴼𑴽𑴿𑵀𑵁𑵂𑵃𑵄𑵅𑵇𑵐𑵑𑵒𑵓𑵔𑵕𑵖𑵗𑵘𑵙; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-escaped.js index f320cb70f85f..bbb689a69657 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-10.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-10.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-10.0.0.js index a2aeca3c6777..f62a0478453b 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-10.0.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-10.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-class-escaped.js new file mode 100644 index 000000000000..8eabe9f40977 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v11.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u07FD\u08D3\u09FE\u0C04\uA8FF\u{10D24}\u{10D25}\u{10D26}\u{10D27}\u{10D30}\u{10D31}\u{10D32}\u{10D33}\u{10D34}\u{10D35}\u{10D36}\u{10D37}\u{10D38}\u{10D39}\u{10F46}\u{10F47}\u{10F48}\u{10F49}\u{10F4A}\u{10F4B}\u{10F4C}\u{10F4D}\u{10F4E}\u{10F4F}\u{10F50}\u{11145}\u{11146}\u{111C9}\u{1133B}\u{1145E}\u{1182C}\u{1182D}\u{1182E}\u{1182F}\u{11830}\u{11831}\u{11832}\u{11833}\u{11834}\u{11835}\u{11836}\u{11837}\u{11838}\u{11839}\u{1183A}\u{11D8A}\u{11D8B}\u{11D8C}\u{11D8D}\u{11D8E}\u{11D90}\u{11D91}\u{11D93}\u{11D94}\u{11D95}\u{11D96}\u{11D97}\u{11DA0}\u{11DA1}\u{11DA2}\u{11DA3}\u{11DA4}\u{11DA5}\u{11DA6}\u{11DA7}\u{11DA8}\u{11DA9}\u{11EF3}\u{11EF4}\u{11EF5}\u{11EF6}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-class.js new file mode 100644 index 000000000000..6204cbba77ea --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v11.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_߽࣓৾ఄꣿ𐴤𐴥𐴦𐴧𐴰𐴱𐴲𐴳𐴴𐴵𐴶𐴷𐴸𐴹𐽆𐽇𐽋𐽍𐽎𐽏𐽐𐽈𐽉𐽊𐽌𑅅𑅆𑇉𑌻𑑞𑠬𑠭𑠮𑠯𑠰𑠱𑠲𑠳𑠴𑠵𑠶𑠷𑠸𑠺𑠹𑶊𑶋𑶌𑶍𑶎𑶐𑶑𑶓𑶔𑶕𑶖𑶗𑶠𑶡𑶢𑶣𑶤𑶥𑶦𑶧𑶨𑶩𑻳𑻴𑻵𑻶; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-escaped.js index 372807887966..7163209f06b7 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-11.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-11.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-11.0.0.js index 87d630b71a27..9e319299611f 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-11.0.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-11.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-class-escaped.js new file mode 100644 index 000000000000..b19efc71a0d7 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v12.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u0EBA\u{119D1}\u{119D2}\u{119D3}\u{119D4}\u{119D5}\u{119D6}\u{119D7}\u{119DA}\u{119DB}\u{119DC}\u{119DD}\u{119DE}\u{119DF}\u{119E0}\u{119E4}\u{16F4F}\u{16F7F}\u{16F80}\u{16F81}\u{16F82}\u{16F83}\u{16F84}\u{16F85}\u{16F86}\u{16F87}\u{1E130}\u{1E131}\u{1E132}\u{1E133}\u{1E134}\u{1E135}\u{1E136}\u{1E140}\u{1E141}\u{1E142}\u{1E143}\u{1E144}\u{1E145}\u{1E146}\u{1E147}\u{1E148}\u{1E149}\u{1E2EC}\u{1E2ED}\u{1E2EE}\u{1E2EF}\u{1E2F0}\u{1E2F1}\u{1E2F2}\u{1E2F3}\u{1E2F4}\u{1E2F5}\u{1E2F6}\u{1E2F7}\u{1E2F8}\u{1E2F9}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-class.js new file mode 100644 index 000000000000..0de53a5c6fc2 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v12.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_຺𑧑𑧒𑧓𑧔𑧕𑧖𑧗𑧚𑧛𑧜𑧝𑧞𑧟𑧠𑧤𖽏𖽿𖾀𖾁𖾂𖾃𖾄𖾅𖾆𖾇𞄰𞄱𞄲𞄳𞄴𞄵𞄶𞅀𞅁𞅂𞅃𞅄𞅅𞅆𞅇𞅈𞅉𞋬𞋭𞋮𞋯𞋰𞋱𞋲𞋳𞋴𞋵𞋶𞋷𞋸𞋹; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-escaped.js index ec15a6ca6440..3e32e02893e2 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-12.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-12.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-12.0.0.js index cb894579bae0..8836c00297e1 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-12.0.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-12.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-class-escaped.js new file mode 100644 index 000000000000..43792d60ef3f --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v13.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u0B55\u0D81\u1ABF\u1AC0\uA82C\u{10EAB}\u{10EAC}\u{111CE}\u{111CF}\u{11930}\u{11931}\u{11932}\u{11933}\u{11934}\u{11935}\u{11937}\u{11938}\u{1193B}\u{1193C}\u{1193D}\u{1193E}\u{11940}\u{11942}\u{11943}\u{11950}\u{11951}\u{11952}\u{11953}\u{11954}\u{11955}\u{11956}\u{11957}\u{11958}\u{11959}\u{16FE4}\u{16FF0}\u{16FF1}\u{1FBF0}\u{1FBF1}\u{1FBF2}\u{1FBF3}\u{1FBF4}\u{1FBF5}\u{1FBF6}\u{1FBF7}\u{1FBF8}\u{1FBF9}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-class.js new file mode 100644 index 000000000000..f494863dc52a --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v13.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_୕ඁ꠬ᪿᫀ𐺫𐺬𑇎𑇏𑤰𑤱𑤲𑤳𑤴𑤵𑤷𑤸𑤻𑤼𑤽𑤾𑥀𑥂𑥃𑥐𑥑𑥒𑥓𑥔𑥕𑥖𑥗𑥘𑥙𖿤𖿰𖿱🯰🯱🯲🯳🯴🯵🯶🯷🯸🯹; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-escaped.js index 139dbd338626..7e9f4be0ac51 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-13.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-13.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-13.0.0.js index 5dadc947f88e..3fa46d6fa266 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-13.0.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-13.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-class-escaped.js new file mode 100644 index 000000000000..e8ebeacbdb54 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v14.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u0898\u0899\u089A\u089B\u089C\u089D\u089E\u089F\u08CA\u08CB\u08CC\u08CD\u08CE\u08CF\u08D0\u08D1\u08D2\u0C3C\u1715\u180F\u1AC1\u1AC2\u1AC3\u1AC4\u1AC5\u1AC6\u1AC7\u1AC8\u1AC9\u1ACA\u1ACB\u1ACC\u1ACD\u1ACE\u1DFA\u{10F82}\u{10F83}\u{10F84}\u{10F85}\u{11070}\u{11073}\u{11074}\u{110C2}\u{16AC0}\u{16AC1}\u{16AC2}\u{16AC3}\u{16AC4}\u{16AC5}\u{16AC6}\u{16AC7}\u{16AC8}\u{16AC9}\u{1CF00}\u{1CF01}\u{1CF02}\u{1CF03}\u{1CF04}\u{1CF05}\u{1CF06}\u{1CF07}\u{1CF08}\u{1CF09}\u{1CF0A}\u{1CF0B}\u{1CF0C}\u{1CF0D}\u{1CF0E}\u{1CF0F}\u{1CF10}\u{1CF11}\u{1CF12}\u{1CF13}\u{1CF14}\u{1CF15}\u{1CF16}\u{1CF17}\u{1CF18}\u{1CF19}\u{1CF1A}\u{1CF1B}\u{1CF1C}\u{1CF1D}\u{1CF1E}\u{1CF1F}\u{1CF20}\u{1CF21}\u{1CF22}\u{1CF23}\u{1CF24}\u{1CF25}\u{1CF26}\u{1CF27}\u{1CF28}\u{1CF29}\u{1CF2A}\u{1CF2B}\u{1CF2C}\u{1CF2D}\u{1CF30}\u{1CF31}\u{1CF32}\u{1CF33}\u{1CF34}\u{1CF35}\u{1CF36}\u{1CF37}\u{1CF38}\u{1CF39}\u{1CF3A}\u{1CF3B}\u{1CF3C}\u{1CF3D}\u{1CF3E}\u{1CF3F}\u{1CF40}\u{1CF41}\u{1CF42}\u{1CF43}\u{1CF44}\u{1CF45}\u{1CF46}\u{1E2AE}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-class.js new file mode 100644 index 000000000000..a16a7939fe80 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v14.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_఼᜕࢙࢚࢛࣏࣐࣑࣒࢘࢜࢝࢞࢟࣊࣋࣌࣍࣎᠏𑁰᷺᫃᫄᫊𐾃𐾅᫁᫂᫅᫆᫇᫈᫉᫋ᫌᫍᫎ𐾂𐾄𑁳𑁴𑃂𖫀𖫁𖫂𖫃𖫄𖫅𖫆𖫇𖫈𖫉𜼀𜼁𜼂𜼃𜼄𜼅𜼆𜼇𜼈𜼉𜼊𜼋𜼌𜼍𜼎𜼏𜼐𜼑𜼒𜼓𜼔𜼕𜼖𜼗𜼘𜼙𜼚𜼛𜼜𜼝𜼞𜼟𜼠𜼡𜼢𜼣𜼤𜼥𜼦𜼧𜼨𜼩𜼪𜼫𜼬𜼭𜼰𜼱𜼲𜼳𜼴𜼵𜼶𜼷𜼸𜼹𜼺𜼻𜼼𜼽𜼾𜼿𜽀𜽁𜽂𜽃𜽄𜽅𜽆𞊮; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-escaped.js new file mode 100644 index 000000000000..47ea483f5f54 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-14.0.0-escaped.js @@ -0,0 +1,18 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: sec-names-and-keywords +description: | + Test that Unicode v14.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols +info: | + Generated by https://github.com/mathiasbynens/caniunicode +---*/ + +var _\u0898\u0899\u089A\u089B\u089C\u089D\u089E\u089F\u08CA\u08CB\u08CC\u08CD\u08CE\u08CF\u08D0\u08D1\u08D2\u0C3C\u1715\u180F\u1AC1\u1AC2\u1AC3\u1AC4\u1AC5\u1AC6\u1AC7\u1AC8\u1AC9\u1ACA\u1ACB\u1ACC\u1ACD\u1ACE\u1DFA\u{10F82}\u{10F83}\u{10F84}\u{10F85}\u{11070}\u{11073}\u{11074}\u{110C2}\u{16AC0}\u{16AC1}\u{16AC2}\u{16AC3}\u{16AC4}\u{16AC5}\u{16AC6}\u{16AC7}\u{16AC8}\u{16AC9}\u{1CF00}\u{1CF01}\u{1CF02}\u{1CF03}\u{1CF04}\u{1CF05}\u{1CF06}\u{1CF07}\u{1CF08}\u{1CF09}\u{1CF0A}\u{1CF0B}\u{1CF0C}\u{1CF0D}\u{1CF0E}\u{1CF0F}\u{1CF10}\u{1CF11}\u{1CF12}\u{1CF13}\u{1CF14}\u{1CF15}\u{1CF16}\u{1CF17}\u{1CF18}\u{1CF19}\u{1CF1A}\u{1CF1B}\u{1CF1C}\u{1CF1D}\u{1CF1E}\u{1CF1F}\u{1CF20}\u{1CF21}\u{1CF22}\u{1CF23}\u{1CF24}\u{1CF25}\u{1CF26}\u{1CF27}\u{1CF28}\u{1CF29}\u{1CF2A}\u{1CF2B}\u{1CF2C}\u{1CF2D}\u{1CF30}\u{1CF31}\u{1CF32}\u{1CF33}\u{1CF34}\u{1CF35}\u{1CF36}\u{1CF37}\u{1CF38}\u{1CF39}\u{1CF3A}\u{1CF3B}\u{1CF3C}\u{1CF3D}\u{1CF3E}\u{1CF3F}\u{1CF40}\u{1CF41}\u{1CF42}\u{1CF43}\u{1CF44}\u{1CF45}\u{1CF46}\u{1E2AE}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-14.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-14.0.0.js new file mode 100644 index 000000000000..402d3d48ad46 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-14.0.0.js @@ -0,0 +1,16 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: sec-names-and-keywords +description: | + Test that Unicode v14.0.0 ID_Continue characters are accepted as + identifier part characters. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +---*/ + +var _఼᜕࢙࢚࢛࣏࣐࣑࣒࢘࢜࢝࢞࢟࣊࣋࣌࣍࣎᠏𑁰᷺᫃᫄᫊𐾃𐾅᫁᫂᫅᫆᫇᫈᫉᫋ᫌᫍᫎ𐾂𐾄𑁳𑁴𑃂𖫀𖫁𖫂𖫃𖫄𖫅𖫆𖫇𖫈𖫉𜼀𜼁𜼂𜼃𜼄𜼅𜼆𜼇𜼈𜼉𜼊𜼋𜼌𜼍𜼎𜼏𜼐𜼑𜼒𜼓𜼔𜼕𜼖𜼗𜼘𜼙𜼚𜼛𜼜𜼝𜼞𜼟𜼠𜼡𜼢𜼣𜼤𜼥𜼦𜼧𜼨𜼩𜼪𜼫𜼬𜼭𜼰𜼱𜼲𜼳𜼴𜼵𜼶𜼷𜼸𜼹𜼺𜼻𜼼𜼽𜼾𜼿𜽀𜽁𜽂𜽃𜽄𜽅𜽆𞊮; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-class-escaped.js new file mode 100644 index 000000000000..6d6cdf39d189 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v5.2.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u0816\u0817\u0818\u0819\u081B\u081C\u081D\u081E\u081F\u0820\u0821\u0822\u0823\u0825\u0826\u0827\u0829\u082A\u082B\u082C\u082D\u0900\u094E\u0955\u109A\u109B\u109C\u109D\u19DA\u1A55\u1A56\u1A57\u1A58\u1A59\u1A5A\u1A5B\u1A5C\u1A5D\u1A5E\u1A60\u1A61\u1A62\u1A63\u1A64\u1A65\u1A66\u1A67\u1A68\u1A69\u1A6A\u1A6B\u1A6C\u1A6D\u1A6E\u1A6F\u1A70\u1A71\u1A72\u1A73\u1A74\u1A75\u1A76\u1A77\u1A78\u1A79\u1A7A\u1A7B\u1A7C\u1A7F\u1A80\u1A81\u1A82\u1A83\u1A84\u1A85\u1A86\u1A87\u1A88\u1A89\u1A90\u1A91\u1A92\u1A93\u1A94\u1A95\u1A96\u1A97\u1A98\u1A99\u1CD0\u1CD1\u1CD2\u1CD4\u1CD5\u1CD6\u1CD7\u1CD8\u1CD9\u1CDA\u1CDB\u1CDC\u1CDD\u1CDE\u1CDF\u1CE0\u1CE1\u1CE2\u1CE3\u1CE4\u1CE5\u1CE6\u1CE7\u1CE8\u1CED\u1CF2\u1DFD\u2CEF\u2CF0\u2CF1\uA6F0\uA6F1\uA8E0\uA8E1\uA8E2\uA8E3\uA8E4\uA8E5\uA8E6\uA8E7\uA8E8\uA8E9\uA8EA\uA8EB\uA8EC\uA8ED\uA8EE\uA8EF\uA8F0\uA8F1\uA980\uA981\uA982\uA983\uA9B3\uA9B4\uA9B5\uA9B6\uA9B7\uA9B8\uA9B9\uA9BA\uA9BB\uA9BC\uA9BD\uA9BE\uA9BF\uA9C0\uA9D0\uA9D1\uA9D2\uA9D3\uA9D4\uA9D5\uA9D6\uA9D7\uA9D8\uA9D9\uAA7B\uAAB0\uAAB2\uAAB3\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uABE3\uABE4\uABE5\uABE6\uABE7\uABE8\uABE9\uABEA\uABEC\uABED\uABF0\uABF1\uABF2\uABF3\uABF4\uABF5\uABF6\uABF7\uABF8\uABF9\u{11080}\u{11081}\u{11082}\u{110B0}\u{110B1}\u{110B2}\u{110B3}\u{110B4}\u{110B5}\u{110B6}\u{110B7}\u{110B8}\u{110B9}\u{110BA}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-class.js new file mode 100644 index 000000000000..db4be76e249d --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v5.2.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_ࠖࠗ࠘࠙ࠛࠜࠝࠞࠟࠠࠡࠢࠣࠥࠦࠧࠩࠪࠫࠬ࠭ऀॎॕႚႛႜႝ᧚ᩕᩖᩗᩘᩙᩚᩛᩜᩝᩞ᩠ᩡᩢᩣᩤᩥᩦᩧᩨᩩᩪᩫᩬᩭᩮᩯᩰᩱᩲᩳᩴ᩿᩵᩶᩷᩸᩹᩺᩻᩼᪀᪁᪂᪃᪄᪅᪆᪇᪈᪉᪐᪑᪒᪓᪔᪕᪖᪗᪘᪙᳔᳕᳖᳗᳘᳙᳜᳝᳞᳟᳐᳑᳒᳚᳛᳠᳡᳢᳣᳤᳥᳦᳧᳨᳭ᳲ᷽⳯⳰⳱꛰꛱꣠꣡꣢꣣꣤꣥꣦꣧꣨꣩꣪꣫꣬꣭꣮꣯꣰꣱ꦀꦁꦂꦃ꦳ꦴꦵꦶꦷꦸꦹꦺꦻꦼꦽꦾꦿ꧀꧐꧑꧒꧓꧔꧕꧖꧗꧘꧙ꩻꪴꪰꪲꪳꪷꪸꪾ꪿꫁ꯣꯤꯥꯦꯧꯨꯩꯪ꯬꯭꯰꯱꯲꯳꯴꯵꯶꯷꯸꯹𑂀𑂁𑂂𑂰𑂱𑂲𑂳𑂴𑂵𑂶𑂷𑂸𑂺𑂹; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-escaped.js index 612362b8dc5f..58d58305bb56 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-5.2.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-5.2.0.js b/js/src/tests/test262/language/identifiers/part-unicode-5.2.0.js index 4363a7ccc7fb..0f5a9277ab4d 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-5.2.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-5.2.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-class-escaped.js new file mode 100644 index 000000000000..b3dcddf17718 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v6.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u065F\u0859\u085A\u085B\u093A\u093B\u094F\u0956\u0957\u0F8D\u0F8E\u0F8F\u135D\u135E\u1BE6\u1BE7\u1BE8\u1BE9\u1BEA\u1BEB\u1BEC\u1BED\u1BEE\u1BEF\u1BF0\u1BF1\u1BF2\u1BF3\u1DFC\u2D7F\u{11000}\u{11001}\u{11002}\u{11038}\u{11039}\u{1103A}\u{1103B}\u{1103C}\u{1103D}\u{1103E}\u{1103F}\u{11040}\u{11041}\u{11042}\u{11043}\u{11044}\u{11045}\u{11046}\u{11066}\u{11067}\u{11068}\u{11069}\u{1106A}\u{1106B}\u{1106C}\u{1106D}\u{1106E}\u{1106F}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-class.js new file mode 100644 index 000000000000..95438af4d2bc --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v6.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_ٟ࡙࡚࡛ऺऻॏॖॗྍྎྏ᯦፝፞ᯧᯨᯩᯪᯫᯬᯭᯮᯯᯰᯱ᯲᯳⵿᷼𑀀𑀁𑀂𑀸𑀹𑀺𑀻𑀼𑀽𑀾𑀿𑁀𑁁𑁂𑁃𑁄𑁅𑁆𑁦𑁧𑁨𑁩𑁪𑁫𑁬𑁭𑁮𑁯; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-escaped.js index 2fe6f8270094..21711f27daa1 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-6.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-6.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-6.0.0.js index 40472aac0349..92e39850d6f6 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-6.0.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-6.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-class-escaped.js new file mode 100644 index 000000000000..5539e01ff72d --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v6.1.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u08E4\u08E5\u08E6\u08E7\u08E8\u08E9\u08EA\u08EB\u08EC\u08ED\u08EE\u08EF\u08F0\u08F1\u08F2\u08F3\u08F4\u08F5\u08F6\u08F7\u08F8\u08F9\u08FA\u08FB\u08FC\u08FD\u08FE\u17B4\u17B5\u1BAB\u1BAC\u1BAD\u1CF3\u1CF4\uA674\uA675\uA676\uA677\uA678\uA679\uA67A\uA67B\uA69F\uAAEB\uAAEC\uAAED\uAAEE\uAAEF\uAAF5\uAAF6\u{110F0}\u{110F1}\u{110F2}\u{110F3}\u{110F4}\u{110F5}\u{110F6}\u{110F7}\u{110F8}\u{110F9}\u{11100}\u{11101}\u{11102}\u{11127}\u{11128}\u{11129}\u{1112A}\u{1112B}\u{1112C}\u{1112D}\u{1112E}\u{1112F}\u{11130}\u{11131}\u{11132}\u{11133}\u{11134}\u{11136}\u{11137}\u{11138}\u{11139}\u{1113A}\u{1113B}\u{1113C}\u{1113D}\u{1113E}\u{1113F}\u{11180}\u{11181}\u{11182}\u{111B3}\u{111B4}\u{111B5}\u{111B6}\u{111B7}\u{111B8}\u{111B9}\u{111BA}\u{111BB}\u{111BC}\u{111BD}\u{111BE}\u{111BF}\u{111C0}\u{111D0}\u{111D1}\u{111D2}\u{111D3}\u{111D4}\u{111D5}\u{111D6}\u{111D7}\u{111D8}\u{111D9}\u{116AB}\u{116AC}\u{116AD}\u{116AE}\u{116AF}\u{116B0}\u{116B1}\u{116B2}\u{116B3}\u{116B4}\u{116B5}\u{116B6}\u{116B7}\u{116C0}\u{116C1}\u{116C2}\u{116C3}\u{116C4}\u{116C5}\u{116C6}\u{116C7}\u{116C8}\u{116C9}\u{16F51}\u{16F52}\u{16F53}\u{16F54}\u{16F55}\u{16F56}\u{16F57}\u{16F58}\u{16F59}\u{16F5A}\u{16F5B}\u{16F5C}\u{16F5D}\u{16F5E}\u{16F5F}\u{16F60}\u{16F61}\u{16F62}\u{16F63}\u{16F64}\u{16F65}\u{16F66}\u{16F67}\u{16F68}\u{16F69}\u{16F6A}\u{16F6B}\u{16F6C}\u{16F6D}\u{16F6E}\u{16F6F}\u{16F70}\u{16F71}\u{16F72}\u{16F73}\u{16F74}\u{16F75}\u{16F76}\u{16F77}\u{16F78}\u{16F79}\u{16F7A}\u{16F7B}\u{16F7C}\u{16F7D}\u{16F7E}\u{16F8F}\u{16F90}\u{16F91}\u{16F92}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-class.js new file mode 100644 index 000000000000..ca807adc5fea --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v6.1.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_ࣰࣱࣲࣦࣩ࣭࣮࣯ࣶࣹࣺࣤࣥࣧࣨ࣪࣫࣬ࣳࣴࣵࣷࣸࣻࣼࣽࣾ឴឵᮫ᮬᮭᳳ᳴ꙴꙵꙶꙷꙸꙹꙺꙻꚟꫫꫬꫭꫮꫯꫵ꫶𑃰𑃱𑃲𑃳𑃴𑃵𑃶𑃷𑃸𑃹𑄀𑄁𑄂𑄧𑄨𑄩𑄪𑄫𑄬𑄭𑄮𑄯𑄰𑄱𑄲𑄳𑄴𑄶𑄷𑄸𑄹𑄺𑄻𑄼𑄽𑄾𑄿𑆀𑆁𑆂𑆳𑆴𑆵𑆶𑆷𑆸𑆹𑆺𑆻𑆼𑆽𑆾𑆿𑇀𑇐𑇑𑇒𑇓𑇔𑇕𑇖𑇗𑇘𑇙𑚫𑚬𑚭𑚮𑚯𑚰𑚱𑚲𑚳𑚴𑚵𑚷𑚶𑛀𑛁𑛂𑛃𑛄𑛅𑛆𑛇𑛈𑛉𖽑𖽒𖽓𖽔𖽕𖽖𖽗𖽘𖽙𖽚𖽛𖽜𖽝𖽞𖽟𖽠𖽡𖽢𖽣𖽤𖽥𖽦𖽧𖽨𖽩𖽪𖽫𖽬𖽭𖽮𖽯𖽰𖽱𖽲𖽳𖽴𖽵𖽶𖽷𖽸𖽹𖽺𖽻𖽼𖽽𖽾𖾏𖾐𖾑𖾒; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-escaped.js index 8dee41d9992e..369c3401bceb 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-6.1.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-6.1.0.js b/js/src/tests/test262/language/identifiers/part-unicode-6.1.0.js index c37893ec35bb..4fa06a132fd4 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-6.1.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-6.1.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-class-escaped.js new file mode 100644 index 000000000000..536faf4c773e --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v7.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u08FF\u0C00\u0C81\u0D01\u0DE6\u0DE7\u0DE8\u0DE9\u0DEA\u0DEB\u0DEC\u0DED\u0DEE\u0DEF\u1AB0\u1AB1\u1AB2\u1AB3\u1AB4\u1AB5\u1AB6\u1AB7\u1AB8\u1AB9\u1ABA\u1ABB\u1ABC\u1ABD\u1CF8\u1CF9\u1DE7\u1DE8\u1DE9\u1DEA\u1DEB\u1DEC\u1DED\u1DEE\u1DEF\u1DF0\u1DF1\u1DF2\u1DF3\u1DF4\u1DF5\uA9E5\uA9F0\uA9F1\uA9F2\uA9F3\uA9F4\uA9F5\uA9F6\uA9F7\uA9F8\uA9F9\uAA7C\uAA7D\uFE27\uFE28\uFE29\uFE2A\uFE2B\uFE2C\uFE2D\u{102E0}\u{10376}\u{10377}\u{10378}\u{10379}\u{1037A}\u{10AE5}\u{10AE6}\u{1107F}\u{11173}\u{1122C}\u{1122D}\u{1122E}\u{1122F}\u{11230}\u{11231}\u{11232}\u{11233}\u{11234}\u{11235}\u{11236}\u{11237}\u{112DF}\u{112E0}\u{112E1}\u{112E2}\u{112E3}\u{112E4}\u{112E5}\u{112E6}\u{112E7}\u{112E8}\u{112E9}\u{112EA}\u{112F0}\u{112F1}\u{112F2}\u{112F3}\u{112F4}\u{112F5}\u{112F6}\u{112F7}\u{112F8}\u{112F9}\u{11301}\u{11302}\u{11303}\u{1133C}\u{1133E}\u{1133F}\u{11340}\u{11341}\u{11342}\u{11343}\u{11344}\u{11347}\u{11348}\u{1134B}\u{1134C}\u{1134D}\u{11357}\u{11362}\u{11363}\u{11366}\u{11367}\u{11368}\u{11369}\u{1136A}\u{1136B}\u{1136C}\u{11370}\u{11371}\u{11372}\u{11373}\u{11374}\u{114B0}\u{114B1}\u{114B2}\u{114B3}\u{114B4}\u{114B5}\u{114B6}\u{114B7}\u{114B8}\u{114B9}\u{114BA}\u{114BB}\u{114BC}\u{114BD}\u{114BE}\u{114BF}\u{114C0}\u{114C1}\u{114C2}\u{114C3}\u{114D0}\u{114D1}\u{114D2}\u{114D3}\u{114D4}\u{114D5}\u{114D6}\u{114D7}\u{114D8}\u{114D9}\u{115AF}\u{115B0}\u{115B1}\u{115B2}\u{115B3}\u{115B4}\u{115B5}\u{115B8}\u{115B9}\u{115BA}\u{115BB}\u{115BC}\u{115BD}\u{115BE}\u{115BF}\u{115C0}\u{11630}\u{11631}\u{11632}\u{11633}\u{11634}\u{11635}\u{11636}\u{11637}\u{11638}\u{11639}\u{1163A}\u{1163B}\u{1163C}\u{1163D}\u{1163E}\u{1163F}\u{11640}\u{11650}\u{11651}\u{11652}\u{11653}\u{11654}\u{11655}\u{11656}\u{11657}\u{11658}\u{11659}\u{118E0}\u{118E1}\u{118E2}\u{118E3}\u{118E4}\u{118E5}\u{118E6}\u{118E7}\u{118E8}\u{118E9}\u{16A60}\u{16A61}\u{16A62}\u{16A63}\u{16A64}\u{16A65}\u{16A66}\u{16A67}\u{16A68}\u{16A69}\u{16AF0}\u{16AF1}\u{16AF2}\u{16AF3}\u{16AF4}\u{16B30}\u{16B31}\u{16B32}\u{16B33}\u{16B34}\u{16B35}\u{16B36}\u{16B50}\u{16B51}\u{16B52}\u{16B53}\u{16B54}\u{16B55}\u{16B56}\u{16B57}\u{16B58}\u{16B59}\u{1BC9D}\u{1BC9E}\u{1E8D0}\u{1E8D1}\u{1E8D2}\u{1E8D3}\u{1E8D4}\u{1E8D5}\u{1E8D6}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-class.js new file mode 100644 index 000000000000..413a2d619124 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v7.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_ࣿఀಁഁ෦෧෨෩෪෫෬෭෮෯᪵᪶᪷᪸᪹᪺᪽᪰᪱᪲᪳᪴᪻᪼᳸᳹ᷧᷨᷩᷪᷫᷬᷭᷮᷯᷰᷱᷲᷳᷴ᷵ꧥ꧰꧱꧲꧳꧴꧵꧶꧷꧸꧹ꩼꩽ𑅳𑁿︧︨︩︪︫︬︭𐋠𐫦𐍶𐍷𐍸𐍹𐍺𐫥𑈬𑈭𑈮𑈯𑈰𑈱𑈲𑈳𑈴𑈶𑈵𑈷𑋟𑋠𑋡𑋢𑋣𑋤𑋥𑋦𑋧𑋨𑋩𑋪𑋰𑋱𑋲𑋳𑋴𑋵𑋶𑋷𑋸𑋹𑌁𑌂𑌃𑌼𑌾𑌿𑍀𑍁𑍂𑍃𑍄𑍇𑍈𑍋𑍌𑍍𑍗𑍢𑍣𑍦𑍧𑍨𑍩𑍪𑍫𑍬𑍰𑍱𑍲𑍳𑍴𑒰𑒱𑒲𑒳𑒴𑒵𑒶𑒷𑒸𑒻𑒻𑒼𑒽𑒾𑒿𑓀𑓁𑓃𑓂𑓐𑓑𑓒𑓓𑓔𑓕𑓖𑓗𑓘𑓙𑖯𑖰𑖱𑖲𑖳𑖴𑖵𑖸𑖹𑖺𑖻𑖼𑖽𑖾𑗀𑖿𑘰𑘱𑘲𑘳𑘴𑘵𑘶𑘷𑘸𑘹𑘺𑘻𑘼𑘽𑘾𑘿𑙀𑙐𑙑𑙒𑙓𑙔𑙕𑙖𑙗𑙘𑙙𑣠𑣡𑣢𑣣𑣤𑣥𑣦𑣧𑣨𑣩𖩠𖩡𖩢𖩣𖩤𖩥𖩦𖩧𖩨𖩩𖫰𖫱𖫲𖫳𖫴𖬰𖬱𖬲𖬳𖬴𖬵𖬶𖭐𖭑𖭒𖭓𖭔𖭕𖭖𖭗𖭘𖭙𛲝𛲞𞣐𞣑𞣒𞣓𞣔𞣕𞣖; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-escaped.js index 76dcebdf110f..ec06c89b0d9f 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-7.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-7.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-7.0.0.js index 93728c0d845e..68e9d54cc49b 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-7.0.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-7.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-class-escaped.js new file mode 100644 index 000000000000..32a6597580f0 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v8.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u08E3\uA69E\uFE2E\uFE2F\u{111CA}\u{111CB}\u{111CC}\u{11300}\u{115DC}\u{115DD}\u{1171D}\u{1171E}\u{1171F}\u{11720}\u{11721}\u{11722}\u{11723}\u{11724}\u{11725}\u{11726}\u{11727}\u{11728}\u{11729}\u{1172A}\u{1172B}\u{11730}\u{11731}\u{11732}\u{11733}\u{11734}\u{11735}\u{11736}\u{11737}\u{11738}\u{11739}\u{1DA00}\u{1DA01}\u{1DA02}\u{1DA03}\u{1DA04}\u{1DA05}\u{1DA06}\u{1DA07}\u{1DA08}\u{1DA09}\u{1DA0A}\u{1DA0B}\u{1DA0C}\u{1DA0D}\u{1DA0E}\u{1DA0F}\u{1DA10}\u{1DA11}\u{1DA12}\u{1DA13}\u{1DA14}\u{1DA15}\u{1DA16}\u{1DA17}\u{1DA18}\u{1DA19}\u{1DA1A}\u{1DA1B}\u{1DA1C}\u{1DA1D}\u{1DA1E}\u{1DA1F}\u{1DA20}\u{1DA21}\u{1DA22}\u{1DA23}\u{1DA24}\u{1DA25}\u{1DA26}\u{1DA27}\u{1DA28}\u{1DA29}\u{1DA2A}\u{1DA2B}\u{1DA2C}\u{1DA2D}\u{1DA2E}\u{1DA2F}\u{1DA30}\u{1DA31}\u{1DA32}\u{1DA33}\u{1DA34}\u{1DA35}\u{1DA36}\u{1DA3B}\u{1DA3C}\u{1DA3D}\u{1DA3E}\u{1DA3F}\u{1DA40}\u{1DA41}\u{1DA42}\u{1DA43}\u{1DA44}\u{1DA45}\u{1DA46}\u{1DA47}\u{1DA48}\u{1DA49}\u{1DA4A}\u{1DA4B}\u{1DA4C}\u{1DA4D}\u{1DA4E}\u{1DA4F}\u{1DA50}\u{1DA51}\u{1DA52}\u{1DA53}\u{1DA54}\u{1DA55}\u{1DA56}\u{1DA57}\u{1DA58}\u{1DA59}\u{1DA5A}\u{1DA5B}\u{1DA5C}\u{1DA5D}\u{1DA5E}\u{1DA5F}\u{1DA60}\u{1DA61}\u{1DA62}\u{1DA63}\u{1DA64}\u{1DA65}\u{1DA66}\u{1DA67}\u{1DA68}\u{1DA69}\u{1DA6A}\u{1DA6B}\u{1DA6C}\u{1DA75}\u{1DA84}\u{1DA9B}\u{1DA9C}\u{1DA9D}\u{1DA9E}\u{1DA9F}\u{1DAA1}\u{1DAA2}\u{1DAA3}\u{1DAA4}\u{1DAA5}\u{1DAA6}\u{1DAA7}\u{1DAA8}\u{1DAA9}\u{1DAAA}\u{1DAAB}\u{1DAAC}\u{1DAAD}\u{1DAAE}\u{1DAAF}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-class.js new file mode 100644 index 000000000000..94cf627dbc4e --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v8.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_𑇊ࣣꚞ︮︯𑇋𑇌𑌀𑗜𑗝𑜝𑜞𑜟𑜠𑜡𑜢𑜣𑜤𑜥𑜦𑜧𑜨𑜩𑜪𑜫𑜰𑜱𑜲𑜳𑜴𑜵𑜶𑜷𑜸𑜹𝨀𝨁𝨂𝨃𝨄𝨅𝨆𝨇𝨈𝨉𝨊𝨋𝨌𝨍𝨎𝨏𝨐𝨑𝨒𝨓𝨔𝨕𝨖𝨗𝨘𝨙𝨚𝨛𝨜𝨝𝨞𝨟𝨠𝨡𝨢𝨣𝨤𝨥𝨦𝨧𝨨𝨩𝨪𝨫𝨬𝨭𝨮𝨯𝨰𝨱𝨲𝨳𝨴𝨵𝨶𝨻𝨼𝨽𝨾𝨿𝩀𝩁𝩂𝩃𝩄𝩅𝩆𝩇𝩈𝩉𝩊𝩋𝩌𝩍𝩎𝩏𝩐𝩑𝩒𝩓𝩔𝩕𝩖𝩗𝩘𝩙𝩚𝩛𝩜𝩝𝩞𝩟𝩠𝩡𝩢𝩣𝩤𝩥𝩦𝩧𝩨𝩩𝩪𝩫𝩬𝩵𝪄𝪛𝪜𝪝𝪞𝪟𝪡𝪢𝪣𝪤𝪥𝪦𝪧𝪨𝪩𝪪𝪫𝪬𝪭𝪮𝪯; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-escaped.js index 7dcc619370b7..d8103d236c61 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-8.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-8.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-8.0.0.js index 378d2831fb2c..eb38c6feecdb 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-8.0.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-8.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-class-escaped.js new file mode 100644 index 000000000000..7eecc44eb9b2 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v9.0.0 ID_Continue characters are accepted as + identifier part characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_\u08D4\u08D5\u08D6\u08D7\u08D8\u08D9\u08DA\u08DB\u08DC\u08DD\u08DE\u08DF\u08E0\u08E1\u1DFB\uA8C5\u{1123E}\u{11435}\u{11436}\u{11437}\u{11438}\u{11439}\u{1143A}\u{1143B}\u{1143C}\u{1143D}\u{1143E}\u{1143F}\u{11440}\u{11441}\u{11442}\u{11443}\u{11444}\u{11445}\u{11446}\u{11450}\u{11451}\u{11452}\u{11453}\u{11454}\u{11455}\u{11456}\u{11457}\u{11458}\u{11459}\u{11C2F}\u{11C30}\u{11C31}\u{11C32}\u{11C33}\u{11C34}\u{11C35}\u{11C36}\u{11C38}\u{11C39}\u{11C3A}\u{11C3B}\u{11C3C}\u{11C3D}\u{11C3E}\u{11C3F}\u{11C50}\u{11C51}\u{11C52}\u{11C53}\u{11C54}\u{11C55}\u{11C56}\u{11C57}\u{11C58}\u{11C59}\u{11C92}\u{11C93}\u{11C94}\u{11C95}\u{11C96}\u{11C97}\u{11C98}\u{11C99}\u{11C9A}\u{11C9B}\u{11C9C}\u{11C9D}\u{11C9E}\u{11C9F}\u{11CA0}\u{11CA1}\u{11CA2}\u{11CA3}\u{11CA4}\u{11CA5}\u{11CA6}\u{11CA7}\u{11CA9}\u{11CAA}\u{11CAB}\u{11CAC}\u{11CAD}\u{11CAE}\u{11CAF}\u{11CB0}\u{11CB1}\u{11CB2}\u{11CB3}\u{11CB4}\u{11CB5}\u{11CB6}\u{1E000}\u{1E001}\u{1E002}\u{1E003}\u{1E004}\u{1E005}\u{1E006}\u{1E008}\u{1E009}\u{1E00A}\u{1E00B}\u{1E00C}\u{1E00D}\u{1E00E}\u{1E00F}\u{1E010}\u{1E011}\u{1E012}\u{1E013}\u{1E014}\u{1E015}\u{1E016}\u{1E017}\u{1E018}\u{1E01B}\u{1E01C}\u{1E01D}\u{1E01E}\u{1E01F}\u{1E020}\u{1E021}\u{1E023}\u{1E024}\u{1E026}\u{1E027}\u{1E028}\u{1E029}\u{1E02A}\u{1E944}\u{1E945}\u{1E946}\u{1E947}\u{1E948}\u{1E949}\u{1E94A}\u{1E950}\u{1E951}\u{1E952}\u{1E953}\u{1E954}\u{1E955}\u{1E956}\u{1E957}\u{1E958}\u{1E959}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-class.js b/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-class.js new file mode 100644 index 000000000000..d6d06d4a591f --- /dev/null +++ b/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v9.0.0 ID_Continue characters are accepted as + identifier part characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #_ࣔࣕࣖࣗࣘࣙࣚࣛࣜࣝࣞࣟ࣠࣡᷻ꣅ𑈾𑐵𑐶𑐷𑐸𑐹𑐺𑐻𑐼𑐽𑐾𑐿𑑀𑑁𑑂𑑃𑑄𑑅𑑆𑑐𑑑𑑒𑑓𑑔𑑕𑑖𑑗𑑘𑑙𑰯𑰰𑰱𑰲𑰳𑰴𑰵𑰶𑰸𑰹𑰺𑰻𑰼𑰽𑰾𑰿𑱐𑱑𑱒𑱓𑱔𑱕𑱖𑱗𑱘𑱙𑲒𑲓𑲔𑲕𑲖𑲗𑲘𑲙𑲚𑲛𑲜𑲝𑲞𑲟𑲠𑲡𑲢𑲣𑲤𑲥𑲦𑲧𑲩𑲪𑲫𑲬𑲭𑲮𑲯𑲰𑲱𑲲𑲳𑲴𑲵𑲶𞥊𞀀𞀁𞀂𞀃𞀄𞀅𞀆𞀈𞀉𞀊𞀋𞀌𞀍𞀎𞀏𞀐𞀑𞀒𞀓𞀔𞀕𞀖𞀗𞀘𞀛𞀜𞀝𞀞𞀟𞀠𞀡𞀣𞀤𞀦𞀧𞀨𞀩𞀪𞥄𞥅𞥆𞥇𞥈𞥉𞥐𞥑𞥒𞥓𞥔𞥕𞥖𞥗𞥘𞥙; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-escaped.js b/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-escaped.js index 8d3fcc81cb9c..dcb656f31698 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-9.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/part-unicode-9.0.0.js b/js/src/tests/test262/language/identifiers/part-unicode-9.0.0.js index f6bef268e061..025bdc5879b6 100644 --- a/js/src/tests/test262/language/identifiers/part-unicode-9.0.0.js +++ b/js/src/tests/test262/language/identifiers/part-unicode-9.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-class-escaped.js new file mode 100644 index 000000000000..58614a3f43c4 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v10.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u0860\u0861\u0862\u0863\u0864\u0865\u0866\u0867\u0868\u0869\u086A\u09FC\u312E\u9FD6\u9FD7\u9FD8\u9FD9\u9FDA\u9FDB\u9FDC\u9FDD\u9FDE\u9FDF\u9FE0\u9FE1\u9FE2\u9FE3\u9FE4\u9FE5\u9FE6\u9FE7\u9FE8\u9FE9\u9FEA\u{1032D}\u{1032E}\u{1032F}\u{11A00}\u{11A0B}\u{11A0C}\u{11A0D}\u{11A0E}\u{11A0F}\u{11A10}\u{11A11}\u{11A12}\u{11A13}\u{11A14}\u{11A15}\u{11A16}\u{11A17}\u{11A18}\u{11A19}\u{11A1A}\u{11A1B}\u{11A1C}\u{11A1D}\u{11A1E}\u{11A1F}\u{11A20}\u{11A21}\u{11A22}\u{11A23}\u{11A24}\u{11A25}\u{11A26}\u{11A27}\u{11A28}\u{11A29}\u{11A2A}\u{11A2B}\u{11A2C}\u{11A2D}\u{11A2E}\u{11A2F}\u{11A30}\u{11A31}\u{11A32}\u{11A3A}\u{11A50}\u{11A5C}\u{11A5D}\u{11A5E}\u{11A5F}\u{11A60}\u{11A61}\u{11A62}\u{11A63}\u{11A64}\u{11A65}\u{11A66}\u{11A67}\u{11A68}\u{11A69}\u{11A6A}\u{11A6B}\u{11A6C}\u{11A6D}\u{11A6E}\u{11A6F}\u{11A70}\u{11A71}\u{11A72}\u{11A73}\u{11A74}\u{11A75}\u{11A76}\u{11A77}\u{11A78}\u{11A79}\u{11A7A}\u{11A7B}\u{11A7C}\u{11A7D}\u{11A7E}\u{11A7F}\u{11A80}\u{11A81}\u{11A82}\u{11A83}\u{11A86}\u{11A87}\u{11A88}\u{11A89}\u{11D00}\u{11D01}\u{11D02}\u{11D03}\u{11D04}\u{11D05}\u{11D06}\u{11D08}\u{11D09}\u{11D0B}\u{11D0C}\u{11D0D}\u{11D0E}\u{11D0F}\u{11D10}\u{11D11}\u{11D12}\u{11D13}\u{11D14}\u{11D15}\u{11D16}\u{11D17}\u{11D18}\u{11D19}\u{11D1A}\u{11D1B}\u{11D1C}\u{11D1D}\u{11D1E}\u{11D1F}\u{11D20}\u{11D21}\u{11D22}\u{11D23}\u{11D24}\u{11D25}\u{11D26}\u{11D27}\u{11D28}\u{11D29}\u{11D2A}\u{11D2B}\u{11D2C}\u{11D2D}\u{11D2E}\u{11D2F}\u{11D30}\u{11D46}\u{16FE1}\u{1B002}\u{1B003}\u{1B004}\u{1B005}\u{1B006}\u{1B007}\u{1B008}\u{1B009}\u{1B00A}\u{1B00B}\u{1B00C}\u{1B00D}\u{1B00E}\u{1B00F}\u{1B010}\u{1B011}\u{1B012}\u{1B013}\u{1B014}\u{1B015}\u{1B016}\u{1B017}\u{1B018}\u{1B019}\u{1B01A}\u{1B01B}\u{1B01C}\u{1B01D}\u{1B01E}\u{1B01F}\u{1B020}\u{1B021}\u{1B022}\u{1B023}\u{1B024}\u{1B025}\u{1B026}\u{1B027}\u{1B028}\u{1B029}\u{1B02A}\u{1B02B}\u{1B02C}\u{1B02D}\u{1B02E}\u{1B02F}\u{1B030}\u{1B031}\u{1B032}\u{1B033}\u{1B034}\u{1B035}\u{1B036}\u{1B037}\u{1B038}\u{1B039}\u{1B03A}\u{1B03B}\u{1B03C}\u{1B03D}\u{1B03E}\u{1B03F}\u{1B040}\u{1B041}\u{1B042}\u{1B043}\u{1B044}\u{1B045}\u{1B046}\u{1B047}\u{1B048}\u{1B049}\u{1B04A}\u{1B04B}\u{1B04C}\u{1B04D}\u{1B04E}\u{1B04F}\u{1B050}\u{1B051}\u{1B052}\u{1B053}\u{1B054}\u{1B055}\u{1B056}\u{1B057}\u{1B058}\u{1B059}\u{1B05A}\u{1B05B}\u{1B05C}\u{1B05D}\u{1B05E}\u{1B05F}\u{1B060}\u{1B061}\u{1B062}\u{1B063}\u{1B064}\u{1B065}\u{1B066}\u{1B067}\u{1B068}\u{1B069}\u{1B06A}\u{1B06B}\u{1B06C}\u{1B06D}\u{1B06E}\u{1B06F}\u{1B070}\u{1B071}\u{1B072}\u{1B073}\u{1B074}\u{1B075}\u{1B076}\u{1B077}\u{1B078}\u{1B079}\u{1B07A}\u{1B07B}\u{1B07C}\u{1B07D}\u{1B07E}\u{1B07F}\u{1B080}\u{1B081}\u{1B082}\u{1B083}\u{1B084}\u{1B085}\u{1B086}\u{1B087}\u{1B088}\u{1B089}\u{1B08A}\u{1B08B}\u{1B08C}\u{1B08D}\u{1B08E}\u{1B08F}\u{1B090}\u{1B091}\u{1B092}\u{1B093}\u{1B094}\u{1B095}\u{1B096}\u{1B097}\u{1B098}\u{1B099}\u{1B09A}\u{1B09B}\u{1B09C}\u{1B09D}\u{1B09E}\u{1B09F}\u{1B0A0}\u{1B0A1}\u{1B0A2}\u{1B0A3}\u{1B0A4}\u{1B0A5}\u{1B0A6}\u{1B0A7}\u{1B0A8}\u{1B0A9}\u{1B0AA}\u{1B0AB}\u{1B0AC}\u{1B0AD}\u{1B0AE}\u{1B0AF}\u{1B0B0}\u{1B0B1}\u{1B0B2}\u{1B0B3}\u{1B0B4}\u{1B0B5}\u{1B0B6}\u{1B0B7}\u{1B0B8}\u{1B0B9}\u{1B0BA}\u{1B0BB}\u{1B0BC}\u{1B0BD}\u{1B0BE}\u{1B0BF}\u{1B0C0}\u{1B0C1}\u{1B0C2}\u{1B0C3}\u{1B0C4}\u{1B0C5}\u{1B0C6}\u{1B0C7}\u{1B0C8}\u{1B0C9}\u{1B0CA}\u{1B0CB}\u{1B0CC}\u{1B0CD}\u{1B0CE}\u{1B0CF}\u{1B0D0}\u{1B0D1}\u{1B0D2}\u{1B0D3}\u{1B0D4}\u{1B0D5}\u{1B0D6}\u{1B0D7}\u{1B0D8}\u{1B0D9}\u{1B0DA}\u{1B0DB}\u{1B0DC}\u{1B0DD}\u{1B0DE}\u{1B0DF}\u{1B0E0}\u{1B0E1}\u{1B0E2}\u{1B0E3}\u{1B0E4}\u{1B0E5}\u{1B0E6}\u{1B0E7}\u{1B0E8}\u{1B0E9}\u{1B0EA}\u{1B0EB}\u{1B0EC}\u{1B0ED}\u{1B0EE}\u{1B0EF}\u{1B0F0}\u{1B0F1}\u{1B0F2}\u{1B0F3}\u{1B0F4}\u{1B0F5}\u{1B0F6}\u{1B0F7}\u{1B0F8}\u{1B0F9}\u{1B0FA}\u{1B0FB}\u{1B0FC}\u{1B0FD}\u{1B0FE}\u{1B0FF}\u{1B100}\u{1B101}\u{1B102}\u{1B103}\u{1B104}\u{1B105}\u{1B106}\u{1B107}\u{1B108}\u{1B109}\u{1B10A}\u{1B10B}\u{1B10C}\u{1B10D}\u{1B10E}\u{1B10F}\u{1B110}\u{1B111}\u{1B112}\u{1B113}\u{1B114}\u{1B115}\u{1B116}\u{1B117}\u{1B118}\u{1B119}\u{1B11A}\u{1B11B}\u{1B11C}\u{1B11D}\u{1B11E}\u{1B170}\u{1B171}\u{1B172}\u{1B173}\u{1B174}\u{1B175}\u{1B176}\u{1B177}\u{1B178}\u{1B179}\u{1B17A}\u{1B17B}\u{1B17C}\u{1B17D}\u{1B17E}\u{1B17F}\u{1B180}\u{1B181}\u{1B182}\u{1B183}\u{1B184}\u{1B185}\u{1B186}\u{1B187}\u{1B188}\u{1B189}\u{1B18A}\u{1B18B}\u{1B18C}\u{1B18D}\u{1B18E}\u{1B18F}\u{1B190}\u{1B191}\u{1B192}\u{1B193}\u{1B194}\u{1B195}\u{1B196}\u{1B197}\u{1B198}\u{1B199}\u{1B19A}\u{1B19B}\u{1B19C}\u{1B19D}\u{1B19E}\u{1B19F}\u{1B1A0}\u{1B1A1}\u{1B1A2}\u{1B1A3}\u{1B1A4}\u{1B1A5}\u{1B1A6}\u{1B1A7}\u{1B1A8}\u{1B1A9}\u{1B1AA}\u{1B1AB}\u{1B1AC}\u{1B1AD}\u{1B1AE}\u{1B1AF}\u{1B1B0}\u{1B1B1}\u{1B1B2}\u{1B1B3}\u{1B1B4}\u{1B1B5}\u{1B1B6}\u{1B1B7}\u{1B1B8}\u{1B1B9}\u{1B1BA}\u{1B1BB}\u{1B1BC}\u{1B1BD}\u{1B1BE}\u{1B1BF}\u{1B1C0}\u{1B1C1}\u{1B1C2}\u{1B1C3}\u{1B1C4}\u{1B1C5}\u{1B1C6}\u{1B1C7}\u{1B1C8}\u{1B1C9}\u{1B1CA}\u{1B1CB}\u{1B1CC}\u{1B1CD}\u{1B1CE}\u{1B1CF}\u{1B1D0}\u{1B1D1}\u{1B1D2}\u{1B1D3}\u{1B1D4}\u{1B1D5}\u{1B1D6}\u{1B1D7}\u{1B1D8}\u{1B1D9}\u{1B1DA}\u{1B1DB}\u{1B1DC}\u{1B1DD}\u{1B1DE}\u{1B1DF}\u{1B1E0}\u{1B1E1}\u{1B1E2}\u{1B1E3}\u{1B1E4}\u{1B1E5}\u{1B1E6}\u{1B1E7}\u{1B1E8}\u{1B1E9}\u{1B1EA}\u{1B1EB}\u{1B1EC}\u{1B1ED}\u{1B1EE}\u{1B1EF}\u{1B1F0}\u{1B1F1}\u{1B1F2}\u{1B1F3}\u{1B1F4}\u{1B1F5}\u{1B1F6}\u{1B1F7}\u{1B1F8}\u{1B1F9}\u{1B1FA}\u{1B1FB}\u{1B1FC}\u{1B1FD}\u{1B1FE}\u{1B1FF}\u{1B200}\u{1B201}\u{1B202}\u{1B203}\u{1B204}\u{1B205}\u{1B206}\u{1B207}\u{1B208}\u{1B209}\u{1B20A}\u{1B20B}\u{1B20C}\u{1B20D}\u{1B20E}\u{1B20F}\u{1B210}\u{1B211}\u{1B212}\u{1B213}\u{1B214}\u{1B215}\u{1B216}\u{1B217}\u{1B218}\u{1B219}\u{1B21A}\u{1B21B}\u{1B21C}\u{1B21D}\u{1B21E}\u{1B21F}\u{1B220}\u{1B221}\u{1B222}\u{1B223}\u{1B224}\u{1B225}\u{1B226}\u{1B227}\u{1B228}\u{1B229}\u{1B22A}\u{1B22B}\u{1B22C}\u{1B22D}\u{1B22E}\u{1B22F}\u{1B230}\u{1B231}\u{1B232}\u{1B233}\u{1B234}\u{1B235}\u{1B236}\u{1B237}\u{1B238}\u{1B239}\u{1B23A}\u{1B23B}\u{1B23C}\u{1B23D}\u{1B23E}\u{1B23F}\u{1B240}\u{1B241}\u{1B242}\u{1B243}\u{1B244}\u{1B245}\u{1B246}\u{1B247}\u{1B248}\u{1B249}\u{1B24A}\u{1B24B}\u{1B24C}\u{1B24D}\u{1B24E}\u{1B24F}\u{1B250}\u{1B251}\u{1B252}\u{1B253}\u{1B254}\u{1B255}\u{1B256}\u{1B257}\u{1B258}\u{1B259}\u{1B25A}\u{1B25B}\u{1B25C}\u{1B25D}\u{1B25E}\u{1B25F}\u{1B260}\u{1B261}\u{1B262}\u{1B263}\u{1B264}\u{1B265}\u{1B266}\u{1B267}\u{1B268}\u{1B269}\u{1B26A}\u{1B26B}\u{1B26C}\u{1B26D}\u{1B26E}\u{1B26F}\u{1B270}\u{1B271}\u{1B272}\u{1B273}\u{1B274}\u{1B275}\u{1B276}\u{1B277}\u{1B278}\u{1B279}\u{1B27A}\u{1B27B}\u{1B27C}\u{1B27D}\u{1B27E}\u{1B27F}\u{1B280}\u{1B281}\u{1B282}\u{1B283}\u{1B284}\u{1B285}\u{1B286}\u{1B287}\u{1B288}\u{1B289}\u{1B28A}\u{1B28B}\u{1B28C}\u{1B28D}\u{1B28E}\u{1B28F}\u{1B290}\u{1B291}\u{1B292}\u{1B293}\u{1B294}\u{1B295}\u{1B296}\u{1B297}\u{1B298}\u{1B299}\u{1B29A}\u{1B29B}\u{1B29C}\u{1B29D}\u{1B29E}\u{1B29F}\u{1B2A0}\u{1B2A1}\u{1B2A2}\u{1B2A3}\u{1B2A4}\u{1B2A5}\u{1B2A6}\u{1B2A7}\u{1B2A8}\u{1B2A9}\u{1B2AA}\u{1B2AB}\u{1B2AC}\u{1B2AD}\u{1B2AE}\u{1B2AF}\u{1B2B0}\u{1B2B1}\u{1B2B2}\u{1B2B3}\u{1B2B4}\u{1B2B5}\u{1B2B6}\u{1B2B7}\u{1B2B8}\u{1B2B9}\u{1B2BA}\u{1B2BB}\u{1B2BC}\u{1B2BD}\u{1B2BE}\u{1B2BF}\u{1B2C0}\u{1B2C1}\u{1B2C2}\u{1B2C3}\u{1B2C4}\u{1B2C5}\u{1B2C6}\u{1B2C7}\u{1B2C8}\u{1B2C9}\u{1B2CA}\u{1B2CB}\u{1B2CC}\u{1B2CD}\u{1B2CE}\u{1B2CF}\u{1B2D0}\u{1B2D1}\u{1B2D2}\u{1B2D3}\u{1B2D4}\u{1B2D5}\u{1B2D6}\u{1B2D7}\u{1B2D8}\u{1B2D9}\u{1B2DA}\u{1B2DB}\u{1B2DC}\u{1B2DD}\u{1B2DE}\u{1B2DF}\u{1B2E0}\u{1B2E1}\u{1B2E2}\u{1B2E3}\u{1B2E4}\u{1B2E5}\u{1B2E6}\u{1B2E7}\u{1B2E8}\u{1B2E9}\u{1B2EA}\u{1B2EB}\u{1B2EC}\u{1B2ED}\u{1B2EE}\u{1B2EF}\u{1B2F0}\u{1B2F1}\u{1B2F2}\u{1B2F3}\u{1B2F4}\u{1B2F5}\u{1B2F6}\u{1B2F7}\u{1B2F8}\u{1B2F9}\u{1B2FA}\u{1B2FB}\u{2CEB0}\u{2CEB1}\u{2CEB2}\u{2CEB3}\u{2CEB4}\u{2CEB5}\u{2CEB6}\u{2CEB7}\u{2CEB8}\u{2CEB9}\u{2CEBA}\u{2CEBB}\u{2CEBC}\u{2CEBD}\u{2CEBE}\u{2CEBF}\u{2CEC0}\u{2CEC1}\u{2CEC2}\u{2CEC3}\u{2CEC4}\u{2CEC5}\u{2CEC6}\u{2CEC7}\u{2CEC8}\u{2CEC9}\u{2CECA}\u{2CECB}\u{2CECC}\u{2CECD}\u{2CECE}\u{2CECF}\u{2CED0}\u{2CED1}\u{2CED2}\u{2CED3}\u{2CED4}\u{2CED5}\u{2CED6}\u{2CED7}\u{2CED8}\u{2CED9}\u{2CEDA}\u{2CEDB}\u{2CEDC}\u{2CEDD}\u{2CEDE}\u{2CEDF}\u{2CEE0}\u{2CEE1}\u{2CEE2}\u{2CEE3}\u{2CEE4}\u{2CEE5}\u{2CEE6}\u{2CEE7}\u{2CEE8}\u{2CEE9}\u{2CEEA}\u{2CEEB}\u{2CEEC}\u{2CEED}\u{2CEEE}\u{2CEEF}\u{2CEF0}\u{2CEF1}\u{2CEF2}\u{2CEF3}\u{2CEF4}\u{2CEF5}\u{2CEF6}\u{2CEF7}\u{2CEF8}\u{2CEF9}\u{2CEFA}\u{2CEFB}\u{2CEFC}\u{2CEFD}\u{2CEFE}\u{2CEFF}\u{2CF00}\u{2CF01}\u{2CF02}\u{2CF03}\u{2CF04}\u{2CF05}\u{2CF06}\u{2CF07}\u{2CF08}\u{2CF09}\u{2CF0A}\u{2CF0B}\u{2CF0C}\u{2CF0D}\u{2CF0E}\u{2CF0F}\u{2CF10}\u{2CF11}\u{2CF12}\u{2CF13}\u{2CF14}\u{2CF15}\u{2CF16}\u{2CF17}\u{2CF18}\u{2CF19}\u{2CF1A}\u{2CF1B}\u{2CF1C}\u{2CF1D}\u{2CF1E}\u{2CF1F}\u{2CF20}\u{2CF21}\u{2CF22}\u{2CF23}\u{2CF24}\u{2CF25}\u{2CF26}\u{2CF27}\u{2CF28}\u{2CF29}\u{2CF2A}\u{2CF2B}\u{2CF2C}\u{2CF2D}\u{2CF2E}\u{2CF2F}\u{2CF30}\u{2CF31}\u{2CF32}\u{2CF33}\u{2CF34}\u{2CF35}\u{2CF36}\u{2CF37}\u{2CF38}\u{2CF39}\u{2CF3A}\u{2CF3B}\u{2CF3C}\u{2CF3D}\u{2CF3E}\u{2CF3F}\u{2CF40}\u{2CF41}\u{2CF42}\u{2CF43}\u{2CF44}\u{2CF45}\u{2CF46}\u{2CF47}\u{2CF48}\u{2CF49}\u{2CF4A}\u{2CF4B}\u{2CF4C}\u{2CF4D}\u{2CF4E}\u{2CF4F}\u{2CF50}\u{2CF51}\u{2CF52}\u{2CF53}\u{2CF54}\u{2CF55}\u{2CF56}\u{2CF57}\u{2CF58}\u{2CF59}\u{2CF5A}\u{2CF5B}\u{2CF5C}\u{2CF5D}\u{2CF5E}\u{2CF5F}\u{2CF60}\u{2CF61}\u{2CF62}\u{2CF63}\u{2CF64}\u{2CF65}\u{2CF66}\u{2CF67}\u{2CF68}\u{2CF69}\u{2CF6A}\u{2CF6B}\u{2CF6C}\u{2CF6D}\u{2CF6E}\u{2CF6F}\u{2CF70}\u{2CF71}\u{2CF72}\u{2CF73}\u{2CF74}\u{2CF75}\u{2CF76}\u{2CF77}\u{2CF78}\u{2CF79}\u{2CF7A}\u{2CF7B}\u{2CF7C}\u{2CF7D}\u{2CF7E}\u{2CF7F}\u{2CF80}\u{2CF81}\u{2CF82}\u{2CF83}\u{2CF84}\u{2CF85}\u{2CF86}\u{2CF87}\u{2CF88}\u{2CF89}\u{2CF8A}\u{2CF8B}\u{2CF8C}\u{2CF8D}\u{2CF8E}\u{2CF8F}\u{2CF90}\u{2CF91}\u{2CF92}\u{2CF93}\u{2CF94}\u{2CF95}\u{2CF96}\u{2CF97}\u{2CF98}\u{2CF99}\u{2CF9A}\u{2CF9B}\u{2CF9C}\u{2CF9D}\u{2CF9E}\u{2CF9F}\u{2CFA0}\u{2CFA1}\u{2CFA2}\u{2CFA3}\u{2CFA4}\u{2CFA5}\u{2CFA6}\u{2CFA7}\u{2CFA8}\u{2CFA9}\u{2CFAA}\u{2CFAB}\u{2CFAC}\u{2CFAD}\u{2CFAE}\u{2CFAF}\u{2CFB0}\u{2CFB1}\u{2CFB2}\u{2CFB3}\u{2CFB4}\u{2CFB5}\u{2CFB6}\u{2CFB7}\u{2CFB8}\u{2CFB9}\u{2CFBA}\u{2CFBB}\u{2CFBC}\u{2CFBD}\u{2CFBE}\u{2CFBF}\u{2CFC0}\u{2CFC1}\u{2CFC2}\u{2CFC3}\u{2CFC4}\u{2CFC5}\u{2CFC6}\u{2CFC7}\u{2CFC8}\u{2CFC9}\u{2CFCA}\u{2CFCB}\u{2CFCC}\u{2CFCD}\u{2CFCE}\u{2CFCF}\u{2CFD0}\u{2CFD1}\u{2CFD2}\u{2CFD3}\u{2CFD4}\u{2CFD5}\u{2CFD6}\u{2CFD7}\u{2CFD8}\u{2CFD9}\u{2CFDA}\u{2CFDB}\u{2CFDC}\u{2CFDD}\u{2CFDE}\u{2CFDF}\u{2CFE0}\u{2CFE1}\u{2CFE2}\u{2CFE3}\u{2CFE4}\u{2CFE5}\u{2CFE6}\u{2CFE7}\u{2CFE8}\u{2CFE9}\u{2CFEA}\u{2CFEB}\u{2CFEC}\u{2CFED}\u{2CFEE}\u{2CFEF}\u{2CFF0}\u{2CFF1}\u{2CFF2}\u{2CFF3}\u{2CFF4}\u{2CFF5}\u{2CFF6}\u{2CFF7}\u{2CFF8}\u{2CFF9}\u{2CFFA}\u{2CFFB}\u{2CFFC}\u{2CFFD}\u{2CFFE}\u{2CFFF}\u{2D000}\u{2D001}\u{2D002}\u{2D003}\u{2D004}\u{2D005}\u{2D006}\u{2D007}\u{2D008}\u{2D009}\u{2D00A}\u{2D00B}\u{2D00C}\u{2D00D}\u{2D00E}\u{2D00F}\u{2D010}\u{2D011}\u{2D012}\u{2D013}\u{2D014}\u{2D015}\u{2D016}\u{2D017}\u{2D018}\u{2D019}\u{2D01A}\u{2D01B}\u{2D01C}\u{2D01D}\u{2D01E}\u{2D01F}\u{2D020}\u{2D021}\u{2D022}\u{2D023}\u{2D024}\u{2D025}\u{2D026}\u{2D027}\u{2D028}\u{2D029}\u{2D02A}\u{2D02B}\u{2D02C}\u{2D02D}\u{2D02E}\u{2D02F}\u{2D030}\u{2D031}\u{2D032}\u{2D033}\u{2D034}\u{2D035}\u{2D036}\u{2D037}\u{2D038}\u{2D039}\u{2D03A}\u{2D03B}\u{2D03C}\u{2D03D}\u{2D03E}\u{2D03F}\u{2D040}\u{2D041}\u{2D042}\u{2D043}\u{2D044}\u{2D045}\u{2D046}\u{2D047}\u{2D048}\u{2D049}\u{2D04A}\u{2D04B}\u{2D04C}\u{2D04D}\u{2D04E}\u{2D04F}\u{2D050}\u{2D051}\u{2D052}\u{2D053}\u{2D054}\u{2D055}\u{2D056}\u{2D057}\u{2D058}\u{2D059}\u{2D05A}\u{2D05B}\u{2D05C}\u{2D05D}\u{2D05E}\u{2D05F}\u{2D060}\u{2D061}\u{2D062}\u{2D063}\u{2D064}\u{2D065}\u{2D066}\u{2D067}\u{2D068}\u{2D069}\u{2D06A}\u{2D06B}\u{2D06C}\u{2D06D}\u{2D06E}\u{2D06F}\u{2D070}\u{2D071}\u{2D072}\u{2D073}\u{2D074}\u{2D075}\u{2D076}\u{2D077}\u{2D078}\u{2D079}\u{2D07A}\u{2D07B}\u{2D07C}\u{2D07D}\u{2D07E}\u{2D07F}\u{2D080}\u{2D081}\u{2D082}\u{2D083}\u{2D084}\u{2D085}\u{2D086}\u{2D087}\u{2D088}\u{2D089}\u{2D08A}\u{2D08B}\u{2D08C}\u{2D08D}\u{2D08E}\u{2D08F}\u{2D090}\u{2D091}\u{2D092}\u{2D093}\u{2D094}\u{2D095}\u{2D096}\u{2D097}\u{2D098}\u{2D099}\u{2D09A}\u{2D09B}\u{2D09C}\u{2D09D}\u{2D09E}\u{2D09F}\u{2D0A0}\u{2D0A1}\u{2D0A2}\u{2D0A3}\u{2D0A4}\u{2D0A5}\u{2D0A6}\u{2D0A7}\u{2D0A8}\u{2D0A9}\u{2D0AA}\u{2D0AB}\u{2D0AC}\u{2D0AD}\u{2D0AE}\u{2D0AF}\u{2D0B0}\u{2D0B1}\u{2D0B2}\u{2D0B3}\u{2D0B4}\u{2D0B5}\u{2D0B6}\u{2D0B7}\u{2D0B8}\u{2D0B9}\u{2D0BA}\u{2D0BB}\u{2D0BC}\u{2D0BD}\u{2D0BE}\u{2D0BF}\u{2D0C0}\u{2D0C1}\u{2D0C2}\u{2D0C3}\u{2D0C4}\u{2D0C5}\u{2D0C6}\u{2D0C7}\u{2D0C8}\u{2D0C9}\u{2D0CA}\u{2D0CB}\u{2D0CC}\u{2D0CD}\u{2D0CE}\u{2D0CF}\u{2D0D0}\u{2D0D1}\u{2D0D2}\u{2D0D3}\u{2D0D4}\u{2D0D5}\u{2D0D6}\u{2D0D7}\u{2D0D8}\u{2D0D9}\u{2D0DA}\u{2D0DB}\u{2D0DC}\u{2D0DD}\u{2D0DE}\u{2D0DF}\u{2D0E0}\u{2D0E1}\u{2D0E2}\u{2D0E3}\u{2D0E4}\u{2D0E5}\u{2D0E6}\u{2D0E7}\u{2D0E8}\u{2D0E9}\u{2D0EA}\u{2D0EB}\u{2D0EC}\u{2D0ED}\u{2D0EE}\u{2D0EF}\u{2D0F0}\u{2D0F1}\u{2D0F2}\u{2D0F3}\u{2D0F4}\u{2D0F5}\u{2D0F6}\u{2D0F7}\u{2D0F8}\u{2D0F9}\u{2D0FA}\u{2D0FB}\u{2D0FC}\u{2D0FD}\u{2D0FE}\u{2D0FF}\u{2D100}\u{2D101}\u{2D102}\u{2D103}\u{2D104}\u{2D105}\u{2D106}\u{2D107}\u{2D108}\u{2D109}\u{2D10A}\u{2D10B}\u{2D10C}\u{2D10D}\u{2D10E}\u{2D10F}\u{2D110}\u{2D111}\u{2D112}\u{2D113}\u{2D114}\u{2D115}\u{2D116}\u{2D117}\u{2D118}\u{2D119}\u{2D11A}\u{2D11B}\u{2D11C}\u{2D11D}\u{2D11E}\u{2D11F}\u{2D120}\u{2D121}\u{2D122}\u{2D123}\u{2D124}\u{2D125}\u{2D126}\u{2D127}\u{2D128}\u{2D129}\u{2D12A}\u{2D12B}\u{2D12C}\u{2D12D}\u{2D12E}\u{2D12F}\u{2D130}\u{2D131}\u{2D132}\u{2D133}\u{2D134}\u{2D135}\u{2D136}\u{2D137}\u{2D138}\u{2D139}\u{2D13A}\u{2D13B}\u{2D13C}\u{2D13D}\u{2D13E}\u{2D13F}\u{2D140}\u{2D141}\u{2D142}\u{2D143}\u{2D144}\u{2D145}\u{2D146}\u{2D147}\u{2D148}\u{2D149}\u{2D14A}\u{2D14B}\u{2D14C}\u{2D14D}\u{2D14E}\u{2D14F}\u{2D150}\u{2D151}\u{2D152}\u{2D153}\u{2D154}\u{2D155}\u{2D156}\u{2D157}\u{2D158}\u{2D159}\u{2D15A}\u{2D15B}\u{2D15C}\u{2D15D}\u{2D15E}\u{2D15F}\u{2D160}\u{2D161}\u{2D162}\u{2D163}\u{2D164}\u{2D165}\u{2D166}\u{2D167}\u{2D168}\u{2D169}\u{2D16A}\u{2D16B}\u{2D16C}\u{2D16D}\u{2D16E}\u{2D16F}\u{2D170}\u{2D171}\u{2D172}\u{2D173}\u{2D174}\u{2D175}\u{2D176}\u{2D177}\u{2D178}\u{2D179}\u{2D17A}\u{2D17B}\u{2D17C}\u{2D17D}\u{2D17E}\u{2D17F}\u{2D180}\u{2D181}\u{2D182}\u{2D183}\u{2D184}\u{2D185}\u{2D186}\u{2D187}\u{2D188}\u{2D189}\u{2D18A}\u{2D18B}\u{2D18C}\u{2D18D}\u{2D18E}\u{2D18F}\u{2D190}\u{2D191}\u{2D192}\u{2D193}\u{2D194}\u{2D195}\u{2D196}\u{2D197}\u{2D198}\u{2D199}\u{2D19A}\u{2D19B}\u{2D19C}\u{2D19D}\u{2D19E}\u{2D19F}\u{2D1A0}\u{2D1A1}\u{2D1A2}\u{2D1A3}\u{2D1A4}\u{2D1A5}\u{2D1A6}\u{2D1A7}\u{2D1A8}\u{2D1A9}\u{2D1AA}\u{2D1AB}\u{2D1AC}\u{2D1AD}\u{2D1AE}\u{2D1AF}\u{2D1B0}\u{2D1B1}\u{2D1B2}\u{2D1B3}\u{2D1B4}\u{2D1B5}\u{2D1B6}\u{2D1B7}\u{2D1B8}\u{2D1B9}\u{2D1BA}\u{2D1BB}\u{2D1BC}\u{2D1BD}\u{2D1BE}\u{2D1BF}\u{2D1C0}\u{2D1C1}\u{2D1C2}\u{2D1C3}\u{2D1C4}\u{2D1C5}\u{2D1C6}\u{2D1C7}\u{2D1C8}\u{2D1C9}\u{2D1CA}\u{2D1CB}\u{2D1CC}\u{2D1CD}\u{2D1CE}\u{2D1CF}\u{2D1D0}\u{2D1D1}\u{2D1D2}\u{2D1D3}\u{2D1D4}\u{2D1D5}\u{2D1D6}\u{2D1D7}\u{2D1D8}\u{2D1D9}\u{2D1DA}\u{2D1DB}\u{2D1DC}\u{2D1DD}\u{2D1DE}\u{2D1DF}\u{2D1E0}\u{2D1E1}\u{2D1E2}\u{2D1E3}\u{2D1E4}\u{2D1E5}\u{2D1E6}\u{2D1E7}\u{2D1E8}\u{2D1E9}\u{2D1EA}\u{2D1EB}\u{2D1EC}\u{2D1ED}\u{2D1EE}\u{2D1EF}\u{2D1F0}\u{2D1F1}\u{2D1F2}\u{2D1F3}\u{2D1F4}\u{2D1F5}\u{2D1F6}\u{2D1F7}\u{2D1F8}\u{2D1F9}\u{2D1FA}\u{2D1FB}\u{2D1FC}\u{2D1FD}\u{2D1FE}\u{2D1FF}\u{2D200}\u{2D201}\u{2D202}\u{2D203}\u{2D204}\u{2D205}\u{2D206}\u{2D207}\u{2D208}\u{2D209}\u{2D20A}\u{2D20B}\u{2D20C}\u{2D20D}\u{2D20E}\u{2D20F}\u{2D210}\u{2D211}\u{2D212}\u{2D213}\u{2D214}\u{2D215}\u{2D216}\u{2D217}\u{2D218}\u{2D219}\u{2D21A}\u{2D21B}\u{2D21C}\u{2D21D}\u{2D21E}\u{2D21F}\u{2D220}\u{2D221}\u{2D222}\u{2D223}\u{2D224}\u{2D225}\u{2D226}\u{2D227}\u{2D228}\u{2D229}\u{2D22A}\u{2D22B}\u{2D22C}\u{2D22D}\u{2D22E}\u{2D22F}\u{2D230}\u{2D231}\u{2D232}\u{2D233}\u{2D234}\u{2D235}\u{2D236}\u{2D237}\u{2D238}\u{2D239}\u{2D23A}\u{2D23B}\u{2D23C}\u{2D23D}\u{2D23E}\u{2D23F}\u{2D240}\u{2D241}\u{2D242}\u{2D243}\u{2D244}\u{2D245}\u{2D246}\u{2D247}\u{2D248}\u{2D249}\u{2D24A}\u{2D24B}\u{2D24C}\u{2D24D}\u{2D24E}\u{2D24F}\u{2D250}\u{2D251}\u{2D252}\u{2D253}\u{2D254}\u{2D255}\u{2D256}\u{2D257}\u{2D258}\u{2D259}\u{2D25A}\u{2D25B}\u{2D25C}\u{2D25D}\u{2D25E}\u{2D25F}\u{2D260}\u{2D261}\u{2D262}\u{2D263}\u{2D264}\u{2D265}\u{2D266}\u{2D267}\u{2D268}\u{2D269}\u{2D26A}\u{2D26B}\u{2D26C}\u{2D26D}\u{2D26E}\u{2D26F}\u{2D270}\u{2D271}\u{2D272}\u{2D273}\u{2D274}\u{2D275}\u{2D276}\u{2D277}\u{2D278}\u{2D279}\u{2D27A}\u{2D27B}\u{2D27C}\u{2D27D}\u{2D27E}\u{2D27F}\u{2D280}\u{2D281}\u{2D282}\u{2D283}\u{2D284}\u{2D285}\u{2D286}\u{2D287}\u{2D288}\u{2D289}\u{2D28A}\u{2D28B}\u{2D28C}\u{2D28D}\u{2D28E}\u{2D28F}\u{2D290}\u{2D291}\u{2D292}\u{2D293}\u{2D294}\u{2D295}\u{2D296}\u{2D297}\u{2D298}\u{2D299}\u{2D29A}\u{2D29B}\u{2D29C}\u{2D29D}\u{2D29E}\u{2D29F}\u{2D2A0}\u{2D2A1}\u{2D2A2}\u{2D2A3}\u{2D2A4}\u{2D2A5}\u{2D2A6}\u{2D2A7}\u{2D2A8}\u{2D2A9}\u{2D2AA}\u{2D2AB}\u{2D2AC}\u{2D2AD}\u{2D2AE}\u{2D2AF}\u{2D2B0}\u{2D2B1}\u{2D2B2}\u{2D2B3}\u{2D2B4}\u{2D2B5}\u{2D2B6}\u{2D2B7}\u{2D2B8}\u{2D2B9}\u{2D2BA}\u{2D2BB}\u{2D2BC}\u{2D2BD}\u{2D2BE}\u{2D2BF}\u{2D2C0}\u{2D2C1}\u{2D2C2}\u{2D2C3}\u{2D2C4}\u{2D2C5}\u{2D2C6}\u{2D2C7}\u{2D2C8}\u{2D2C9}\u{2D2CA}\u{2D2CB}\u{2D2CC}\u{2D2CD}\u{2D2CE}\u{2D2CF}\u{2D2D0}\u{2D2D1}\u{2D2D2}\u{2D2D3}\u{2D2D4}\u{2D2D5}\u{2D2D6}\u{2D2D7}\u{2D2D8}\u{2D2D9}\u{2D2DA}\u{2D2DB}\u{2D2DC}\u{2D2DD}\u{2D2DE}\u{2D2DF}\u{2D2E0}\u{2D2E1}\u{2D2E2}\u{2D2E3}\u{2D2E4}\u{2D2E5}\u{2D2E6}\u{2D2E7}\u{2D2E8}\u{2D2E9}\u{2D2EA}\u{2D2EB}\u{2D2EC}\u{2D2ED}\u{2D2EE}\u{2D2EF}\u{2D2F0}\u{2D2F1}\u{2D2F2}\u{2D2F3}\u{2D2F4}\u{2D2F5}\u{2D2F6}\u{2D2F7}\u{2D2F8}\u{2D2F9}\u{2D2FA}\u{2D2FB}\u{2D2FC}\u{2D2FD}\u{2D2FE}\u{2D2FF}\u{2D300}\u{2D301}\u{2D302}\u{2D303}\u{2D304}\u{2D305}\u{2D306}\u{2D307}\u{2D308}\u{2D309}\u{2D30A}\u{2D30B}\u{2D30C}\u{2D30D}\u{2D30E}\u{2D30F}\u{2D310}\u{2D311}\u{2D312}\u{2D313}\u{2D314}\u{2D315}\u{2D316}\u{2D317}\u{2D318}\u{2D319}\u{2D31A}\u{2D31B}\u{2D31C}\u{2D31D}\u{2D31E}\u{2D31F}\u{2D320}\u{2D321}\u{2D322}\u{2D323}\u{2D324}\u{2D325}\u{2D326}\u{2D327}\u{2D328}\u{2D329}\u{2D32A}\u{2D32B}\u{2D32C}\u{2D32D}\u{2D32E}\u{2D32F}\u{2D330}\u{2D331}\u{2D332}\u{2D333}\u{2D334}\u{2D335}\u{2D336}\u{2D337}\u{2D338}\u{2D339}\u{2D33A}\u{2D33B}\u{2D33C}\u{2D33D}\u{2D33E}\u{2D33F}\u{2D340}\u{2D341}\u{2D342}\u{2D343}\u{2D344}\u{2D345}\u{2D346}\u{2D347}\u{2D348}\u{2D349}\u{2D34A}\u{2D34B}\u{2D34C}\u{2D34D}\u{2D34E}\u{2D34F}\u{2D350}\u{2D351}\u{2D352}\u{2D353}\u{2D354}\u{2D355}\u{2D356}\u{2D357}\u{2D358}\u{2D359}\u{2D35A}\u{2D35B}\u{2D35C}\u{2D35D}\u{2D35E}\u{2D35F}\u{2D360}\u{2D361}\u{2D362}\u{2D363}\u{2D364}\u{2D365}\u{2D366}\u{2D367}\u{2D368}\u{2D369}\u{2D36A}\u{2D36B}\u{2D36C}\u{2D36D}\u{2D36E}\u{2D36F}\u{2D370}\u{2D371}\u{2D372}\u{2D373}\u{2D374}\u{2D375}\u{2D376}\u{2D377}\u{2D378}\u{2D379}\u{2D37A}\u{2D37B}\u{2D37C}\u{2D37D}\u{2D37E}\u{2D37F}\u{2D380}\u{2D381}\u{2D382}\u{2D383}\u{2D384}\u{2D385}\u{2D386}\u{2D387}\u{2D388}\u{2D389}\u{2D38A}\u{2D38B}\u{2D38C}\u{2D38D}\u{2D38E}\u{2D38F}\u{2D390}\u{2D391}\u{2D392}\u{2D393}\u{2D394}\u{2D395}\u{2D396}\u{2D397}\u{2D398}\u{2D399}\u{2D39A}\u{2D39B}\u{2D39C}\u{2D39D}\u{2D39E}\u{2D39F}\u{2D3A0}\u{2D3A1}\u{2D3A2}\u{2D3A3}\u{2D3A4}\u{2D3A5}\u{2D3A6}\u{2D3A7}\u{2D3A8}\u{2D3A9}\u{2D3AA}\u{2D3AB}\u{2D3AC}\u{2D3AD}\u{2D3AE}\u{2D3AF}\u{2D3B0}\u{2D3B1}\u{2D3B2}\u{2D3B3}\u{2D3B4}\u{2D3B5}\u{2D3B6}\u{2D3B7}\u{2D3B8}\u{2D3B9}\u{2D3BA}\u{2D3BB}\u{2D3BC}\u{2D3BD}\u{2D3BE}\u{2D3BF}\u{2D3C0}\u{2D3C1}\u{2D3C2}\u{2D3C3}\u{2D3C4}\u{2D3C5}\u{2D3C6}\u{2D3C7}\u{2D3C8}\u{2D3C9}\u{2D3CA}\u{2D3CB}\u{2D3CC}\u{2D3CD}\u{2D3CE}\u{2D3CF}\u{2D3D0}\u{2D3D1}\u{2D3D2}\u{2D3D3}\u{2D3D4}\u{2D3D5}\u{2D3D6}\u{2D3D7}\u{2D3D8}\u{2D3D9}\u{2D3DA}\u{2D3DB}\u{2D3DC}\u{2D3DD}\u{2D3DE}\u{2D3DF}\u{2D3E0}\u{2D3E1}\u{2D3E2}\u{2D3E3}\u{2D3E4}\u{2D3E5}\u{2D3E6}\u{2D3E7}\u{2D3E8}\u{2D3E9}\u{2D3EA}\u{2D3EB}\u{2D3EC}\u{2D3ED}\u{2D3EE}\u{2D3EF}\u{2D3F0}\u{2D3F1}\u{2D3F2}\u{2D3F3}\u{2D3F4}\u{2D3F5}\u{2D3F6}\u{2D3F7}\u{2D3F8}\u{2D3F9}\u{2D3FA}\u{2D3FB}\u{2D3FC}\u{2D3FD}\u{2D3FE}\u{2D3FF}\u{2D400}\u{2D401}\u{2D402}\u{2D403}\u{2D404}\u{2D405}\u{2D406}\u{2D407}\u{2D408}\u{2D409}\u{2D40A}\u{2D40B}\u{2D40C}\u{2D40D}\u{2D40E}\u{2D40F}\u{2D410}\u{2D411}\u{2D412}\u{2D413}\u{2D414}\u{2D415}\u{2D416}\u{2D417}\u{2D418}\u{2D419}\u{2D41A}\u{2D41B}\u{2D41C}\u{2D41D}\u{2D41E}\u{2D41F}\u{2D420}\u{2D421}\u{2D422}\u{2D423}\u{2D424}\u{2D425}\u{2D426}\u{2D427}\u{2D428}\u{2D429}\u{2D42A}\u{2D42B}\u{2D42C}\u{2D42D}\u{2D42E}\u{2D42F}\u{2D430}\u{2D431}\u{2D432}\u{2D433}\u{2D434}\u{2D435}\u{2D436}\u{2D437}\u{2D438}\u{2D439}\u{2D43A}\u{2D43B}\u{2D43C}\u{2D43D}\u{2D43E}\u{2D43F}\u{2D440}\u{2D441}\u{2D442}\u{2D443}\u{2D444}\u{2D445}\u{2D446}\u{2D447}\u{2D448}\u{2D449}\u{2D44A}\u{2D44B}\u{2D44C}\u{2D44D}\u{2D44E}\u{2D44F}\u{2D450}\u{2D451}\u{2D452}\u{2D453}\u{2D454}\u{2D455}\u{2D456}\u{2D457}\u{2D458}\u{2D459}\u{2D45A}\u{2D45B}\u{2D45C}\u{2D45D}\u{2D45E}\u{2D45F}\u{2D460}\u{2D461}\u{2D462}\u{2D463}\u{2D464}\u{2D465}\u{2D466}\u{2D467}\u{2D468}\u{2D469}\u{2D46A}\u{2D46B}\u{2D46C}\u{2D46D}\u{2D46E}\u{2D46F}\u{2D470}\u{2D471}\u{2D472}\u{2D473}\u{2D474}\u{2D475}\u{2D476}\u{2D477}\u{2D478}\u{2D479}\u{2D47A}\u{2D47B}\u{2D47C}\u{2D47D}\u{2D47E}\u{2D47F}\u{2D480}\u{2D481}\u{2D482}\u{2D483}\u{2D484}\u{2D485}\u{2D486}\u{2D487}\u{2D488}\u{2D489}\u{2D48A}\u{2D48B}\u{2D48C}\u{2D48D}\u{2D48E}\u{2D48F}\u{2D490}\u{2D491}\u{2D492}\u{2D493}\u{2D494}\u{2D495}\u{2D496}\u{2D497}\u{2D498}\u{2D499}\u{2D49A}\u{2D49B}\u{2D49C}\u{2D49D}\u{2D49E}\u{2D49F}\u{2D4A0}\u{2D4A1}\u{2D4A2}\u{2D4A3}\u{2D4A4}\u{2D4A5}\u{2D4A6}\u{2D4A7}\u{2D4A8}\u{2D4A9}\u{2D4AA}\u{2D4AB}\u{2D4AC}\u{2D4AD}\u{2D4AE}\u{2D4AF}\u{2D4B0}\u{2D4B1}\u{2D4B2}\u{2D4B3}\u{2D4B4}\u{2D4B5}\u{2D4B6}\u{2D4B7}\u{2D4B8}\u{2D4B9}\u{2D4BA}\u{2D4BB}\u{2D4BC}\u{2D4BD}\u{2D4BE}\u{2D4BF}\u{2D4C0}\u{2D4C1}\u{2D4C2}\u{2D4C3}\u{2D4C4}\u{2D4C5}\u{2D4C6}\u{2D4C7}\u{2D4C8}\u{2D4C9}\u{2D4CA}\u{2D4CB}\u{2D4CC}\u{2D4CD}\u{2D4CE}\u{2D4CF}\u{2D4D0}\u{2D4D1}\u{2D4D2}\u{2D4D3}\u{2D4D4}\u{2D4D5}\u{2D4D6}\u{2D4D7}\u{2D4D8}\u{2D4D9}\u{2D4DA}\u{2D4DB}\u{2D4DC}\u{2D4DD}\u{2D4DE}\u{2D4DF}\u{2D4E0}\u{2D4E1}\u{2D4E2}\u{2D4E3}\u{2D4E4}\u{2D4E5}\u{2D4E6}\u{2D4E7}\u{2D4E8}\u{2D4E9}\u{2D4EA}\u{2D4EB}\u{2D4EC}\u{2D4ED}\u{2D4EE}\u{2D4EF}\u{2D4F0}\u{2D4F1}\u{2D4F2}\u{2D4F3}\u{2D4F4}\u{2D4F5}\u{2D4F6}\u{2D4F7}\u{2D4F8}\u{2D4F9}\u{2D4FA}\u{2D4FB}\u{2D4FC}\u{2D4FD}\u{2D4FE}\u{2D4FF}\u{2D500}\u{2D501}\u{2D502}\u{2D503}\u{2D504}\u{2D505}\u{2D506}\u{2D507}\u{2D508}\u{2D509}\u{2D50A}\u{2D50B}\u{2D50C}\u{2D50D}\u{2D50E}\u{2D50F}\u{2D510}\u{2D511}\u{2D512}\u{2D513}\u{2D514}\u{2D515}\u{2D516}\u{2D517}\u{2D518}\u{2D519}\u{2D51A}\u{2D51B}\u{2D51C}\u{2D51D}\u{2D51E}\u{2D51F}\u{2D520}\u{2D521}\u{2D522}\u{2D523}\u{2D524}\u{2D525}\u{2D526}\u{2D527}\u{2D528}\u{2D529}\u{2D52A}\u{2D52B}\u{2D52C}\u{2D52D}\u{2D52E}\u{2D52F}\u{2D530}\u{2D531}\u{2D532}\u{2D533}\u{2D534}\u{2D535}\u{2D536}\u{2D537}\u{2D538}\u{2D539}\u{2D53A}\u{2D53B}\u{2D53C}\u{2D53D}\u{2D53E}\u{2D53F}\u{2D540}\u{2D541}\u{2D542}\u{2D543}\u{2D544}\u{2D545}\u{2D546}\u{2D547}\u{2D548}\u{2D549}\u{2D54A}\u{2D54B}\u{2D54C}\u{2D54D}\u{2D54E}\u{2D54F}\u{2D550}\u{2D551}\u{2D552}\u{2D553}\u{2D554}\u{2D555}\u{2D556}\u{2D557}\u{2D558}\u{2D559}\u{2D55A}\u{2D55B}\u{2D55C}\u{2D55D}\u{2D55E}\u{2D55F}\u{2D560}\u{2D561}\u{2D562}\u{2D563}\u{2D564}\u{2D565}\u{2D566}\u{2D567}\u{2D568}\u{2D569}\u{2D56A}\u{2D56B}\u{2D56C}\u{2D56D}\u{2D56E}\u{2D56F}\u{2D570}\u{2D571}\u{2D572}\u{2D573}\u{2D574}\u{2D575}\u{2D576}\u{2D577}\u{2D578}\u{2D579}\u{2D57A}\u{2D57B}\u{2D57C}\u{2D57D}\u{2D57E}\u{2D57F}\u{2D580}\u{2D581}\u{2D582}\u{2D583}\u{2D584}\u{2D585}\u{2D586}\u{2D587}\u{2D588}\u{2D589}\u{2D58A}\u{2D58B}\u{2D58C}\u{2D58D}\u{2D58E}\u{2D58F}\u{2D590}\u{2D591}\u{2D592}\u{2D593}\u{2D594}\u{2D595}\u{2D596}\u{2D597}\u{2D598}\u{2D599}\u{2D59A}\u{2D59B}\u{2D59C}\u{2D59D}\u{2D59E}\u{2D59F}\u{2D5A0}\u{2D5A1}\u{2D5A2}\u{2D5A3}\u{2D5A4}\u{2D5A5}\u{2D5A6}\u{2D5A7}\u{2D5A8}\u{2D5A9}\u{2D5AA}\u{2D5AB}\u{2D5AC}\u{2D5AD}\u{2D5AE}\u{2D5AF}\u{2D5B0}\u{2D5B1}\u{2D5B2}\u{2D5B3}\u{2D5B4}\u{2D5B5}\u{2D5B6}\u{2D5B7}\u{2D5B8}\u{2D5B9}\u{2D5BA}\u{2D5BB}\u{2D5BC}\u{2D5BD}\u{2D5BE}\u{2D5BF}\u{2D5C0}\u{2D5C1}\u{2D5C2}\u{2D5C3}\u{2D5C4}\u{2D5C5}\u{2D5C6}\u{2D5C7}\u{2D5C8}\u{2D5C9}\u{2D5CA}\u{2D5CB}\u{2D5CC}\u{2D5CD}\u{2D5CE}\u{2D5CF}\u{2D5D0}\u{2D5D1}\u{2D5D2}\u{2D5D3}\u{2D5D4}\u{2D5D5}\u{2D5D6}\u{2D5D7}\u{2D5D8}\u{2D5D9}\u{2D5DA}\u{2D5DB}\u{2D5DC}\u{2D5DD}\u{2D5DE}\u{2D5DF}\u{2D5E0}\u{2D5E1}\u{2D5E2}\u{2D5E3}\u{2D5E4}\u{2D5E5}\u{2D5E6}\u{2D5E7}\u{2D5E8}\u{2D5E9}\u{2D5EA}\u{2D5EB}\u{2D5EC}\u{2D5ED}\u{2D5EE}\u{2D5EF}\u{2D5F0}\u{2D5F1}\u{2D5F2}\u{2D5F3}\u{2D5F4}\u{2D5F5}\u{2D5F6}\u{2D5F7}\u{2D5F8}\u{2D5F9}\u{2D5FA}\u{2D5FB}\u{2D5FC}\u{2D5FD}\u{2D5FE}\u{2D5FF}\u{2D600}\u{2D601}\u{2D602}\u{2D603}\u{2D604}\u{2D605}\u{2D606}\u{2D607}\u{2D608}\u{2D609}\u{2D60A}\u{2D60B}\u{2D60C}\u{2D60D}\u{2D60E}\u{2D60F}\u{2D610}\u{2D611}\u{2D612}\u{2D613}\u{2D614}\u{2D615}\u{2D616}\u{2D617}\u{2D618}\u{2D619}\u{2D61A}\u{2D61B}\u{2D61C}\u{2D61D}\u{2D61E}\u{2D61F}\u{2D620}\u{2D621}\u{2D622}\u{2D623}\u{2D624}\u{2D625}\u{2D626}\u{2D627}\u{2D628}\u{2D629}\u{2D62A}\u{2D62B}\u{2D62C}\u{2D62D}\u{2D62E}\u{2D62F}\u{2D630}\u{2D631}\u{2D632}\u{2D633}\u{2D634}\u{2D635}\u{2D636}\u{2D637}\u{2D638}\u{2D639}\u{2D63A}\u{2D63B}\u{2D63C}\u{2D63D}\u{2D63E}\u{2D63F}\u{2D640}\u{2D641}\u{2D642}\u{2D643}\u{2D644}\u{2D645}\u{2D646}\u{2D647}\u{2D648}\u{2D649}\u{2D64A}\u{2D64B}\u{2D64C}\u{2D64D}\u{2D64E}\u{2D64F}\u{2D650}\u{2D651}\u{2D652}\u{2D653}\u{2D654}\u{2D655}\u{2D656}\u{2D657}\u{2D658}\u{2D659}\u{2D65A}\u{2D65B}\u{2D65C}\u{2D65D}\u{2D65E}\u{2D65F}\u{2D660}\u{2D661}\u{2D662}\u{2D663}\u{2D664}\u{2D665}\u{2D666}\u{2D667}\u{2D668}\u{2D669}\u{2D66A}\u{2D66B}\u{2D66C}\u{2D66D}\u{2D66E}\u{2D66F}\u{2D670}\u{2D671}\u{2D672}\u{2D673}\u{2D674}\u{2D675}\u{2D676}\u{2D677}\u{2D678}\u{2D679}\u{2D67A}\u{2D67B}\u{2D67C}\u{2D67D}\u{2D67E}\u{2D67F}\u{2D680}\u{2D681}\u{2D682}\u{2D683}\u{2D684}\u{2D685}\u{2D686}\u{2D687}\u{2D688}\u{2D689}\u{2D68A}\u{2D68B}\u{2D68C}\u{2D68D}\u{2D68E}\u{2D68F}\u{2D690}\u{2D691}\u{2D692}\u{2D693}\u{2D694}\u{2D695}\u{2D696}\u{2D697}\u{2D698}\u{2D699}\u{2D69A}\u{2D69B}\u{2D69C}\u{2D69D}\u{2D69E}\u{2D69F}\u{2D6A0}\u{2D6A1}\u{2D6A2}\u{2D6A3}\u{2D6A4}\u{2D6A5}\u{2D6A6}\u{2D6A7}\u{2D6A8}\u{2D6A9}\u{2D6AA}\u{2D6AB}\u{2D6AC}\u{2D6AD}\u{2D6AE}\u{2D6AF}\u{2D6B0}\u{2D6B1}\u{2D6B2}\u{2D6B3}\u{2D6B4}\u{2D6B5}\u{2D6B6}\u{2D6B7}\u{2D6B8}\u{2D6B9}\u{2D6BA}\u{2D6BB}\u{2D6BC}\u{2D6BD}\u{2D6BE}\u{2D6BF}\u{2D6C0}\u{2D6C1}\u{2D6C2}\u{2D6C3}\u{2D6C4}\u{2D6C5}\u{2D6C6}\u{2D6C7}\u{2D6C8}\u{2D6C9}\u{2D6CA}\u{2D6CB}\u{2D6CC}\u{2D6CD}\u{2D6CE}\u{2D6CF}\u{2D6D0}\u{2D6D1}\u{2D6D2}\u{2D6D3}\u{2D6D4}\u{2D6D5}\u{2D6D6}\u{2D6D7}\u{2D6D8}\u{2D6D9}\u{2D6DA}\u{2D6DB}\u{2D6DC}\u{2D6DD}\u{2D6DE}\u{2D6DF}\u{2D6E0}\u{2D6E1}\u{2D6E2}\u{2D6E3}\u{2D6E4}\u{2D6E5}\u{2D6E6}\u{2D6E7}\u{2D6E8}\u{2D6E9}\u{2D6EA}\u{2D6EB}\u{2D6EC}\u{2D6ED}\u{2D6EE}\u{2D6EF}\u{2D6F0}\u{2D6F1}\u{2D6F2}\u{2D6F3}\u{2D6F4}\u{2D6F5}\u{2D6F6}\u{2D6F7}\u{2D6F8}\u{2D6F9}\u{2D6FA}\u{2D6FB}\u{2D6FC}\u{2D6FD}\u{2D6FE}\u{2D6FF}\u{2D700}\u{2D701}\u{2D702}\u{2D703}\u{2D704}\u{2D705}\u{2D706}\u{2D707}\u{2D708}\u{2D709}\u{2D70A}\u{2D70B}\u{2D70C}\u{2D70D}\u{2D70E}\u{2D70F}\u{2D710}\u{2D711}\u{2D712}\u{2D713}\u{2D714}\u{2D715}\u{2D716}\u{2D717}\u{2D718}\u{2D719}\u{2D71A}\u{2D71B}\u{2D71C}\u{2D71D}\u{2D71E}\u{2D71F}\u{2D720}\u{2D721}\u{2D722}\u{2D723}\u{2D724}\u{2D725}\u{2D726}\u{2D727}\u{2D728}\u{2D729}\u{2D72A}\u{2D72B}\u{2D72C}\u{2D72D}\u{2D72E}\u{2D72F}\u{2D730}\u{2D731}\u{2D732}\u{2D733}\u{2D734}\u{2D735}\u{2D736}\u{2D737}\u{2D738}\u{2D739}\u{2D73A}\u{2D73B}\u{2D73C}\u{2D73D}\u{2D73E}\u{2D73F}\u{2D740}\u{2D741}\u{2D742}\u{2D743}\u{2D744}\u{2D745}\u{2D746}\u{2D747}\u{2D748}\u{2D749}\u{2D74A}\u{2D74B}\u{2D74C}\u{2D74D}\u{2D74E}\u{2D74F}\u{2D750}\u{2D751}\u{2D752}\u{2D753}\u{2D754}\u{2D755}\u{2D756}\u{2D757}\u{2D758}\u{2D759}\u{2D75A}\u{2D75B}\u{2D75C}\u{2D75D}\u{2D75E}\u{2D75F}\u{2D760}\u{2D761}\u{2D762}\u{2D763}\u{2D764}\u{2D765}\u{2D766}\u{2D767}\u{2D768}\u{2D769}\u{2D76A}\u{2D76B}\u{2D76C}\u{2D76D}\u{2D76E}\u{2D76F}\u{2D770}\u{2D771}\u{2D772}\u{2D773}\u{2D774}\u{2D775}\u{2D776}\u{2D777}\u{2D778}\u{2D779}\u{2D77A}\u{2D77B}\u{2D77C}\u{2D77D}\u{2D77E}\u{2D77F}\u{2D780}\u{2D781}\u{2D782}\u{2D783}\u{2D784}\u{2D785}\u{2D786}\u{2D787}\u{2D788}\u{2D789}\u{2D78A}\u{2D78B}\u{2D78C}\u{2D78D}\u{2D78E}\u{2D78F}\u{2D790}\u{2D791}\u{2D792}\u{2D793}\u{2D794}\u{2D795}\u{2D796}\u{2D797}\u{2D798}\u{2D799}\u{2D79A}\u{2D79B}\u{2D79C}\u{2D79D}\u{2D79E}\u{2D79F}\u{2D7A0}\u{2D7A1}\u{2D7A2}\u{2D7A3}\u{2D7A4}\u{2D7A5}\u{2D7A6}\u{2D7A7}\u{2D7A8}\u{2D7A9}\u{2D7AA}\u{2D7AB}\u{2D7AC}\u{2D7AD}\u{2D7AE}\u{2D7AF}\u{2D7B0}\u{2D7B1}\u{2D7B2}\u{2D7B3}\u{2D7B4}\u{2D7B5}\u{2D7B6}\u{2D7B7}\u{2D7B8}\u{2D7B9}\u{2D7BA}\u{2D7BB}\u{2D7BC}\u{2D7BD}\u{2D7BE}\u{2D7BF}\u{2D7C0}\u{2D7C1}\u{2D7C2}\u{2D7C3}\u{2D7C4}\u{2D7C5}\u{2D7C6}\u{2D7C7}\u{2D7C8}\u{2D7C9}\u{2D7CA}\u{2D7CB}\u{2D7CC}\u{2D7CD}\u{2D7CE}\u{2D7CF}\u{2D7D0}\u{2D7D1}\u{2D7D2}\u{2D7D3}\u{2D7D4}\u{2D7D5}\u{2D7D6}\u{2D7D7}\u{2D7D8}\u{2D7D9}\u{2D7DA}\u{2D7DB}\u{2D7DC}\u{2D7DD}\u{2D7DE}\u{2D7DF}\u{2D7E0}\u{2D7E1}\u{2D7E2}\u{2D7E3}\u{2D7E4}\u{2D7E5}\u{2D7E6}\u{2D7E7}\u{2D7E8}\u{2D7E9}\u{2D7EA}\u{2D7EB}\u{2D7EC}\u{2D7ED}\u{2D7EE}\u{2D7EF}\u{2D7F0}\u{2D7F1}\u{2D7F2}\u{2D7F3}\u{2D7F4}\u{2D7F5}\u{2D7F6}\u{2D7F7}\u{2D7F8}\u{2D7F9}\u{2D7FA}\u{2D7FB}\u{2D7FC}\u{2D7FD}\u{2D7FE}\u{2D7FF}\u{2D800}\u{2D801}\u{2D802}\u{2D803}\u{2D804}\u{2D805}\u{2D806}\u{2D807}\u{2D808}\u{2D809}\u{2D80A}\u{2D80B}\u{2D80C}\u{2D80D}\u{2D80E}\u{2D80F}\u{2D810}\u{2D811}\u{2D812}\u{2D813}\u{2D814}\u{2D815}\u{2D816}\u{2D817}\u{2D818}\u{2D819}\u{2D81A}\u{2D81B}\u{2D81C}\u{2D81D}\u{2D81E}\u{2D81F}\u{2D820}\u{2D821}\u{2D822}\u{2D823}\u{2D824}\u{2D825}\u{2D826}\u{2D827}\u{2D828}\u{2D829}\u{2D82A}\u{2D82B}\u{2D82C}\u{2D82D}\u{2D82E}\u{2D82F}\u{2D830}\u{2D831}\u{2D832}\u{2D833}\u{2D834}\u{2D835}\u{2D836}\u{2D837}\u{2D838}\u{2D839}\u{2D83A}\u{2D83B}\u{2D83C}\u{2D83D}\u{2D83E}\u{2D83F}\u{2D840}\u{2D841}\u{2D842}\u{2D843}\u{2D844}\u{2D845}\u{2D846}\u{2D847}\u{2D848}\u{2D849}\u{2D84A}\u{2D84B}\u{2D84C}\u{2D84D}\u{2D84E}\u{2D84F}\u{2D850}\u{2D851}\u{2D852}\u{2D853}\u{2D854}\u{2D855}\u{2D856}\u{2D857}\u{2D858}\u{2D859}\u{2D85A}\u{2D85B}\u{2D85C}\u{2D85D}\u{2D85E}\u{2D85F}\u{2D860}\u{2D861}\u{2D862}\u{2D863}\u{2D864}\u{2D865}\u{2D866}\u{2D867}\u{2D868}\u{2D869}\u{2D86A}\u{2D86B}\u{2D86C}\u{2D86D}\u{2D86E}\u{2D86F}\u{2D870}\u{2D871}\u{2D872}\u{2D873}\u{2D874}\u{2D875}\u{2D876}\u{2D877}\u{2D878}\u{2D879}\u{2D87A}\u{2D87B}\u{2D87C}\u{2D87D}\u{2D87E}\u{2D87F}\u{2D880}\u{2D881}\u{2D882}\u{2D883}\u{2D884}\u{2D885}\u{2D886}\u{2D887}\u{2D888}\u{2D889}\u{2D88A}\u{2D88B}\u{2D88C}\u{2D88D}\u{2D88E}\u{2D88F}\u{2D890}\u{2D891}\u{2D892}\u{2D893}\u{2D894}\u{2D895}\u{2D896}\u{2D897}\u{2D898}\u{2D899}\u{2D89A}\u{2D89B}\u{2D89C}\u{2D89D}\u{2D89E}\u{2D89F}\u{2D8A0}\u{2D8A1}\u{2D8A2}\u{2D8A3}\u{2D8A4}\u{2D8A5}\u{2D8A6}\u{2D8A7}\u{2D8A8}\u{2D8A9}\u{2D8AA}\u{2D8AB}\u{2D8AC}\u{2D8AD}\u{2D8AE}\u{2D8AF}\u{2D8B0}\u{2D8B1}\u{2D8B2}\u{2D8B3}\u{2D8B4}\u{2D8B5}\u{2D8B6}\u{2D8B7}\u{2D8B8}\u{2D8B9}\u{2D8BA}\u{2D8BB}\u{2D8BC}\u{2D8BD}\u{2D8BE}\u{2D8BF}\u{2D8C0}\u{2D8C1}\u{2D8C2}\u{2D8C3}\u{2D8C4}\u{2D8C5}\u{2D8C6}\u{2D8C7}\u{2D8C8}\u{2D8C9}\u{2D8CA}\u{2D8CB}\u{2D8CC}\u{2D8CD}\u{2D8CE}\u{2D8CF}\u{2D8D0}\u{2D8D1}\u{2D8D2}\u{2D8D3}\u{2D8D4}\u{2D8D5}\u{2D8D6}\u{2D8D7}\u{2D8D8}\u{2D8D9}\u{2D8DA}\u{2D8DB}\u{2D8DC}\u{2D8DD}\u{2D8DE}\u{2D8DF}\u{2D8E0}\u{2D8E1}\u{2D8E2}\u{2D8E3}\u{2D8E4}\u{2D8E5}\u{2D8E6}\u{2D8E7}\u{2D8E8}\u{2D8E9}\u{2D8EA}\u{2D8EB}\u{2D8EC}\u{2D8ED}\u{2D8EE}\u{2D8EF}\u{2D8F0}\u{2D8F1}\u{2D8F2}\u{2D8F3}\u{2D8F4}\u{2D8F5}\u{2D8F6}\u{2D8F7}\u{2D8F8}\u{2D8F9}\u{2D8FA}\u{2D8FB}\u{2D8FC}\u{2D8FD}\u{2D8FE}\u{2D8FF}\u{2D900}\u{2D901}\u{2D902}\u{2D903}\u{2D904}\u{2D905}\u{2D906}\u{2D907}\u{2D908}\u{2D909}\u{2D90A}\u{2D90B}\u{2D90C}\u{2D90D}\u{2D90E}\u{2D90F}\u{2D910}\u{2D911}\u{2D912}\u{2D913}\u{2D914}\u{2D915}\u{2D916}\u{2D917}\u{2D918}\u{2D919}\u{2D91A}\u{2D91B}\u{2D91C}\u{2D91D}\u{2D91E}\u{2D91F}\u{2D920}\u{2D921}\u{2D922}\u{2D923}\u{2D924}\u{2D925}\u{2D926}\u{2D927}\u{2D928}\u{2D929}\u{2D92A}\u{2D92B}\u{2D92C}\u{2D92D}\u{2D92E}\u{2D92F}\u{2D930}\u{2D931}\u{2D932}\u{2D933}\u{2D934}\u{2D935}\u{2D936}\u{2D937}\u{2D938}\u{2D939}\u{2D93A}\u{2D93B}\u{2D93C}\u{2D93D}\u{2D93E}\u{2D93F}\u{2D940}\u{2D941}\u{2D942}\u{2D943}\u{2D944}\u{2D945}\u{2D946}\u{2D947}\u{2D948}\u{2D949}\u{2D94A}\u{2D94B}\u{2D94C}\u{2D94D}\u{2D94E}\u{2D94F}\u{2D950}\u{2D951}\u{2D952}\u{2D953}\u{2D954}\u{2D955}\u{2D956}\u{2D957}\u{2D958}\u{2D959}\u{2D95A}\u{2D95B}\u{2D95C}\u{2D95D}\u{2D95E}\u{2D95F}\u{2D960}\u{2D961}\u{2D962}\u{2D963}\u{2D964}\u{2D965}\u{2D966}\u{2D967}\u{2D968}\u{2D969}\u{2D96A}\u{2D96B}\u{2D96C}\u{2D96D}\u{2D96E}\u{2D96F}\u{2D970}\u{2D971}\u{2D972}\u{2D973}\u{2D974}\u{2D975}\u{2D976}\u{2D977}\u{2D978}\u{2D979}\u{2D97A}\u{2D97B}\u{2D97C}\u{2D97D}\u{2D97E}\u{2D97F}\u{2D980}\u{2D981}\u{2D982}\u{2D983}\u{2D984}\u{2D985}\u{2D986}\u{2D987}\u{2D988}\u{2D989}\u{2D98A}\u{2D98B}\u{2D98C}\u{2D98D}\u{2D98E}\u{2D98F}\u{2D990}\u{2D991}\u{2D992}\u{2D993}\u{2D994}\u{2D995}\u{2D996}\u{2D997}\u{2D998}\u{2D999}\u{2D99A}\u{2D99B}\u{2D99C}\u{2D99D}\u{2D99E}\u{2D99F}\u{2D9A0}\u{2D9A1}\u{2D9A2}\u{2D9A3}\u{2D9A4}\u{2D9A5}\u{2D9A6}\u{2D9A7}\u{2D9A8}\u{2D9A9}\u{2D9AA}\u{2D9AB}\u{2D9AC}\u{2D9AD}\u{2D9AE}\u{2D9AF}\u{2D9B0}\u{2D9B1}\u{2D9B2}\u{2D9B3}\u{2D9B4}\u{2D9B5}\u{2D9B6}\u{2D9B7}\u{2D9B8}\u{2D9B9}\u{2D9BA}\u{2D9BB}\u{2D9BC}\u{2D9BD}\u{2D9BE}\u{2D9BF}\u{2D9C0}\u{2D9C1}\u{2D9C2}\u{2D9C3}\u{2D9C4}\u{2D9C5}\u{2D9C6}\u{2D9C7}\u{2D9C8}\u{2D9C9}\u{2D9CA}\u{2D9CB}\u{2D9CC}\u{2D9CD}\u{2D9CE}\u{2D9CF}\u{2D9D0}\u{2D9D1}\u{2D9D2}\u{2D9D3}\u{2D9D4}\u{2D9D5}\u{2D9D6}\u{2D9D7}\u{2D9D8}\u{2D9D9}\u{2D9DA}\u{2D9DB}\u{2D9DC}\u{2D9DD}\u{2D9DE}\u{2D9DF}\u{2D9E0}\u{2D9E1}\u{2D9E2}\u{2D9E3}\u{2D9E4}\u{2D9E5}\u{2D9E6}\u{2D9E7}\u{2D9E8}\u{2D9E9}\u{2D9EA}\u{2D9EB}\u{2D9EC}\u{2D9ED}\u{2D9EE}\u{2D9EF}\u{2D9F0}\u{2D9F1}\u{2D9F2}\u{2D9F3}\u{2D9F4}\u{2D9F5}\u{2D9F6}\u{2D9F7}\u{2D9F8}\u{2D9F9}\u{2D9FA}\u{2D9FB}\u{2D9FC}\u{2D9FD}\u{2D9FE}\u{2D9FF}\u{2DA00}\u{2DA01}\u{2DA02}\u{2DA03}\u{2DA04}\u{2DA05}\u{2DA06}\u{2DA07}\u{2DA08}\u{2DA09}\u{2DA0A}\u{2DA0B}\u{2DA0C}\u{2DA0D}\u{2DA0E}\u{2DA0F}\u{2DA10}\u{2DA11}\u{2DA12}\u{2DA13}\u{2DA14}\u{2DA15}\u{2DA16}\u{2DA17}\u{2DA18}\u{2DA19}\u{2DA1A}\u{2DA1B}\u{2DA1C}\u{2DA1D}\u{2DA1E}\u{2DA1F}\u{2DA20}\u{2DA21}\u{2DA22}\u{2DA23}\u{2DA24}\u{2DA25}\u{2DA26}\u{2DA27}\u{2DA28}\u{2DA29}\u{2DA2A}\u{2DA2B}\u{2DA2C}\u{2DA2D}\u{2DA2E}\u{2DA2F}\u{2DA30}\u{2DA31}\u{2DA32}\u{2DA33}\u{2DA34}\u{2DA35}\u{2DA36}\u{2DA37}\u{2DA38}\u{2DA39}\u{2DA3A}\u{2DA3B}\u{2DA3C}\u{2DA3D}\u{2DA3E}\u{2DA3F}\u{2DA40}\u{2DA41}\u{2DA42}\u{2DA43}\u{2DA44}\u{2DA45}\u{2DA46}\u{2DA47}\u{2DA48}\u{2DA49}\u{2DA4A}\u{2DA4B}\u{2DA4C}\u{2DA4D}\u{2DA4E}\u{2DA4F}\u{2DA50}\u{2DA51}\u{2DA52}\u{2DA53}\u{2DA54}\u{2DA55}\u{2DA56}\u{2DA57}\u{2DA58}\u{2DA59}\u{2DA5A}\u{2DA5B}\u{2DA5C}\u{2DA5D}\u{2DA5E}\u{2DA5F}\u{2DA60}\u{2DA61}\u{2DA62}\u{2DA63}\u{2DA64}\u{2DA65}\u{2DA66}\u{2DA67}\u{2DA68}\u{2DA69}\u{2DA6A}\u{2DA6B}\u{2DA6C}\u{2DA6D}\u{2DA6E}\u{2DA6F}\u{2DA70}\u{2DA71}\u{2DA72}\u{2DA73}\u{2DA74}\u{2DA75}\u{2DA76}\u{2DA77}\u{2DA78}\u{2DA79}\u{2DA7A}\u{2DA7B}\u{2DA7C}\u{2DA7D}\u{2DA7E}\u{2DA7F}\u{2DA80}\u{2DA81}\u{2DA82}\u{2DA83}\u{2DA84}\u{2DA85}\u{2DA86}\u{2DA87}\u{2DA88}\u{2DA89}\u{2DA8A}\u{2DA8B}\u{2DA8C}\u{2DA8D}\u{2DA8E}\u{2DA8F}\u{2DA90}\u{2DA91}\u{2DA92}\u{2DA93}\u{2DA94}\u{2DA95}\u{2DA96}\u{2DA97}\u{2DA98}\u{2DA99}\u{2DA9A}\u{2DA9B}\u{2DA9C}\u{2DA9D}\u{2DA9E}\u{2DA9F}\u{2DAA0}\u{2DAA1}\u{2DAA2}\u{2DAA3}\u{2DAA4}\u{2DAA5}\u{2DAA6}\u{2DAA7}\u{2DAA8}\u{2DAA9}\u{2DAAA}\u{2DAAB}\u{2DAAC}\u{2DAAD}\u{2DAAE}\u{2DAAF}\u{2DAB0}\u{2DAB1}\u{2DAB2}\u{2DAB3}\u{2DAB4}\u{2DAB5}\u{2DAB6}\u{2DAB7}\u{2DAB8}\u{2DAB9}\u{2DABA}\u{2DABB}\u{2DABC}\u{2DABD}\u{2DABE}\u{2DABF}\u{2DAC0}\u{2DAC1}\u{2DAC2}\u{2DAC3}\u{2DAC4}\u{2DAC5}\u{2DAC6}\u{2DAC7}\u{2DAC8}\u{2DAC9}\u{2DACA}\u{2DACB}\u{2DACC}\u{2DACD}\u{2DACE}\u{2DACF}\u{2DAD0}\u{2DAD1}\u{2DAD2}\u{2DAD3}\u{2DAD4}\u{2DAD5}\u{2DAD6}\u{2DAD7}\u{2DAD8}\u{2DAD9}\u{2DADA}\u{2DADB}\u{2DADC}\u{2DADD}\u{2DADE}\u{2DADF}\u{2DAE0}\u{2DAE1}\u{2DAE2}\u{2DAE3}\u{2DAE4}\u{2DAE5}\u{2DAE6}\u{2DAE7}\u{2DAE8}\u{2DAE9}\u{2DAEA}\u{2DAEB}\u{2DAEC}\u{2DAED}\u{2DAEE}\u{2DAEF}\u{2DAF0}\u{2DAF1}\u{2DAF2}\u{2DAF3}\u{2DAF4}\u{2DAF5}\u{2DAF6}\u{2DAF7}\u{2DAF8}\u{2DAF9}\u{2DAFA}\u{2DAFB}\u{2DAFC}\u{2DAFD}\u{2DAFE}\u{2DAFF}\u{2DB00}\u{2DB01}\u{2DB02}\u{2DB03}\u{2DB04}\u{2DB05}\u{2DB06}\u{2DB07}\u{2DB08}\u{2DB09}\u{2DB0A}\u{2DB0B}\u{2DB0C}\u{2DB0D}\u{2DB0E}\u{2DB0F}\u{2DB10}\u{2DB11}\u{2DB12}\u{2DB13}\u{2DB14}\u{2DB15}\u{2DB16}\u{2DB17}\u{2DB18}\u{2DB19}\u{2DB1A}\u{2DB1B}\u{2DB1C}\u{2DB1D}\u{2DB1E}\u{2DB1F}\u{2DB20}\u{2DB21}\u{2DB22}\u{2DB23}\u{2DB24}\u{2DB25}\u{2DB26}\u{2DB27}\u{2DB28}\u{2DB29}\u{2DB2A}\u{2DB2B}\u{2DB2C}\u{2DB2D}\u{2DB2E}\u{2DB2F}\u{2DB30}\u{2DB31}\u{2DB32}\u{2DB33}\u{2DB34}\u{2DB35}\u{2DB36}\u{2DB37}\u{2DB38}\u{2DB39}\u{2DB3A}\u{2DB3B}\u{2DB3C}\u{2DB3D}\u{2DB3E}\u{2DB3F}\u{2DB40}\u{2DB41}\u{2DB42}\u{2DB43}\u{2DB44}\u{2DB45}\u{2DB46}\u{2DB47}\u{2DB48}\u{2DB49}\u{2DB4A}\u{2DB4B}\u{2DB4C}\u{2DB4D}\u{2DB4E}\u{2DB4F}\u{2DB50}\u{2DB51}\u{2DB52}\u{2DB53}\u{2DB54}\u{2DB55}\u{2DB56}\u{2DB57}\u{2DB58}\u{2DB59}\u{2DB5A}\u{2DB5B}\u{2DB5C}\u{2DB5D}\u{2DB5E}\u{2DB5F}\u{2DB60}\u{2DB61}\u{2DB62}\u{2DB63}\u{2DB64}\u{2DB65}\u{2DB66}\u{2DB67}\u{2DB68}\u{2DB69}\u{2DB6A}\u{2DB6B}\u{2DB6C}\u{2DB6D}\u{2DB6E}\u{2DB6F}\u{2DB70}\u{2DB71}\u{2DB72}\u{2DB73}\u{2DB74}\u{2DB75}\u{2DB76}\u{2DB77}\u{2DB78}\u{2DB79}\u{2DB7A}\u{2DB7B}\u{2DB7C}\u{2DB7D}\u{2DB7E}\u{2DB7F}\u{2DB80}\u{2DB81}\u{2DB82}\u{2DB83}\u{2DB84}\u{2DB85}\u{2DB86}\u{2DB87}\u{2DB88}\u{2DB89}\u{2DB8A}\u{2DB8B}\u{2DB8C}\u{2DB8D}\u{2DB8E}\u{2DB8F}\u{2DB90}\u{2DB91}\u{2DB92}\u{2DB93}\u{2DB94}\u{2DB95}\u{2DB96}\u{2DB97}\u{2DB98}\u{2DB99}\u{2DB9A}\u{2DB9B}\u{2DB9C}\u{2DB9D}\u{2DB9E}\u{2DB9F}\u{2DBA0}\u{2DBA1}\u{2DBA2}\u{2DBA3}\u{2DBA4}\u{2DBA5}\u{2DBA6}\u{2DBA7}\u{2DBA8}\u{2DBA9}\u{2DBAA}\u{2DBAB}\u{2DBAC}\u{2DBAD}\u{2DBAE}\u{2DBAF}\u{2DBB0}\u{2DBB1}\u{2DBB2}\u{2DBB3}\u{2DBB4}\u{2DBB5}\u{2DBB6}\u{2DBB7}\u{2DBB8}\u{2DBB9}\u{2DBBA}\u{2DBBB}\u{2DBBC}\u{2DBBD}\u{2DBBE}\u{2DBBF}\u{2DBC0}\u{2DBC1}\u{2DBC2}\u{2DBC3}\u{2DBC4}\u{2DBC5}\u{2DBC6}\u{2DBC7}\u{2DBC8}\u{2DBC9}\u{2DBCA}\u{2DBCB}\u{2DBCC}\u{2DBCD}\u{2DBCE}\u{2DBCF}\u{2DBD0}\u{2DBD1}\u{2DBD2}\u{2DBD3}\u{2DBD4}\u{2DBD5}\u{2DBD6}\u{2DBD7}\u{2DBD8}\u{2DBD9}\u{2DBDA}\u{2DBDB}\u{2DBDC}\u{2DBDD}\u{2DBDE}\u{2DBDF}\u{2DBE0}\u{2DBE1}\u{2DBE2}\u{2DBE3}\u{2DBE4}\u{2DBE5}\u{2DBE6}\u{2DBE7}\u{2DBE8}\u{2DBE9}\u{2DBEA}\u{2DBEB}\u{2DBEC}\u{2DBED}\u{2DBEE}\u{2DBEF}\u{2DBF0}\u{2DBF1}\u{2DBF2}\u{2DBF3}\u{2DBF4}\u{2DBF5}\u{2DBF6}\u{2DBF7}\u{2DBF8}\u{2DBF9}\u{2DBFA}\u{2DBFB}\u{2DBFC}\u{2DBFD}\u{2DBFE}\u{2DBFF}\u{2DC00}\u{2DC01}\u{2DC02}\u{2DC03}\u{2DC04}\u{2DC05}\u{2DC06}\u{2DC07}\u{2DC08}\u{2DC09}\u{2DC0A}\u{2DC0B}\u{2DC0C}\u{2DC0D}\u{2DC0E}\u{2DC0F}\u{2DC10}\u{2DC11}\u{2DC12}\u{2DC13}\u{2DC14}\u{2DC15}\u{2DC16}\u{2DC17}\u{2DC18}\u{2DC19}\u{2DC1A}\u{2DC1B}\u{2DC1C}\u{2DC1D}\u{2DC1E}\u{2DC1F}\u{2DC20}\u{2DC21}\u{2DC22}\u{2DC23}\u{2DC24}\u{2DC25}\u{2DC26}\u{2DC27}\u{2DC28}\u{2DC29}\u{2DC2A}\u{2DC2B}\u{2DC2C}\u{2DC2D}\u{2DC2E}\u{2DC2F}\u{2DC30}\u{2DC31}\u{2DC32}\u{2DC33}\u{2DC34}\u{2DC35}\u{2DC36}\u{2DC37}\u{2DC38}\u{2DC39}\u{2DC3A}\u{2DC3B}\u{2DC3C}\u{2DC3D}\u{2DC3E}\u{2DC3F}\u{2DC40}\u{2DC41}\u{2DC42}\u{2DC43}\u{2DC44}\u{2DC45}\u{2DC46}\u{2DC47}\u{2DC48}\u{2DC49}\u{2DC4A}\u{2DC4B}\u{2DC4C}\u{2DC4D}\u{2DC4E}\u{2DC4F}\u{2DC50}\u{2DC51}\u{2DC52}\u{2DC53}\u{2DC54}\u{2DC55}\u{2DC56}\u{2DC57}\u{2DC58}\u{2DC59}\u{2DC5A}\u{2DC5B}\u{2DC5C}\u{2DC5D}\u{2DC5E}\u{2DC5F}\u{2DC60}\u{2DC61}\u{2DC62}\u{2DC63}\u{2DC64}\u{2DC65}\u{2DC66}\u{2DC67}\u{2DC68}\u{2DC69}\u{2DC6A}\u{2DC6B}\u{2DC6C}\u{2DC6D}\u{2DC6E}\u{2DC6F}\u{2DC70}\u{2DC71}\u{2DC72}\u{2DC73}\u{2DC74}\u{2DC75}\u{2DC76}\u{2DC77}\u{2DC78}\u{2DC79}\u{2DC7A}\u{2DC7B}\u{2DC7C}\u{2DC7D}\u{2DC7E}\u{2DC7F}\u{2DC80}\u{2DC81}\u{2DC82}\u{2DC83}\u{2DC84}\u{2DC85}\u{2DC86}\u{2DC87}\u{2DC88}\u{2DC89}\u{2DC8A}\u{2DC8B}\u{2DC8C}\u{2DC8D}\u{2DC8E}\u{2DC8F}\u{2DC90}\u{2DC91}\u{2DC92}\u{2DC93}\u{2DC94}\u{2DC95}\u{2DC96}\u{2DC97}\u{2DC98}\u{2DC99}\u{2DC9A}\u{2DC9B}\u{2DC9C}\u{2DC9D}\u{2DC9E}\u{2DC9F}\u{2DCA0}\u{2DCA1}\u{2DCA2}\u{2DCA3}\u{2DCA4}\u{2DCA5}\u{2DCA6}\u{2DCA7}\u{2DCA8}\u{2DCA9}\u{2DCAA}\u{2DCAB}\u{2DCAC}\u{2DCAD}\u{2DCAE}\u{2DCAF}\u{2DCB0}\u{2DCB1}\u{2DCB2}\u{2DCB3}\u{2DCB4}\u{2DCB5}\u{2DCB6}\u{2DCB7}\u{2DCB8}\u{2DCB9}\u{2DCBA}\u{2DCBB}\u{2DCBC}\u{2DCBD}\u{2DCBE}\u{2DCBF}\u{2DCC0}\u{2DCC1}\u{2DCC2}\u{2DCC3}\u{2DCC4}\u{2DCC5}\u{2DCC6}\u{2DCC7}\u{2DCC8}\u{2DCC9}\u{2DCCA}\u{2DCCB}\u{2DCCC}\u{2DCCD}\u{2DCCE}\u{2DCCF}\u{2DCD0}\u{2DCD1}\u{2DCD2}\u{2DCD3}\u{2DCD4}\u{2DCD5}\u{2DCD6}\u{2DCD7}\u{2DCD8}\u{2DCD9}\u{2DCDA}\u{2DCDB}\u{2DCDC}\u{2DCDD}\u{2DCDE}\u{2DCDF}\u{2DCE0}\u{2DCE1}\u{2DCE2}\u{2DCE3}\u{2DCE4}\u{2DCE5}\u{2DCE6}\u{2DCE7}\u{2DCE8}\u{2DCE9}\u{2DCEA}\u{2DCEB}\u{2DCEC}\u{2DCED}\u{2DCEE}\u{2DCEF}\u{2DCF0}\u{2DCF1}\u{2DCF2}\u{2DCF3}\u{2DCF4}\u{2DCF5}\u{2DCF6}\u{2DCF7}\u{2DCF8}\u{2DCF9}\u{2DCFA}\u{2DCFB}\u{2DCFC}\u{2DCFD}\u{2DCFE}\u{2DCFF}\u{2DD00}\u{2DD01}\u{2DD02}\u{2DD03}\u{2DD04}\u{2DD05}\u{2DD06}\u{2DD07}\u{2DD08}\u{2DD09}\u{2DD0A}\u{2DD0B}\u{2DD0C}\u{2DD0D}\u{2DD0E}\u{2DD0F}\u{2DD10}\u{2DD11}\u{2DD12}\u{2DD13}\u{2DD14}\u{2DD15}\u{2DD16}\u{2DD17}\u{2DD18}\u{2DD19}\u{2DD1A}\u{2DD1B}\u{2DD1C}\u{2DD1D}\u{2DD1E}\u{2DD1F}\u{2DD20}\u{2DD21}\u{2DD22}\u{2DD23}\u{2DD24}\u{2DD25}\u{2DD26}\u{2DD27}\u{2DD28}\u{2DD29}\u{2DD2A}\u{2DD2B}\u{2DD2C}\u{2DD2D}\u{2DD2E}\u{2DD2F}\u{2DD30}\u{2DD31}\u{2DD32}\u{2DD33}\u{2DD34}\u{2DD35}\u{2DD36}\u{2DD37}\u{2DD38}\u{2DD39}\u{2DD3A}\u{2DD3B}\u{2DD3C}\u{2DD3D}\u{2DD3E}\u{2DD3F}\u{2DD40}\u{2DD41}\u{2DD42}\u{2DD43}\u{2DD44}\u{2DD45}\u{2DD46}\u{2DD47}\u{2DD48}\u{2DD49}\u{2DD4A}\u{2DD4B}\u{2DD4C}\u{2DD4D}\u{2DD4E}\u{2DD4F}\u{2DD50}\u{2DD51}\u{2DD52}\u{2DD53}\u{2DD54}\u{2DD55}\u{2DD56}\u{2DD57}\u{2DD58}\u{2DD59}\u{2DD5A}\u{2DD5B}\u{2DD5C}\u{2DD5D}\u{2DD5E}\u{2DD5F}\u{2DD60}\u{2DD61}\u{2DD62}\u{2DD63}\u{2DD64}\u{2DD65}\u{2DD66}\u{2DD67}\u{2DD68}\u{2DD69}\u{2DD6A}\u{2DD6B}\u{2DD6C}\u{2DD6D}\u{2DD6E}\u{2DD6F}\u{2DD70}\u{2DD71}\u{2DD72}\u{2DD73}\u{2DD74}\u{2DD75}\u{2DD76}\u{2DD77}\u{2DD78}\u{2DD79}\u{2DD7A}\u{2DD7B}\u{2DD7C}\u{2DD7D}\u{2DD7E}\u{2DD7F}\u{2DD80}\u{2DD81}\u{2DD82}\u{2DD83}\u{2DD84}\u{2DD85}\u{2DD86}\u{2DD87}\u{2DD88}\u{2DD89}\u{2DD8A}\u{2DD8B}\u{2DD8C}\u{2DD8D}\u{2DD8E}\u{2DD8F}\u{2DD90}\u{2DD91}\u{2DD92}\u{2DD93}\u{2DD94}\u{2DD95}\u{2DD96}\u{2DD97}\u{2DD98}\u{2DD99}\u{2DD9A}\u{2DD9B}\u{2DD9C}\u{2DD9D}\u{2DD9E}\u{2DD9F}\u{2DDA0}\u{2DDA1}\u{2DDA2}\u{2DDA3}\u{2DDA4}\u{2DDA5}\u{2DDA6}\u{2DDA7}\u{2DDA8}\u{2DDA9}\u{2DDAA}\u{2DDAB}\u{2DDAC}\u{2DDAD}\u{2DDAE}\u{2DDAF}\u{2DDB0}\u{2DDB1}\u{2DDB2}\u{2DDB3}\u{2DDB4}\u{2DDB5}\u{2DDB6}\u{2DDB7}\u{2DDB8}\u{2DDB9}\u{2DDBA}\u{2DDBB}\u{2DDBC}\u{2DDBD}\u{2DDBE}\u{2DDBF}\u{2DDC0}\u{2DDC1}\u{2DDC2}\u{2DDC3}\u{2DDC4}\u{2DDC5}\u{2DDC6}\u{2DDC7}\u{2DDC8}\u{2DDC9}\u{2DDCA}\u{2DDCB}\u{2DDCC}\u{2DDCD}\u{2DDCE}\u{2DDCF}\u{2DDD0}\u{2DDD1}\u{2DDD2}\u{2DDD3}\u{2DDD4}\u{2DDD5}\u{2DDD6}\u{2DDD7}\u{2DDD8}\u{2DDD9}\u{2DDDA}\u{2DDDB}\u{2DDDC}\u{2DDDD}\u{2DDDE}\u{2DDDF}\u{2DDE0}\u{2DDE1}\u{2DDE2}\u{2DDE3}\u{2DDE4}\u{2DDE5}\u{2DDE6}\u{2DDE7}\u{2DDE8}\u{2DDE9}\u{2DDEA}\u{2DDEB}\u{2DDEC}\u{2DDED}\u{2DDEE}\u{2DDEF}\u{2DDF0}\u{2DDF1}\u{2DDF2}\u{2DDF3}\u{2DDF4}\u{2DDF5}\u{2DDF6}\u{2DDF7}\u{2DDF8}\u{2DDF9}\u{2DDFA}\u{2DDFB}\u{2DDFC}\u{2DDFD}\u{2DDFE}\u{2DDFF}\u{2DE00}\u{2DE01}\u{2DE02}\u{2DE03}\u{2DE04}\u{2DE05}\u{2DE06}\u{2DE07}\u{2DE08}\u{2DE09}\u{2DE0A}\u{2DE0B}\u{2DE0C}\u{2DE0D}\u{2DE0E}\u{2DE0F}\u{2DE10}\u{2DE11}\u{2DE12}\u{2DE13}\u{2DE14}\u{2DE15}\u{2DE16}\u{2DE17}\u{2DE18}\u{2DE19}\u{2DE1A}\u{2DE1B}\u{2DE1C}\u{2DE1D}\u{2DE1E}\u{2DE1F}\u{2DE20}\u{2DE21}\u{2DE22}\u{2DE23}\u{2DE24}\u{2DE25}\u{2DE26}\u{2DE27}\u{2DE28}\u{2DE29}\u{2DE2A}\u{2DE2B}\u{2DE2C}\u{2DE2D}\u{2DE2E}\u{2DE2F}\u{2DE30}\u{2DE31}\u{2DE32}\u{2DE33}\u{2DE34}\u{2DE35}\u{2DE36}\u{2DE37}\u{2DE38}\u{2DE39}\u{2DE3A}\u{2DE3B}\u{2DE3C}\u{2DE3D}\u{2DE3E}\u{2DE3F}\u{2DE40}\u{2DE41}\u{2DE42}\u{2DE43}\u{2DE44}\u{2DE45}\u{2DE46}\u{2DE47}\u{2DE48}\u{2DE49}\u{2DE4A}\u{2DE4B}\u{2DE4C}\u{2DE4D}\u{2DE4E}\u{2DE4F}\u{2DE50}\u{2DE51}\u{2DE52}\u{2DE53}\u{2DE54}\u{2DE55}\u{2DE56}\u{2DE57}\u{2DE58}\u{2DE59}\u{2DE5A}\u{2DE5B}\u{2DE5C}\u{2DE5D}\u{2DE5E}\u{2DE5F}\u{2DE60}\u{2DE61}\u{2DE62}\u{2DE63}\u{2DE64}\u{2DE65}\u{2DE66}\u{2DE67}\u{2DE68}\u{2DE69}\u{2DE6A}\u{2DE6B}\u{2DE6C}\u{2DE6D}\u{2DE6E}\u{2DE6F}\u{2DE70}\u{2DE71}\u{2DE72}\u{2DE73}\u{2DE74}\u{2DE75}\u{2DE76}\u{2DE77}\u{2DE78}\u{2DE79}\u{2DE7A}\u{2DE7B}\u{2DE7C}\u{2DE7D}\u{2DE7E}\u{2DE7F}\u{2DE80}\u{2DE81}\u{2DE82}\u{2DE83}\u{2DE84}\u{2DE85}\u{2DE86}\u{2DE87}\u{2DE88}\u{2DE89}\u{2DE8A}\u{2DE8B}\u{2DE8C}\u{2DE8D}\u{2DE8E}\u{2DE8F}\u{2DE90}\u{2DE91}\u{2DE92}\u{2DE93}\u{2DE94}\u{2DE95}\u{2DE96}\u{2DE97}\u{2DE98}\u{2DE99}\u{2DE9A}\u{2DE9B}\u{2DE9C}\u{2DE9D}\u{2DE9E}\u{2DE9F}\u{2DEA0}\u{2DEA1}\u{2DEA2}\u{2DEA3}\u{2DEA4}\u{2DEA5}\u{2DEA6}\u{2DEA7}\u{2DEA8}\u{2DEA9}\u{2DEAA}\u{2DEAB}\u{2DEAC}\u{2DEAD}\u{2DEAE}\u{2DEAF}\u{2DEB0}\u{2DEB1}\u{2DEB2}\u{2DEB3}\u{2DEB4}\u{2DEB5}\u{2DEB6}\u{2DEB7}\u{2DEB8}\u{2DEB9}\u{2DEBA}\u{2DEBB}\u{2DEBC}\u{2DEBD}\u{2DEBE}\u{2DEBF}\u{2DEC0}\u{2DEC1}\u{2DEC2}\u{2DEC3}\u{2DEC4}\u{2DEC5}\u{2DEC6}\u{2DEC7}\u{2DEC8}\u{2DEC9}\u{2DECA}\u{2DECB}\u{2DECC}\u{2DECD}\u{2DECE}\u{2DECF}\u{2DED0}\u{2DED1}\u{2DED2}\u{2DED3}\u{2DED4}\u{2DED5}\u{2DED6}\u{2DED7}\u{2DED8}\u{2DED9}\u{2DEDA}\u{2DEDB}\u{2DEDC}\u{2DEDD}\u{2DEDE}\u{2DEDF}\u{2DEE0}\u{2DEE1}\u{2DEE2}\u{2DEE3}\u{2DEE4}\u{2DEE5}\u{2DEE6}\u{2DEE7}\u{2DEE8}\u{2DEE9}\u{2DEEA}\u{2DEEB}\u{2DEEC}\u{2DEED}\u{2DEEE}\u{2DEEF}\u{2DEF0}\u{2DEF1}\u{2DEF2}\u{2DEF3}\u{2DEF4}\u{2DEF5}\u{2DEF6}\u{2DEF7}\u{2DEF8}\u{2DEF9}\u{2DEFA}\u{2DEFB}\u{2DEFC}\u{2DEFD}\u{2DEFE}\u{2DEFF}\u{2DF00}\u{2DF01}\u{2DF02}\u{2DF03}\u{2DF04}\u{2DF05}\u{2DF06}\u{2DF07}\u{2DF08}\u{2DF09}\u{2DF0A}\u{2DF0B}\u{2DF0C}\u{2DF0D}\u{2DF0E}\u{2DF0F}\u{2DF10}\u{2DF11}\u{2DF12}\u{2DF13}\u{2DF14}\u{2DF15}\u{2DF16}\u{2DF17}\u{2DF18}\u{2DF19}\u{2DF1A}\u{2DF1B}\u{2DF1C}\u{2DF1D}\u{2DF1E}\u{2DF1F}\u{2DF20}\u{2DF21}\u{2DF22}\u{2DF23}\u{2DF24}\u{2DF25}\u{2DF26}\u{2DF27}\u{2DF28}\u{2DF29}\u{2DF2A}\u{2DF2B}\u{2DF2C}\u{2DF2D}\u{2DF2E}\u{2DF2F}\u{2DF30}\u{2DF31}\u{2DF32}\u{2DF33}\u{2DF34}\u{2DF35}\u{2DF36}\u{2DF37}\u{2DF38}\u{2DF39}\u{2DF3A}\u{2DF3B}\u{2DF3C}\u{2DF3D}\u{2DF3E}\u{2DF3F}\u{2DF40}\u{2DF41}\u{2DF42}\u{2DF43}\u{2DF44}\u{2DF45}\u{2DF46}\u{2DF47}\u{2DF48}\u{2DF49}\u{2DF4A}\u{2DF4B}\u{2DF4C}\u{2DF4D}\u{2DF4E}\u{2DF4F}\u{2DF50}\u{2DF51}\u{2DF52}\u{2DF53}\u{2DF54}\u{2DF55}\u{2DF56}\u{2DF57}\u{2DF58}\u{2DF59}\u{2DF5A}\u{2DF5B}\u{2DF5C}\u{2DF5D}\u{2DF5E}\u{2DF5F}\u{2DF60}\u{2DF61}\u{2DF62}\u{2DF63}\u{2DF64}\u{2DF65}\u{2DF66}\u{2DF67}\u{2DF68}\u{2DF69}\u{2DF6A}\u{2DF6B}\u{2DF6C}\u{2DF6D}\u{2DF6E}\u{2DF6F}\u{2DF70}\u{2DF71}\u{2DF72}\u{2DF73}\u{2DF74}\u{2DF75}\u{2DF76}\u{2DF77}\u{2DF78}\u{2DF79}\u{2DF7A}\u{2DF7B}\u{2DF7C}\u{2DF7D}\u{2DF7E}\u{2DF7F}\u{2DF80}\u{2DF81}\u{2DF82}\u{2DF83}\u{2DF84}\u{2DF85}\u{2DF86}\u{2DF87}\u{2DF88}\u{2DF89}\u{2DF8A}\u{2DF8B}\u{2DF8C}\u{2DF8D}\u{2DF8E}\u{2DF8F}\u{2DF90}\u{2DF91}\u{2DF92}\u{2DF93}\u{2DF94}\u{2DF95}\u{2DF96}\u{2DF97}\u{2DF98}\u{2DF99}\u{2DF9A}\u{2DF9B}\u{2DF9C}\u{2DF9D}\u{2DF9E}\u{2DF9F}\u{2DFA0}\u{2DFA1}\u{2DFA2}\u{2DFA3}\u{2DFA4}\u{2DFA5}\u{2DFA6}\u{2DFA7}\u{2DFA8}\u{2DFA9}\u{2DFAA}\u{2DFAB}\u{2DFAC}\u{2DFAD}\u{2DFAE}\u{2DFAF}\u{2DFB0}\u{2DFB1}\u{2DFB2}\u{2DFB3}\u{2DFB4}\u{2DFB5}\u{2DFB6}\u{2DFB7}\u{2DFB8}\u{2DFB9}\u{2DFBA}\u{2DFBB}\u{2DFBC}\u{2DFBD}\u{2DFBE}\u{2DFBF}\u{2DFC0}\u{2DFC1}\u{2DFC2}\u{2DFC3}\u{2DFC4}\u{2DFC5}\u{2DFC6}\u{2DFC7}\u{2DFC8}\u{2DFC9}\u{2DFCA}\u{2DFCB}\u{2DFCC}\u{2DFCD}\u{2DFCE}\u{2DFCF}\u{2DFD0}\u{2DFD1}\u{2DFD2}\u{2DFD3}\u{2DFD4}\u{2DFD5}\u{2DFD6}\u{2DFD7}\u{2DFD8}\u{2DFD9}\u{2DFDA}\u{2DFDB}\u{2DFDC}\u{2DFDD}\u{2DFDE}\u{2DFDF}\u{2DFE0}\u{2DFE1}\u{2DFE2}\u{2DFE3}\u{2DFE4}\u{2DFE5}\u{2DFE6}\u{2DFE7}\u{2DFE8}\u{2DFE9}\u{2DFEA}\u{2DFEB}\u{2DFEC}\u{2DFED}\u{2DFEE}\u{2DFEF}\u{2DFF0}\u{2DFF1}\u{2DFF2}\u{2DFF3}\u{2DFF4}\u{2DFF5}\u{2DFF6}\u{2DFF7}\u{2DFF8}\u{2DFF9}\u{2DFFA}\u{2DFFB}\u{2DFFC}\u{2DFFD}\u{2DFFE}\u{2DFFF}\u{2E000}\u{2E001}\u{2E002}\u{2E003}\u{2E004}\u{2E005}\u{2E006}\u{2E007}\u{2E008}\u{2E009}\u{2E00A}\u{2E00B}\u{2E00C}\u{2E00D}\u{2E00E}\u{2E00F}\u{2E010}\u{2E011}\u{2E012}\u{2E013}\u{2E014}\u{2E015}\u{2E016}\u{2E017}\u{2E018}\u{2E019}\u{2E01A}\u{2E01B}\u{2E01C}\u{2E01D}\u{2E01E}\u{2E01F}\u{2E020}\u{2E021}\u{2E022}\u{2E023}\u{2E024}\u{2E025}\u{2E026}\u{2E027}\u{2E028}\u{2E029}\u{2E02A}\u{2E02B}\u{2E02C}\u{2E02D}\u{2E02E}\u{2E02F}\u{2E030}\u{2E031}\u{2E032}\u{2E033}\u{2E034}\u{2E035}\u{2E036}\u{2E037}\u{2E038}\u{2E039}\u{2E03A}\u{2E03B}\u{2E03C}\u{2E03D}\u{2E03E}\u{2E03F}\u{2E040}\u{2E041}\u{2E042}\u{2E043}\u{2E044}\u{2E045}\u{2E046}\u{2E047}\u{2E048}\u{2E049}\u{2E04A}\u{2E04B}\u{2E04C}\u{2E04D}\u{2E04E}\u{2E04F}\u{2E050}\u{2E051}\u{2E052}\u{2E053}\u{2E054}\u{2E055}\u{2E056}\u{2E057}\u{2E058}\u{2E059}\u{2E05A}\u{2E05B}\u{2E05C}\u{2E05D}\u{2E05E}\u{2E05F}\u{2E060}\u{2E061}\u{2E062}\u{2E063}\u{2E064}\u{2E065}\u{2E066}\u{2E067}\u{2E068}\u{2E069}\u{2E06A}\u{2E06B}\u{2E06C}\u{2E06D}\u{2E06E}\u{2E06F}\u{2E070}\u{2E071}\u{2E072}\u{2E073}\u{2E074}\u{2E075}\u{2E076}\u{2E077}\u{2E078}\u{2E079}\u{2E07A}\u{2E07B}\u{2E07C}\u{2E07D}\u{2E07E}\u{2E07F}\u{2E080}\u{2E081}\u{2E082}\u{2E083}\u{2E084}\u{2E085}\u{2E086}\u{2E087}\u{2E088}\u{2E089}\u{2E08A}\u{2E08B}\u{2E08C}\u{2E08D}\u{2E08E}\u{2E08F}\u{2E090}\u{2E091}\u{2E092}\u{2E093}\u{2E094}\u{2E095}\u{2E096}\u{2E097}\u{2E098}\u{2E099}\u{2E09A}\u{2E09B}\u{2E09C}\u{2E09D}\u{2E09E}\u{2E09F}\u{2E0A0}\u{2E0A1}\u{2E0A2}\u{2E0A3}\u{2E0A4}\u{2E0A5}\u{2E0A6}\u{2E0A7}\u{2E0A8}\u{2E0A9}\u{2E0AA}\u{2E0AB}\u{2E0AC}\u{2E0AD}\u{2E0AE}\u{2E0AF}\u{2E0B0}\u{2E0B1}\u{2E0B2}\u{2E0B3}\u{2E0B4}\u{2E0B5}\u{2E0B6}\u{2E0B7}\u{2E0B8}\u{2E0B9}\u{2E0BA}\u{2E0BB}\u{2E0BC}\u{2E0BD}\u{2E0BE}\u{2E0BF}\u{2E0C0}\u{2E0C1}\u{2E0C2}\u{2E0C3}\u{2E0C4}\u{2E0C5}\u{2E0C6}\u{2E0C7}\u{2E0C8}\u{2E0C9}\u{2E0CA}\u{2E0CB}\u{2E0CC}\u{2E0CD}\u{2E0CE}\u{2E0CF}\u{2E0D0}\u{2E0D1}\u{2E0D2}\u{2E0D3}\u{2E0D4}\u{2E0D5}\u{2E0D6}\u{2E0D7}\u{2E0D8}\u{2E0D9}\u{2E0DA}\u{2E0DB}\u{2E0DC}\u{2E0DD}\u{2E0DE}\u{2E0DF}\u{2E0E0}\u{2E0E1}\u{2E0E2}\u{2E0E3}\u{2E0E4}\u{2E0E5}\u{2E0E6}\u{2E0E7}\u{2E0E8}\u{2E0E9}\u{2E0EA}\u{2E0EB}\u{2E0EC}\u{2E0ED}\u{2E0EE}\u{2E0EF}\u{2E0F0}\u{2E0F1}\u{2E0F2}\u{2E0F3}\u{2E0F4}\u{2E0F5}\u{2E0F6}\u{2E0F7}\u{2E0F8}\u{2E0F9}\u{2E0FA}\u{2E0FB}\u{2E0FC}\u{2E0FD}\u{2E0FE}\u{2E0FF}\u{2E100}\u{2E101}\u{2E102}\u{2E103}\u{2E104}\u{2E105}\u{2E106}\u{2E107}\u{2E108}\u{2E109}\u{2E10A}\u{2E10B}\u{2E10C}\u{2E10D}\u{2E10E}\u{2E10F}\u{2E110}\u{2E111}\u{2E112}\u{2E113}\u{2E114}\u{2E115}\u{2E116}\u{2E117}\u{2E118}\u{2E119}\u{2E11A}\u{2E11B}\u{2E11C}\u{2E11D}\u{2E11E}\u{2E11F}\u{2E120}\u{2E121}\u{2E122}\u{2E123}\u{2E124}\u{2E125}\u{2E126}\u{2E127}\u{2E128}\u{2E129}\u{2E12A}\u{2E12B}\u{2E12C}\u{2E12D}\u{2E12E}\u{2E12F}\u{2E130}\u{2E131}\u{2E132}\u{2E133}\u{2E134}\u{2E135}\u{2E136}\u{2E137}\u{2E138}\u{2E139}\u{2E13A}\u{2E13B}\u{2E13C}\u{2E13D}\u{2E13E}\u{2E13F}\u{2E140}\u{2E141}\u{2E142}\u{2E143}\u{2E144}\u{2E145}\u{2E146}\u{2E147}\u{2E148}\u{2E149}\u{2E14A}\u{2E14B}\u{2E14C}\u{2E14D}\u{2E14E}\u{2E14F}\u{2E150}\u{2E151}\u{2E152}\u{2E153}\u{2E154}\u{2E155}\u{2E156}\u{2E157}\u{2E158}\u{2E159}\u{2E15A}\u{2E15B}\u{2E15C}\u{2E15D}\u{2E15E}\u{2E15F}\u{2E160}\u{2E161}\u{2E162}\u{2E163}\u{2E164}\u{2E165}\u{2E166}\u{2E167}\u{2E168}\u{2E169}\u{2E16A}\u{2E16B}\u{2E16C}\u{2E16D}\u{2E16E}\u{2E16F}\u{2E170}\u{2E171}\u{2E172}\u{2E173}\u{2E174}\u{2E175}\u{2E176}\u{2E177}\u{2E178}\u{2E179}\u{2E17A}\u{2E17B}\u{2E17C}\u{2E17D}\u{2E17E}\u{2E17F}\u{2E180}\u{2E181}\u{2E182}\u{2E183}\u{2E184}\u{2E185}\u{2E186}\u{2E187}\u{2E188}\u{2E189}\u{2E18A}\u{2E18B}\u{2E18C}\u{2E18D}\u{2E18E}\u{2E18F}\u{2E190}\u{2E191}\u{2E192}\u{2E193}\u{2E194}\u{2E195}\u{2E196}\u{2E197}\u{2E198}\u{2E199}\u{2E19A}\u{2E19B}\u{2E19C}\u{2E19D}\u{2E19E}\u{2E19F}\u{2E1A0}\u{2E1A1}\u{2E1A2}\u{2E1A3}\u{2E1A4}\u{2E1A5}\u{2E1A6}\u{2E1A7}\u{2E1A8}\u{2E1A9}\u{2E1AA}\u{2E1AB}\u{2E1AC}\u{2E1AD}\u{2E1AE}\u{2E1AF}\u{2E1B0}\u{2E1B1}\u{2E1B2}\u{2E1B3}\u{2E1B4}\u{2E1B5}\u{2E1B6}\u{2E1B7}\u{2E1B8}\u{2E1B9}\u{2E1BA}\u{2E1BB}\u{2E1BC}\u{2E1BD}\u{2E1BE}\u{2E1BF}\u{2E1C0}\u{2E1C1}\u{2E1C2}\u{2E1C3}\u{2E1C4}\u{2E1C5}\u{2E1C6}\u{2E1C7}\u{2E1C8}\u{2E1C9}\u{2E1CA}\u{2E1CB}\u{2E1CC}\u{2E1CD}\u{2E1CE}\u{2E1CF}\u{2E1D0}\u{2E1D1}\u{2E1D2}\u{2E1D3}\u{2E1D4}\u{2E1D5}\u{2E1D6}\u{2E1D7}\u{2E1D8}\u{2E1D9}\u{2E1DA}\u{2E1DB}\u{2E1DC}\u{2E1DD}\u{2E1DE}\u{2E1DF}\u{2E1E0}\u{2E1E1}\u{2E1E2}\u{2E1E3}\u{2E1E4}\u{2E1E5}\u{2E1E6}\u{2E1E7}\u{2E1E8}\u{2E1E9}\u{2E1EA}\u{2E1EB}\u{2E1EC}\u{2E1ED}\u{2E1EE}\u{2E1EF}\u{2E1F0}\u{2E1F1}\u{2E1F2}\u{2E1F3}\u{2E1F4}\u{2E1F5}\u{2E1F6}\u{2E1F7}\u{2E1F8}\u{2E1F9}\u{2E1FA}\u{2E1FB}\u{2E1FC}\u{2E1FD}\u{2E1FE}\u{2E1FF}\u{2E200}\u{2E201}\u{2E202}\u{2E203}\u{2E204}\u{2E205}\u{2E206}\u{2E207}\u{2E208}\u{2E209}\u{2E20A}\u{2E20B}\u{2E20C}\u{2E20D}\u{2E20E}\u{2E20F}\u{2E210}\u{2E211}\u{2E212}\u{2E213}\u{2E214}\u{2E215}\u{2E216}\u{2E217}\u{2E218}\u{2E219}\u{2E21A}\u{2E21B}\u{2E21C}\u{2E21D}\u{2E21E}\u{2E21F}\u{2E220}\u{2E221}\u{2E222}\u{2E223}\u{2E224}\u{2E225}\u{2E226}\u{2E227}\u{2E228}\u{2E229}\u{2E22A}\u{2E22B}\u{2E22C}\u{2E22D}\u{2E22E}\u{2E22F}\u{2E230}\u{2E231}\u{2E232}\u{2E233}\u{2E234}\u{2E235}\u{2E236}\u{2E237}\u{2E238}\u{2E239}\u{2E23A}\u{2E23B}\u{2E23C}\u{2E23D}\u{2E23E}\u{2E23F}\u{2E240}\u{2E241}\u{2E242}\u{2E243}\u{2E244}\u{2E245}\u{2E246}\u{2E247}\u{2E248}\u{2E249}\u{2E24A}\u{2E24B}\u{2E24C}\u{2E24D}\u{2E24E}\u{2E24F}\u{2E250}\u{2E251}\u{2E252}\u{2E253}\u{2E254}\u{2E255}\u{2E256}\u{2E257}\u{2E258}\u{2E259}\u{2E25A}\u{2E25B}\u{2E25C}\u{2E25D}\u{2E25E}\u{2E25F}\u{2E260}\u{2E261}\u{2E262}\u{2E263}\u{2E264}\u{2E265}\u{2E266}\u{2E267}\u{2E268}\u{2E269}\u{2E26A}\u{2E26B}\u{2E26C}\u{2E26D}\u{2E26E}\u{2E26F}\u{2E270}\u{2E271}\u{2E272}\u{2E273}\u{2E274}\u{2E275}\u{2E276}\u{2E277}\u{2E278}\u{2E279}\u{2E27A}\u{2E27B}\u{2E27C}\u{2E27D}\u{2E27E}\u{2E27F}\u{2E280}\u{2E281}\u{2E282}\u{2E283}\u{2E284}\u{2E285}\u{2E286}\u{2E287}\u{2E288}\u{2E289}\u{2E28A}\u{2E28B}\u{2E28C}\u{2E28D}\u{2E28E}\u{2E28F}\u{2E290}\u{2E291}\u{2E292}\u{2E293}\u{2E294}\u{2E295}\u{2E296}\u{2E297}\u{2E298}\u{2E299}\u{2E29A}\u{2E29B}\u{2E29C}\u{2E29D}\u{2E29E}\u{2E29F}\u{2E2A0}\u{2E2A1}\u{2E2A2}\u{2E2A3}\u{2E2A4}\u{2E2A5}\u{2E2A6}\u{2E2A7}\u{2E2A8}\u{2E2A9}\u{2E2AA}\u{2E2AB}\u{2E2AC}\u{2E2AD}\u{2E2AE}\u{2E2AF}\u{2E2B0}\u{2E2B1}\u{2E2B2}\u{2E2B3}\u{2E2B4}\u{2E2B5}\u{2E2B6}\u{2E2B7}\u{2E2B8}\u{2E2B9}\u{2E2BA}\u{2E2BB}\u{2E2BC}\u{2E2BD}\u{2E2BE}\u{2E2BF}\u{2E2C0}\u{2E2C1}\u{2E2C2}\u{2E2C3}\u{2E2C4}\u{2E2C5}\u{2E2C6}\u{2E2C7}\u{2E2C8}\u{2E2C9}\u{2E2CA}\u{2E2CB}\u{2E2CC}\u{2E2CD}\u{2E2CE}\u{2E2CF}\u{2E2D0}\u{2E2D1}\u{2E2D2}\u{2E2D3}\u{2E2D4}\u{2E2D5}\u{2E2D6}\u{2E2D7}\u{2E2D8}\u{2E2D9}\u{2E2DA}\u{2E2DB}\u{2E2DC}\u{2E2DD}\u{2E2DE}\u{2E2DF}\u{2E2E0}\u{2E2E1}\u{2E2E2}\u{2E2E3}\u{2E2E4}\u{2E2E5}\u{2E2E6}\u{2E2E7}\u{2E2E8}\u{2E2E9}\u{2E2EA}\u{2E2EB}\u{2E2EC}\u{2E2ED}\u{2E2EE}\u{2E2EF}\u{2E2F0}\u{2E2F1}\u{2E2F2}\u{2E2F3}\u{2E2F4}\u{2E2F5}\u{2E2F6}\u{2E2F7}\u{2E2F8}\u{2E2F9}\u{2E2FA}\u{2E2FB}\u{2E2FC}\u{2E2FD}\u{2E2FE}\u{2E2FF}\u{2E300}\u{2E301}\u{2E302}\u{2E303}\u{2E304}\u{2E305}\u{2E306}\u{2E307}\u{2E308}\u{2E309}\u{2E30A}\u{2E30B}\u{2E30C}\u{2E30D}\u{2E30E}\u{2E30F}\u{2E310}\u{2E311}\u{2E312}\u{2E313}\u{2E314}\u{2E315}\u{2E316}\u{2E317}\u{2E318}\u{2E319}\u{2E31A}\u{2E31B}\u{2E31C}\u{2E31D}\u{2E31E}\u{2E31F}\u{2E320}\u{2E321}\u{2E322}\u{2E323}\u{2E324}\u{2E325}\u{2E326}\u{2E327}\u{2E328}\u{2E329}\u{2E32A}\u{2E32B}\u{2E32C}\u{2E32D}\u{2E32E}\u{2E32F}\u{2E330}\u{2E331}\u{2E332}\u{2E333}\u{2E334}\u{2E335}\u{2E336}\u{2E337}\u{2E338}\u{2E339}\u{2E33A}\u{2E33B}\u{2E33C}\u{2E33D}\u{2E33E}\u{2E33F}\u{2E340}\u{2E341}\u{2E342}\u{2E343}\u{2E344}\u{2E345}\u{2E346}\u{2E347}\u{2E348}\u{2E349}\u{2E34A}\u{2E34B}\u{2E34C}\u{2E34D}\u{2E34E}\u{2E34F}\u{2E350}\u{2E351}\u{2E352}\u{2E353}\u{2E354}\u{2E355}\u{2E356}\u{2E357}\u{2E358}\u{2E359}\u{2E35A}\u{2E35B}\u{2E35C}\u{2E35D}\u{2E35E}\u{2E35F}\u{2E360}\u{2E361}\u{2E362}\u{2E363}\u{2E364}\u{2E365}\u{2E366}\u{2E367}\u{2E368}\u{2E369}\u{2E36A}\u{2E36B}\u{2E36C}\u{2E36D}\u{2E36E}\u{2E36F}\u{2E370}\u{2E371}\u{2E372}\u{2E373}\u{2E374}\u{2E375}\u{2E376}\u{2E377}\u{2E378}\u{2E379}\u{2E37A}\u{2E37B}\u{2E37C}\u{2E37D}\u{2E37E}\u{2E37F}\u{2E380}\u{2E381}\u{2E382}\u{2E383}\u{2E384}\u{2E385}\u{2E386}\u{2E387}\u{2E388}\u{2E389}\u{2E38A}\u{2E38B}\u{2E38C}\u{2E38D}\u{2E38E}\u{2E38F}\u{2E390}\u{2E391}\u{2E392}\u{2E393}\u{2E394}\u{2E395}\u{2E396}\u{2E397}\u{2E398}\u{2E399}\u{2E39A}\u{2E39B}\u{2E39C}\u{2E39D}\u{2E39E}\u{2E39F}\u{2E3A0}\u{2E3A1}\u{2E3A2}\u{2E3A3}\u{2E3A4}\u{2E3A5}\u{2E3A6}\u{2E3A7}\u{2E3A8}\u{2E3A9}\u{2E3AA}\u{2E3AB}\u{2E3AC}\u{2E3AD}\u{2E3AE}\u{2E3AF}\u{2E3B0}\u{2E3B1}\u{2E3B2}\u{2E3B3}\u{2E3B4}\u{2E3B5}\u{2E3B6}\u{2E3B7}\u{2E3B8}\u{2E3B9}\u{2E3BA}\u{2E3BB}\u{2E3BC}\u{2E3BD}\u{2E3BE}\u{2E3BF}\u{2E3C0}\u{2E3C1}\u{2E3C2}\u{2E3C3}\u{2E3C4}\u{2E3C5}\u{2E3C6}\u{2E3C7}\u{2E3C8}\u{2E3C9}\u{2E3CA}\u{2E3CB}\u{2E3CC}\u{2E3CD}\u{2E3CE}\u{2E3CF}\u{2E3D0}\u{2E3D1}\u{2E3D2}\u{2E3D3}\u{2E3D4}\u{2E3D5}\u{2E3D6}\u{2E3D7}\u{2E3D8}\u{2E3D9}\u{2E3DA}\u{2E3DB}\u{2E3DC}\u{2E3DD}\u{2E3DE}\u{2E3DF}\u{2E3E0}\u{2E3E1}\u{2E3E2}\u{2E3E3}\u{2E3E4}\u{2E3E5}\u{2E3E6}\u{2E3E7}\u{2E3E8}\u{2E3E9}\u{2E3EA}\u{2E3EB}\u{2E3EC}\u{2E3ED}\u{2E3EE}\u{2E3EF}\u{2E3F0}\u{2E3F1}\u{2E3F2}\u{2E3F3}\u{2E3F4}\u{2E3F5}\u{2E3F6}\u{2E3F7}\u{2E3F8}\u{2E3F9}\u{2E3FA}\u{2E3FB}\u{2E3FC}\u{2E3FD}\u{2E3FE}\u{2E3FF}\u{2E400}\u{2E401}\u{2E402}\u{2E403}\u{2E404}\u{2E405}\u{2E406}\u{2E407}\u{2E408}\u{2E409}\u{2E40A}\u{2E40B}\u{2E40C}\u{2E40D}\u{2E40E}\u{2E40F}\u{2E410}\u{2E411}\u{2E412}\u{2E413}\u{2E414}\u{2E415}\u{2E416}\u{2E417}\u{2E418}\u{2E419}\u{2E41A}\u{2E41B}\u{2E41C}\u{2E41D}\u{2E41E}\u{2E41F}\u{2E420}\u{2E421}\u{2E422}\u{2E423}\u{2E424}\u{2E425}\u{2E426}\u{2E427}\u{2E428}\u{2E429}\u{2E42A}\u{2E42B}\u{2E42C}\u{2E42D}\u{2E42E}\u{2E42F}\u{2E430}\u{2E431}\u{2E432}\u{2E433}\u{2E434}\u{2E435}\u{2E436}\u{2E437}\u{2E438}\u{2E439}\u{2E43A}\u{2E43B}\u{2E43C}\u{2E43D}\u{2E43E}\u{2E43F}\u{2E440}\u{2E441}\u{2E442}\u{2E443}\u{2E444}\u{2E445}\u{2E446}\u{2E447}\u{2E448}\u{2E449}\u{2E44A}\u{2E44B}\u{2E44C}\u{2E44D}\u{2E44E}\u{2E44F}\u{2E450}\u{2E451}\u{2E452}\u{2E453}\u{2E454}\u{2E455}\u{2E456}\u{2E457}\u{2E458}\u{2E459}\u{2E45A}\u{2E45B}\u{2E45C}\u{2E45D}\u{2E45E}\u{2E45F}\u{2E460}\u{2E461}\u{2E462}\u{2E463}\u{2E464}\u{2E465}\u{2E466}\u{2E467}\u{2E468}\u{2E469}\u{2E46A}\u{2E46B}\u{2E46C}\u{2E46D}\u{2E46E}\u{2E46F}\u{2E470}\u{2E471}\u{2E472}\u{2E473}\u{2E474}\u{2E475}\u{2E476}\u{2E477}\u{2E478}\u{2E479}\u{2E47A}\u{2E47B}\u{2E47C}\u{2E47D}\u{2E47E}\u{2E47F}\u{2E480}\u{2E481}\u{2E482}\u{2E483}\u{2E484}\u{2E485}\u{2E486}\u{2E487}\u{2E488}\u{2E489}\u{2E48A}\u{2E48B}\u{2E48C}\u{2E48D}\u{2E48E}\u{2E48F}\u{2E490}\u{2E491}\u{2E492}\u{2E493}\u{2E494}\u{2E495}\u{2E496}\u{2E497}\u{2E498}\u{2E499}\u{2E49A}\u{2E49B}\u{2E49C}\u{2E49D}\u{2E49E}\u{2E49F}\u{2E4A0}\u{2E4A1}\u{2E4A2}\u{2E4A3}\u{2E4A4}\u{2E4A5}\u{2E4A6}\u{2E4A7}\u{2E4A8}\u{2E4A9}\u{2E4AA}\u{2E4AB}\u{2E4AC}\u{2E4AD}\u{2E4AE}\u{2E4AF}\u{2E4B0}\u{2E4B1}\u{2E4B2}\u{2E4B3}\u{2E4B4}\u{2E4B5}\u{2E4B6}\u{2E4B7}\u{2E4B8}\u{2E4B9}\u{2E4BA}\u{2E4BB}\u{2E4BC}\u{2E4BD}\u{2E4BE}\u{2E4BF}\u{2E4C0}\u{2E4C1}\u{2E4C2}\u{2E4C3}\u{2E4C4}\u{2E4C5}\u{2E4C6}\u{2E4C7}\u{2E4C8}\u{2E4C9}\u{2E4CA}\u{2E4CB}\u{2E4CC}\u{2E4CD}\u{2E4CE}\u{2E4CF}\u{2E4D0}\u{2E4D1}\u{2E4D2}\u{2E4D3}\u{2E4D4}\u{2E4D5}\u{2E4D6}\u{2E4D7}\u{2E4D8}\u{2E4D9}\u{2E4DA}\u{2E4DB}\u{2E4DC}\u{2E4DD}\u{2E4DE}\u{2E4DF}\u{2E4E0}\u{2E4E1}\u{2E4E2}\u{2E4E3}\u{2E4E4}\u{2E4E5}\u{2E4E6}\u{2E4E7}\u{2E4E8}\u{2E4E9}\u{2E4EA}\u{2E4EB}\u{2E4EC}\u{2E4ED}\u{2E4EE}\u{2E4EF}\u{2E4F0}\u{2E4F1}\u{2E4F2}\u{2E4F3}\u{2E4F4}\u{2E4F5}\u{2E4F6}\u{2E4F7}\u{2E4F8}\u{2E4F9}\u{2E4FA}\u{2E4FB}\u{2E4FC}\u{2E4FD}\u{2E4FE}\u{2E4FF}\u{2E500}\u{2E501}\u{2E502}\u{2E503}\u{2E504}\u{2E505}\u{2E506}\u{2E507}\u{2E508}\u{2E509}\u{2E50A}\u{2E50B}\u{2E50C}\u{2E50D}\u{2E50E}\u{2E50F}\u{2E510}\u{2E511}\u{2E512}\u{2E513}\u{2E514}\u{2E515}\u{2E516}\u{2E517}\u{2E518}\u{2E519}\u{2E51A}\u{2E51B}\u{2E51C}\u{2E51D}\u{2E51E}\u{2E51F}\u{2E520}\u{2E521}\u{2E522}\u{2E523}\u{2E524}\u{2E525}\u{2E526}\u{2E527}\u{2E528}\u{2E529}\u{2E52A}\u{2E52B}\u{2E52C}\u{2E52D}\u{2E52E}\u{2E52F}\u{2E530}\u{2E531}\u{2E532}\u{2E533}\u{2E534}\u{2E535}\u{2E536}\u{2E537}\u{2E538}\u{2E539}\u{2E53A}\u{2E53B}\u{2E53C}\u{2E53D}\u{2E53E}\u{2E53F}\u{2E540}\u{2E541}\u{2E542}\u{2E543}\u{2E544}\u{2E545}\u{2E546}\u{2E547}\u{2E548}\u{2E549}\u{2E54A}\u{2E54B}\u{2E54C}\u{2E54D}\u{2E54E}\u{2E54F}\u{2E550}\u{2E551}\u{2E552}\u{2E553}\u{2E554}\u{2E555}\u{2E556}\u{2E557}\u{2E558}\u{2E559}\u{2E55A}\u{2E55B}\u{2E55C}\u{2E55D}\u{2E55E}\u{2E55F}\u{2E560}\u{2E561}\u{2E562}\u{2E563}\u{2E564}\u{2E565}\u{2E566}\u{2E567}\u{2E568}\u{2E569}\u{2E56A}\u{2E56B}\u{2E56C}\u{2E56D}\u{2E56E}\u{2E56F}\u{2E570}\u{2E571}\u{2E572}\u{2E573}\u{2E574}\u{2E575}\u{2E576}\u{2E577}\u{2E578}\u{2E579}\u{2E57A}\u{2E57B}\u{2E57C}\u{2E57D}\u{2E57E}\u{2E57F}\u{2E580}\u{2E581}\u{2E582}\u{2E583}\u{2E584}\u{2E585}\u{2E586}\u{2E587}\u{2E588}\u{2E589}\u{2E58A}\u{2E58B}\u{2E58C}\u{2E58D}\u{2E58E}\u{2E58F}\u{2E590}\u{2E591}\u{2E592}\u{2E593}\u{2E594}\u{2E595}\u{2E596}\u{2E597}\u{2E598}\u{2E599}\u{2E59A}\u{2E59B}\u{2E59C}\u{2E59D}\u{2E59E}\u{2E59F}\u{2E5A0}\u{2E5A1}\u{2E5A2}\u{2E5A3}\u{2E5A4}\u{2E5A5}\u{2E5A6}\u{2E5A7}\u{2E5A8}\u{2E5A9}\u{2E5AA}\u{2E5AB}\u{2E5AC}\u{2E5AD}\u{2E5AE}\u{2E5AF}\u{2E5B0}\u{2E5B1}\u{2E5B2}\u{2E5B3}\u{2E5B4}\u{2E5B5}\u{2E5B6}\u{2E5B7}\u{2E5B8}\u{2E5B9}\u{2E5BA}\u{2E5BB}\u{2E5BC}\u{2E5BD}\u{2E5BE}\u{2E5BF}\u{2E5C0}\u{2E5C1}\u{2E5C2}\u{2E5C3}\u{2E5C4}\u{2E5C5}\u{2E5C6}\u{2E5C7}\u{2E5C8}\u{2E5C9}\u{2E5CA}\u{2E5CB}\u{2E5CC}\u{2E5CD}\u{2E5CE}\u{2E5CF}\u{2E5D0}\u{2E5D1}\u{2E5D2}\u{2E5D3}\u{2E5D4}\u{2E5D5}\u{2E5D6}\u{2E5D7}\u{2E5D8}\u{2E5D9}\u{2E5DA}\u{2E5DB}\u{2E5DC}\u{2E5DD}\u{2E5DE}\u{2E5DF}\u{2E5E0}\u{2E5E1}\u{2E5E2}\u{2E5E3}\u{2E5E4}\u{2E5E5}\u{2E5E6}\u{2E5E7}\u{2E5E8}\u{2E5E9}\u{2E5EA}\u{2E5EB}\u{2E5EC}\u{2E5ED}\u{2E5EE}\u{2E5EF}\u{2E5F0}\u{2E5F1}\u{2E5F2}\u{2E5F3}\u{2E5F4}\u{2E5F5}\u{2E5F6}\u{2E5F7}\u{2E5F8}\u{2E5F9}\u{2E5FA}\u{2E5FB}\u{2E5FC}\u{2E5FD}\u{2E5FE}\u{2E5FF}\u{2E600}\u{2E601}\u{2E602}\u{2E603}\u{2E604}\u{2E605}\u{2E606}\u{2E607}\u{2E608}\u{2E609}\u{2E60A}\u{2E60B}\u{2E60C}\u{2E60D}\u{2E60E}\u{2E60F}\u{2E610}\u{2E611}\u{2E612}\u{2E613}\u{2E614}\u{2E615}\u{2E616}\u{2E617}\u{2E618}\u{2E619}\u{2E61A}\u{2E61B}\u{2E61C}\u{2E61D}\u{2E61E}\u{2E61F}\u{2E620}\u{2E621}\u{2E622}\u{2E623}\u{2E624}\u{2E625}\u{2E626}\u{2E627}\u{2E628}\u{2E629}\u{2E62A}\u{2E62B}\u{2E62C}\u{2E62D}\u{2E62E}\u{2E62F}\u{2E630}\u{2E631}\u{2E632}\u{2E633}\u{2E634}\u{2E635}\u{2E636}\u{2E637}\u{2E638}\u{2E639}\u{2E63A}\u{2E63B}\u{2E63C}\u{2E63D}\u{2E63E}\u{2E63F}\u{2E640}\u{2E641}\u{2E642}\u{2E643}\u{2E644}\u{2E645}\u{2E646}\u{2E647}\u{2E648}\u{2E649}\u{2E64A}\u{2E64B}\u{2E64C}\u{2E64D}\u{2E64E}\u{2E64F}\u{2E650}\u{2E651}\u{2E652}\u{2E653}\u{2E654}\u{2E655}\u{2E656}\u{2E657}\u{2E658}\u{2E659}\u{2E65A}\u{2E65B}\u{2E65C}\u{2E65D}\u{2E65E}\u{2E65F}\u{2E660}\u{2E661}\u{2E662}\u{2E663}\u{2E664}\u{2E665}\u{2E666}\u{2E667}\u{2E668}\u{2E669}\u{2E66A}\u{2E66B}\u{2E66C}\u{2E66D}\u{2E66E}\u{2E66F}\u{2E670}\u{2E671}\u{2E672}\u{2E673}\u{2E674}\u{2E675}\u{2E676}\u{2E677}\u{2E678}\u{2E679}\u{2E67A}\u{2E67B}\u{2E67C}\u{2E67D}\u{2E67E}\u{2E67F}\u{2E680}\u{2E681}\u{2E682}\u{2E683}\u{2E684}\u{2E685}\u{2E686}\u{2E687}\u{2E688}\u{2E689}\u{2E68A}\u{2E68B}\u{2E68C}\u{2E68D}\u{2E68E}\u{2E68F}\u{2E690}\u{2E691}\u{2E692}\u{2E693}\u{2E694}\u{2E695}\u{2E696}\u{2E697}\u{2E698}\u{2E699}\u{2E69A}\u{2E69B}\u{2E69C}\u{2E69D}\u{2E69E}\u{2E69F}\u{2E6A0}\u{2E6A1}\u{2E6A2}\u{2E6A3}\u{2E6A4}\u{2E6A5}\u{2E6A6}\u{2E6A7}\u{2E6A8}\u{2E6A9}\u{2E6AA}\u{2E6AB}\u{2E6AC}\u{2E6AD}\u{2E6AE}\u{2E6AF}\u{2E6B0}\u{2E6B1}\u{2E6B2}\u{2E6B3}\u{2E6B4}\u{2E6B5}\u{2E6B6}\u{2E6B7}\u{2E6B8}\u{2E6B9}\u{2E6BA}\u{2E6BB}\u{2E6BC}\u{2E6BD}\u{2E6BE}\u{2E6BF}\u{2E6C0}\u{2E6C1}\u{2E6C2}\u{2E6C3}\u{2E6C4}\u{2E6C5}\u{2E6C6}\u{2E6C7}\u{2E6C8}\u{2E6C9}\u{2E6CA}\u{2E6CB}\u{2E6CC}\u{2E6CD}\u{2E6CE}\u{2E6CF}\u{2E6D0}\u{2E6D1}\u{2E6D2}\u{2E6D3}\u{2E6D4}\u{2E6D5}\u{2E6D6}\u{2E6D7}\u{2E6D8}\u{2E6D9}\u{2E6DA}\u{2E6DB}\u{2E6DC}\u{2E6DD}\u{2E6DE}\u{2E6DF}\u{2E6E0}\u{2E6E1}\u{2E6E2}\u{2E6E3}\u{2E6E4}\u{2E6E5}\u{2E6E6}\u{2E6E7}\u{2E6E8}\u{2E6E9}\u{2E6EA}\u{2E6EB}\u{2E6EC}\u{2E6ED}\u{2E6EE}\u{2E6EF}\u{2E6F0}\u{2E6F1}\u{2E6F2}\u{2E6F3}\u{2E6F4}\u{2E6F5}\u{2E6F6}\u{2E6F7}\u{2E6F8}\u{2E6F9}\u{2E6FA}\u{2E6FB}\u{2E6FC}\u{2E6FD}\u{2E6FE}\u{2E6FF}\u{2E700}\u{2E701}\u{2E702}\u{2E703}\u{2E704}\u{2E705}\u{2E706}\u{2E707}\u{2E708}\u{2E709}\u{2E70A}\u{2E70B}\u{2E70C}\u{2E70D}\u{2E70E}\u{2E70F}\u{2E710}\u{2E711}\u{2E712}\u{2E713}\u{2E714}\u{2E715}\u{2E716}\u{2E717}\u{2E718}\u{2E719}\u{2E71A}\u{2E71B}\u{2E71C}\u{2E71D}\u{2E71E}\u{2E71F}\u{2E720}\u{2E721}\u{2E722}\u{2E723}\u{2E724}\u{2E725}\u{2E726}\u{2E727}\u{2E728}\u{2E729}\u{2E72A}\u{2E72B}\u{2E72C}\u{2E72D}\u{2E72E}\u{2E72F}\u{2E730}\u{2E731}\u{2E732}\u{2E733}\u{2E734}\u{2E735}\u{2E736}\u{2E737}\u{2E738}\u{2E739}\u{2E73A}\u{2E73B}\u{2E73C}\u{2E73D}\u{2E73E}\u{2E73F}\u{2E740}\u{2E741}\u{2E742}\u{2E743}\u{2E744}\u{2E745}\u{2E746}\u{2E747}\u{2E748}\u{2E749}\u{2E74A}\u{2E74B}\u{2E74C}\u{2E74D}\u{2E74E}\u{2E74F}\u{2E750}\u{2E751}\u{2E752}\u{2E753}\u{2E754}\u{2E755}\u{2E756}\u{2E757}\u{2E758}\u{2E759}\u{2E75A}\u{2E75B}\u{2E75C}\u{2E75D}\u{2E75E}\u{2E75F}\u{2E760}\u{2E761}\u{2E762}\u{2E763}\u{2E764}\u{2E765}\u{2E766}\u{2E767}\u{2E768}\u{2E769}\u{2E76A}\u{2E76B}\u{2E76C}\u{2E76D}\u{2E76E}\u{2E76F}\u{2E770}\u{2E771}\u{2E772}\u{2E773}\u{2E774}\u{2E775}\u{2E776}\u{2E777}\u{2E778}\u{2E779}\u{2E77A}\u{2E77B}\u{2E77C}\u{2E77D}\u{2E77E}\u{2E77F}\u{2E780}\u{2E781}\u{2E782}\u{2E783}\u{2E784}\u{2E785}\u{2E786}\u{2E787}\u{2E788}\u{2E789}\u{2E78A}\u{2E78B}\u{2E78C}\u{2E78D}\u{2E78E}\u{2E78F}\u{2E790}\u{2E791}\u{2E792}\u{2E793}\u{2E794}\u{2E795}\u{2E796}\u{2E797}\u{2E798}\u{2E799}\u{2E79A}\u{2E79B}\u{2E79C}\u{2E79D}\u{2E79E}\u{2E79F}\u{2E7A0}\u{2E7A1}\u{2E7A2}\u{2E7A3}\u{2E7A4}\u{2E7A5}\u{2E7A6}\u{2E7A7}\u{2E7A8}\u{2E7A9}\u{2E7AA}\u{2E7AB}\u{2E7AC}\u{2E7AD}\u{2E7AE}\u{2E7AF}\u{2E7B0}\u{2E7B1}\u{2E7B2}\u{2E7B3}\u{2E7B4}\u{2E7B5}\u{2E7B6}\u{2E7B7}\u{2E7B8}\u{2E7B9}\u{2E7BA}\u{2E7BB}\u{2E7BC}\u{2E7BD}\u{2E7BE}\u{2E7BF}\u{2E7C0}\u{2E7C1}\u{2E7C2}\u{2E7C3}\u{2E7C4}\u{2E7C5}\u{2E7C6}\u{2E7C7}\u{2E7C8}\u{2E7C9}\u{2E7CA}\u{2E7CB}\u{2E7CC}\u{2E7CD}\u{2E7CE}\u{2E7CF}\u{2E7D0}\u{2E7D1}\u{2E7D2}\u{2E7D3}\u{2E7D4}\u{2E7D5}\u{2E7D6}\u{2E7D7}\u{2E7D8}\u{2E7D9}\u{2E7DA}\u{2E7DB}\u{2E7DC}\u{2E7DD}\u{2E7DE}\u{2E7DF}\u{2E7E0}\u{2E7E1}\u{2E7E2}\u{2E7E3}\u{2E7E4}\u{2E7E5}\u{2E7E6}\u{2E7E7}\u{2E7E8}\u{2E7E9}\u{2E7EA}\u{2E7EB}\u{2E7EC}\u{2E7ED}\u{2E7EE}\u{2E7EF}\u{2E7F0}\u{2E7F1}\u{2E7F2}\u{2E7F3}\u{2E7F4}\u{2E7F5}\u{2E7F6}\u{2E7F7}\u{2E7F8}\u{2E7F9}\u{2E7FA}\u{2E7FB}\u{2E7FC}\u{2E7FD}\u{2E7FE}\u{2E7FF}\u{2E800}\u{2E801}\u{2E802}\u{2E803}\u{2E804}\u{2E805}\u{2E806}\u{2E807}\u{2E808}\u{2E809}\u{2E80A}\u{2E80B}\u{2E80C}\u{2E80D}\u{2E80E}\u{2E80F}\u{2E810}\u{2E811}\u{2E812}\u{2E813}\u{2E814}\u{2E815}\u{2E816}\u{2E817}\u{2E818}\u{2E819}\u{2E81A}\u{2E81B}\u{2E81C}\u{2E81D}\u{2E81E}\u{2E81F}\u{2E820}\u{2E821}\u{2E822}\u{2E823}\u{2E824}\u{2E825}\u{2E826}\u{2E827}\u{2E828}\u{2E829}\u{2E82A}\u{2E82B}\u{2E82C}\u{2E82D}\u{2E82E}\u{2E82F}\u{2E830}\u{2E831}\u{2E832}\u{2E833}\u{2E834}\u{2E835}\u{2E836}\u{2E837}\u{2E838}\u{2E839}\u{2E83A}\u{2E83B}\u{2E83C}\u{2E83D}\u{2E83E}\u{2E83F}\u{2E840}\u{2E841}\u{2E842}\u{2E843}\u{2E844}\u{2E845}\u{2E846}\u{2E847}\u{2E848}\u{2E849}\u{2E84A}\u{2E84B}\u{2E84C}\u{2E84D}\u{2E84E}\u{2E84F}\u{2E850}\u{2E851}\u{2E852}\u{2E853}\u{2E854}\u{2E855}\u{2E856}\u{2E857}\u{2E858}\u{2E859}\u{2E85A}\u{2E85B}\u{2E85C}\u{2E85D}\u{2E85E}\u{2E85F}\u{2E860}\u{2E861}\u{2E862}\u{2E863}\u{2E864}\u{2E865}\u{2E866}\u{2E867}\u{2E868}\u{2E869}\u{2E86A}\u{2E86B}\u{2E86C}\u{2E86D}\u{2E86E}\u{2E86F}\u{2E870}\u{2E871}\u{2E872}\u{2E873}\u{2E874}\u{2E875}\u{2E876}\u{2E877}\u{2E878}\u{2E879}\u{2E87A}\u{2E87B}\u{2E87C}\u{2E87D}\u{2E87E}\u{2E87F}\u{2E880}\u{2E881}\u{2E882}\u{2E883}\u{2E884}\u{2E885}\u{2E886}\u{2E887}\u{2E888}\u{2E889}\u{2E88A}\u{2E88B}\u{2E88C}\u{2E88D}\u{2E88E}\u{2E88F}\u{2E890}\u{2E891}\u{2E892}\u{2E893}\u{2E894}\u{2E895}\u{2E896}\u{2E897}\u{2E898}\u{2E899}\u{2E89A}\u{2E89B}\u{2E89C}\u{2E89D}\u{2E89E}\u{2E89F}\u{2E8A0}\u{2E8A1}\u{2E8A2}\u{2E8A3}\u{2E8A4}\u{2E8A5}\u{2E8A6}\u{2E8A7}\u{2E8A8}\u{2E8A9}\u{2E8AA}\u{2E8AB}\u{2E8AC}\u{2E8AD}\u{2E8AE}\u{2E8AF}\u{2E8B0}\u{2E8B1}\u{2E8B2}\u{2E8B3}\u{2E8B4}\u{2E8B5}\u{2E8B6}\u{2E8B7}\u{2E8B8}\u{2E8B9}\u{2E8BA}\u{2E8BB}\u{2E8BC}\u{2E8BD}\u{2E8BE}\u{2E8BF}\u{2E8C0}\u{2E8C1}\u{2E8C2}\u{2E8C3}\u{2E8C4}\u{2E8C5}\u{2E8C6}\u{2E8C7}\u{2E8C8}\u{2E8C9}\u{2E8CA}\u{2E8CB}\u{2E8CC}\u{2E8CD}\u{2E8CE}\u{2E8CF}\u{2E8D0}\u{2E8D1}\u{2E8D2}\u{2E8D3}\u{2E8D4}\u{2E8D5}\u{2E8D6}\u{2E8D7}\u{2E8D8}\u{2E8D9}\u{2E8DA}\u{2E8DB}\u{2E8DC}\u{2E8DD}\u{2E8DE}\u{2E8DF}\u{2E8E0}\u{2E8E1}\u{2E8E2}\u{2E8E3}\u{2E8E4}\u{2E8E5}\u{2E8E6}\u{2E8E7}\u{2E8E8}\u{2E8E9}\u{2E8EA}\u{2E8EB}\u{2E8EC}\u{2E8ED}\u{2E8EE}\u{2E8EF}\u{2E8F0}\u{2E8F1}\u{2E8F2}\u{2E8F3}\u{2E8F4}\u{2E8F5}\u{2E8F6}\u{2E8F7}\u{2E8F8}\u{2E8F9}\u{2E8FA}\u{2E8FB}\u{2E8FC}\u{2E8FD}\u{2E8FE}\u{2E8FF}\u{2E900}\u{2E901}\u{2E902}\u{2E903}\u{2E904}\u{2E905}\u{2E906}\u{2E907}\u{2E908}\u{2E909}\u{2E90A}\u{2E90B}\u{2E90C}\u{2E90D}\u{2E90E}\u{2E90F}\u{2E910}\u{2E911}\u{2E912}\u{2E913}\u{2E914}\u{2E915}\u{2E916}\u{2E917}\u{2E918}\u{2E919}\u{2E91A}\u{2E91B}\u{2E91C}\u{2E91D}\u{2E91E}\u{2E91F}\u{2E920}\u{2E921}\u{2E922}\u{2E923}\u{2E924}\u{2E925}\u{2E926}\u{2E927}\u{2E928}\u{2E929}\u{2E92A}\u{2E92B}\u{2E92C}\u{2E92D}\u{2E92E}\u{2E92F}\u{2E930}\u{2E931}\u{2E932}\u{2E933}\u{2E934}\u{2E935}\u{2E936}\u{2E937}\u{2E938}\u{2E939}\u{2E93A}\u{2E93B}\u{2E93C}\u{2E93D}\u{2E93E}\u{2E93F}\u{2E940}\u{2E941}\u{2E942}\u{2E943}\u{2E944}\u{2E945}\u{2E946}\u{2E947}\u{2E948}\u{2E949}\u{2E94A}\u{2E94B}\u{2E94C}\u{2E94D}\u{2E94E}\u{2E94F}\u{2E950}\u{2E951}\u{2E952}\u{2E953}\u{2E954}\u{2E955}\u{2E956}\u{2E957}\u{2E958}\u{2E959}\u{2E95A}\u{2E95B}\u{2E95C}\u{2E95D}\u{2E95E}\u{2E95F}\u{2E960}\u{2E961}\u{2E962}\u{2E963}\u{2E964}\u{2E965}\u{2E966}\u{2E967}\u{2E968}\u{2E969}\u{2E96A}\u{2E96B}\u{2E96C}\u{2E96D}\u{2E96E}\u{2E96F}\u{2E970}\u{2E971}\u{2E972}\u{2E973}\u{2E974}\u{2E975}\u{2E976}\u{2E977}\u{2E978}\u{2E979}\u{2E97A}\u{2E97B}\u{2E97C}\u{2E97D}\u{2E97E}\u{2E97F}\u{2E980}\u{2E981}\u{2E982}\u{2E983}\u{2E984}\u{2E985}\u{2E986}\u{2E987}\u{2E988}\u{2E989}\u{2E98A}\u{2E98B}\u{2E98C}\u{2E98D}\u{2E98E}\u{2E98F}\u{2E990}\u{2E991}\u{2E992}\u{2E993}\u{2E994}\u{2E995}\u{2E996}\u{2E997}\u{2E998}\u{2E999}\u{2E99A}\u{2E99B}\u{2E99C}\u{2E99D}\u{2E99E}\u{2E99F}\u{2E9A0}\u{2E9A1}\u{2E9A2}\u{2E9A3}\u{2E9A4}\u{2E9A5}\u{2E9A6}\u{2E9A7}\u{2E9A8}\u{2E9A9}\u{2E9AA}\u{2E9AB}\u{2E9AC}\u{2E9AD}\u{2E9AE}\u{2E9AF}\u{2E9B0}\u{2E9B1}\u{2E9B2}\u{2E9B3}\u{2E9B4}\u{2E9B5}\u{2E9B6}\u{2E9B7}\u{2E9B8}\u{2E9B9}\u{2E9BA}\u{2E9BB}\u{2E9BC}\u{2E9BD}\u{2E9BE}\u{2E9BF}\u{2E9C0}\u{2E9C1}\u{2E9C2}\u{2E9C3}\u{2E9C4}\u{2E9C5}\u{2E9C6}\u{2E9C7}\u{2E9C8}\u{2E9C9}\u{2E9CA}\u{2E9CB}\u{2E9CC}\u{2E9CD}\u{2E9CE}\u{2E9CF}\u{2E9D0}\u{2E9D1}\u{2E9D2}\u{2E9D3}\u{2E9D4}\u{2E9D5}\u{2E9D6}\u{2E9D7}\u{2E9D8}\u{2E9D9}\u{2E9DA}\u{2E9DB}\u{2E9DC}\u{2E9DD}\u{2E9DE}\u{2E9DF}\u{2E9E0}\u{2E9E1}\u{2E9E2}\u{2E9E3}\u{2E9E4}\u{2E9E5}\u{2E9E6}\u{2E9E7}\u{2E9E8}\u{2E9E9}\u{2E9EA}\u{2E9EB}\u{2E9EC}\u{2E9ED}\u{2E9EE}\u{2E9EF}\u{2E9F0}\u{2E9F1}\u{2E9F2}\u{2E9F3}\u{2E9F4}\u{2E9F5}\u{2E9F6}\u{2E9F7}\u{2E9F8}\u{2E9F9}\u{2E9FA}\u{2E9FB}\u{2E9FC}\u{2E9FD}\u{2E9FE}\u{2E9FF}\u{2EA00}\u{2EA01}\u{2EA02}\u{2EA03}\u{2EA04}\u{2EA05}\u{2EA06}\u{2EA07}\u{2EA08}\u{2EA09}\u{2EA0A}\u{2EA0B}\u{2EA0C}\u{2EA0D}\u{2EA0E}\u{2EA0F}\u{2EA10}\u{2EA11}\u{2EA12}\u{2EA13}\u{2EA14}\u{2EA15}\u{2EA16}\u{2EA17}\u{2EA18}\u{2EA19}\u{2EA1A}\u{2EA1B}\u{2EA1C}\u{2EA1D}\u{2EA1E}\u{2EA1F}\u{2EA20}\u{2EA21}\u{2EA22}\u{2EA23}\u{2EA24}\u{2EA25}\u{2EA26}\u{2EA27}\u{2EA28}\u{2EA29}\u{2EA2A}\u{2EA2B}\u{2EA2C}\u{2EA2D}\u{2EA2E}\u{2EA2F}\u{2EA30}\u{2EA31}\u{2EA32}\u{2EA33}\u{2EA34}\u{2EA35}\u{2EA36}\u{2EA37}\u{2EA38}\u{2EA39}\u{2EA3A}\u{2EA3B}\u{2EA3C}\u{2EA3D}\u{2EA3E}\u{2EA3F}\u{2EA40}\u{2EA41}\u{2EA42}\u{2EA43}\u{2EA44}\u{2EA45}\u{2EA46}\u{2EA47}\u{2EA48}\u{2EA49}\u{2EA4A}\u{2EA4B}\u{2EA4C}\u{2EA4D}\u{2EA4E}\u{2EA4F}\u{2EA50}\u{2EA51}\u{2EA52}\u{2EA53}\u{2EA54}\u{2EA55}\u{2EA56}\u{2EA57}\u{2EA58}\u{2EA59}\u{2EA5A}\u{2EA5B}\u{2EA5C}\u{2EA5D}\u{2EA5E}\u{2EA5F}\u{2EA60}\u{2EA61}\u{2EA62}\u{2EA63}\u{2EA64}\u{2EA65}\u{2EA66}\u{2EA67}\u{2EA68}\u{2EA69}\u{2EA6A}\u{2EA6B}\u{2EA6C}\u{2EA6D}\u{2EA6E}\u{2EA6F}\u{2EA70}\u{2EA71}\u{2EA72}\u{2EA73}\u{2EA74}\u{2EA75}\u{2EA76}\u{2EA77}\u{2EA78}\u{2EA79}\u{2EA7A}\u{2EA7B}\u{2EA7C}\u{2EA7D}\u{2EA7E}\u{2EA7F}\u{2EA80}\u{2EA81}\u{2EA82}\u{2EA83}\u{2EA84}\u{2EA85}\u{2EA86}\u{2EA87}\u{2EA88}\u{2EA89}\u{2EA8A}\u{2EA8B}\u{2EA8C}\u{2EA8D}\u{2EA8E}\u{2EA8F}\u{2EA90}\u{2EA91}\u{2EA92}\u{2EA93}\u{2EA94}\u{2EA95}\u{2EA96}\u{2EA97}\u{2EA98}\u{2EA99}\u{2EA9A}\u{2EA9B}\u{2EA9C}\u{2EA9D}\u{2EA9E}\u{2EA9F}\u{2EAA0}\u{2EAA1}\u{2EAA2}\u{2EAA3}\u{2EAA4}\u{2EAA5}\u{2EAA6}\u{2EAA7}\u{2EAA8}\u{2EAA9}\u{2EAAA}\u{2EAAB}\u{2EAAC}\u{2EAAD}\u{2EAAE}\u{2EAAF}\u{2EAB0}\u{2EAB1}\u{2EAB2}\u{2EAB3}\u{2EAB4}\u{2EAB5}\u{2EAB6}\u{2EAB7}\u{2EAB8}\u{2EAB9}\u{2EABA}\u{2EABB}\u{2EABC}\u{2EABD}\u{2EABE}\u{2EABF}\u{2EAC0}\u{2EAC1}\u{2EAC2}\u{2EAC3}\u{2EAC4}\u{2EAC5}\u{2EAC6}\u{2EAC7}\u{2EAC8}\u{2EAC9}\u{2EACA}\u{2EACB}\u{2EACC}\u{2EACD}\u{2EACE}\u{2EACF}\u{2EAD0}\u{2EAD1}\u{2EAD2}\u{2EAD3}\u{2EAD4}\u{2EAD5}\u{2EAD6}\u{2EAD7}\u{2EAD8}\u{2EAD9}\u{2EADA}\u{2EADB}\u{2EADC}\u{2EADD}\u{2EADE}\u{2EADF}\u{2EAE0}\u{2EAE1}\u{2EAE2}\u{2EAE3}\u{2EAE4}\u{2EAE5}\u{2EAE6}\u{2EAE7}\u{2EAE8}\u{2EAE9}\u{2EAEA}\u{2EAEB}\u{2EAEC}\u{2EAED}\u{2EAEE}\u{2EAEF}\u{2EAF0}\u{2EAF1}\u{2EAF2}\u{2EAF3}\u{2EAF4}\u{2EAF5}\u{2EAF6}\u{2EAF7}\u{2EAF8}\u{2EAF9}\u{2EAFA}\u{2EAFB}\u{2EAFC}\u{2EAFD}\u{2EAFE}\u{2EAFF}\u{2EB00}\u{2EB01}\u{2EB02}\u{2EB03}\u{2EB04}\u{2EB05}\u{2EB06}\u{2EB07}\u{2EB08}\u{2EB09}\u{2EB0A}\u{2EB0B}\u{2EB0C}\u{2EB0D}\u{2EB0E}\u{2EB0F}\u{2EB10}\u{2EB11}\u{2EB12}\u{2EB13}\u{2EB14}\u{2EB15}\u{2EB16}\u{2EB17}\u{2EB18}\u{2EB19}\u{2EB1A}\u{2EB1B}\u{2EB1C}\u{2EB1D}\u{2EB1E}\u{2EB1F}\u{2EB20}\u{2EB21}\u{2EB22}\u{2EB23}\u{2EB24}\u{2EB25}\u{2EB26}\u{2EB27}\u{2EB28}\u{2EB29}\u{2EB2A}\u{2EB2B}\u{2EB2C}\u{2EB2D}\u{2EB2E}\u{2EB2F}\u{2EB30}\u{2EB31}\u{2EB32}\u{2EB33}\u{2EB34}\u{2EB35}\u{2EB36}\u{2EB37}\u{2EB38}\u{2EB39}\u{2EB3A}\u{2EB3B}\u{2EB3C}\u{2EB3D}\u{2EB3E}\u{2EB3F}\u{2EB40}\u{2EB41}\u{2EB42}\u{2EB43}\u{2EB44}\u{2EB45}\u{2EB46}\u{2EB47}\u{2EB48}\u{2EB49}\u{2EB4A}\u{2EB4B}\u{2EB4C}\u{2EB4D}\u{2EB4E}\u{2EB4F}\u{2EB50}\u{2EB51}\u{2EB52}\u{2EB53}\u{2EB54}\u{2EB55}\u{2EB56}\u{2EB57}\u{2EB58}\u{2EB59}\u{2EB5A}\u{2EB5B}\u{2EB5C}\u{2EB5D}\u{2EB5E}\u{2EB5F}\u{2EB60}\u{2EB61}\u{2EB62}\u{2EB63}\u{2EB64}\u{2EB65}\u{2EB66}\u{2EB67}\u{2EB68}\u{2EB69}\u{2EB6A}\u{2EB6B}\u{2EB6C}\u{2EB6D}\u{2EB6E}\u{2EB6F}\u{2EB70}\u{2EB71}\u{2EB72}\u{2EB73}\u{2EB74}\u{2EB75}\u{2EB76}\u{2EB77}\u{2EB78}\u{2EB79}\u{2EB7A}\u{2EB7B}\u{2EB7C}\u{2EB7D}\u{2EB7E}\u{2EB7F}\u{2EB80}\u{2EB81}\u{2EB82}\u{2EB83}\u{2EB84}\u{2EB85}\u{2EB86}\u{2EB87}\u{2EB88}\u{2EB89}\u{2EB8A}\u{2EB8B}\u{2EB8C}\u{2EB8D}\u{2EB8E}\u{2EB8F}\u{2EB90}\u{2EB91}\u{2EB92}\u{2EB93}\u{2EB94}\u{2EB95}\u{2EB96}\u{2EB97}\u{2EB98}\u{2EB99}\u{2EB9A}\u{2EB9B}\u{2EB9C}\u{2EB9D}\u{2EB9E}\u{2EB9F}\u{2EBA0}\u{2EBA1}\u{2EBA2}\u{2EBA3}\u{2EBA4}\u{2EBA5}\u{2EBA6}\u{2EBA7}\u{2EBA8}\u{2EBA9}\u{2EBAA}\u{2EBAB}\u{2EBAC}\u{2EBAD}\u{2EBAE}\u{2EBAF}\u{2EBB0}\u{2EBB1}\u{2EBB2}\u{2EBB3}\u{2EBB4}\u{2EBB5}\u{2EBB6}\u{2EBB7}\u{2EBB8}\u{2EBB9}\u{2EBBA}\u{2EBBB}\u{2EBBC}\u{2EBBD}\u{2EBBE}\u{2EBBF}\u{2EBC0}\u{2EBC1}\u{2EBC2}\u{2EBC3}\u{2EBC4}\u{2EBC5}\u{2EBC6}\u{2EBC7}\u{2EBC8}\u{2EBC9}\u{2EBCA}\u{2EBCB}\u{2EBCC}\u{2EBCD}\u{2EBCE}\u{2EBCF}\u{2EBD0}\u{2EBD1}\u{2EBD2}\u{2EBD3}\u{2EBD4}\u{2EBD5}\u{2EBD6}\u{2EBD7}\u{2EBD8}\u{2EBD9}\u{2EBDA}\u{2EBDB}\u{2EBDC}\u{2EBDD}\u{2EBDE}\u{2EBDF}\u{2EBE0}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-class.js new file mode 100644 index 000000000000..c0ba5c452dde --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v10.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ࡠࡡࡢࡣࡤࡥࡦࡧࡨࡩࡪৼㄮ鿖鿗鿘鿙鿚鿛鿜鿝鿞鿟鿠鿡鿢鿣鿤鿥鿦鿧鿨鿩鿪𐌭𐌮𐌯𑨀𑨋𑨌𑨍𑨎𑨏𑨐𑨑𑨒𑨓𑨔𑨕𑨖𑨗𑨘𑨙𑨚𑨛𑨜𑨝𑨞𑨟𑨠𑨡𑨢𑨣𑨤𑨥𑨦𑨧𑨨𑨩𑨪𑨫𑨬𑨭𑨮𑨯𑨰𑨱𑨲𑨺𑩐𑩜𑩝𑩞𑩟𑩠𑩡𑩢𑩣𑩤𑩥𑩦𑩧𑩨𑩩𑩪𑩫𑩬𑩭𑩮𑩯𑩰𑩱𑩲𑩳𑩴𑩵𑩶𑩷𑩸𑩹𑩺𑩻𑩼𑩽𑩾𑩿𑪀𑪁𑪂𑪃𑪆𑪇𑪈𑪉𑴀𑴁𑴂𑴃𑴄𑴅𑴆𑴈𑴉𑴋𑴌𑴍𑴎𑴏𑴐𑴑𑴒𑴓𑴔𑴕𑴖𑴗𑴘𑴙𑴚𑴛𑴜𑴝𑴞𑴟𑴠𑴡𑴢𑴣𑴤𑴥𑴦𑴧𑴨𑴩𑴪𑴫𑴬𑴭𑴮𑴯𑴰𑵆𖿡𛀂𛀃𛀄𛀅𛀆𛀇𛀈𛀉𛀊𛀋𛀌𛀍𛀎𛀏𛀐𛀑𛀒𛀓𛀔𛀕𛀖𛀗𛀘𛀙𛀚𛀛𛀜𛀝𛀞𛀟𛀠𛀡𛀢𛀣𛀤𛀥𛀦𛀧𛀨𛀩𛀪𛀫𛀬𛀭𛀮𛀯𛀰𛀱𛀲𛀳𛀴𛀵𛀶𛀷𛀸𛀹𛀺𛀻𛀼𛀽𛀾𛀿𛁀𛁁𛁂𛁃𛁄𛁅𛁆𛁇𛁈𛁉𛁊𛁋𛁌𛁍𛁎𛁏𛁐𛁑𛁒𛁓𛁔𛁕𛁖𛁗𛁘𛁙𛁚𛁛𛁜𛁝𛁞𛁟𛁠𛁡𛁢𛁣𛁤𛁥𛁦𛁧𛁨𛁩𛁪𛁫𛁬𛁭𛁮𛁯𛁰𛁱𛁲𛁳𛁴𛁵𛁶𛁷𛁸𛁹𛁺𛁻𛁼𛁽𛁾𛁿𛂀𛂁𛂂𛂃𛂄𛂅𛂆𛂇𛂈𛂉𛂊𛂋𛂌𛂍𛂎𛂏𛂐𛂑𛂒𛂓𛂔𛂕𛂖𛂗𛂘𛂙𛂚𛂛𛂜𛂝𛂞𛂟𛂠𛂡𛂢𛂣𛂤𛂥𛂦𛂧𛂨𛂩𛂪𛂫𛂬𛂭𛂮𛂯𛂰𛂱𛂲𛂳𛂴𛂵𛂶𛂷𛂸𛂹𛂺𛂻𛂼𛂽𛂾𛂿𛃀𛃁𛃂𛃃𛃄𛃅𛃆𛃇𛃈𛃉𛃊𛃋𛃌𛃍𛃎𛃏𛃐𛃑𛃒𛃓𛃔𛃕𛃖𛃗𛃘𛃙𛃚𛃛𛃜𛃝𛃞𛃟𛃠𛃡𛃢𛃣𛃤𛃥𛃦𛃧𛃨𛃩𛃪𛃫𛃬𛃭𛃮𛃯𛃰𛃱𛃲𛃳𛃴𛃵𛃶𛃷𛃸𛃹𛃺𛃻𛃼𛃽𛃾𛃿𛄀𛄁𛄂𛄃𛄄𛄅𛄆𛄇𛄈𛄉𛄊𛄋𛄌𛄍𛄎𛄏𛄐𛄑𛄒𛄓𛄔𛄕𛄖𛄗𛄘𛄙𛄚𛄛𛄜𛄝𛄞𛅰𛅱𛅲𛅳𛅴𛅵𛅶𛅷𛅸𛅹𛅺𛅻𛅼𛅽𛅾𛅿𛆀𛆁𛆂𛆃𛆄𛆅𛆆𛆇𛆈𛆉𛆊𛆋𛆌𛆍𛆎𛆏𛆐𛆑𛆒𛆓𛆔𛆕𛆖𛆗𛆘𛆙𛆚𛆛𛆜𛆝𛆞𛆟𛆠𛆡𛆢𛆣𛆤𛆥𛆦𛆧𛆨𛆩𛆪𛆫𛆬𛆭𛆮𛆯𛆰𛆱𛆲𛆳𛆴𛆵𛆶𛆷𛆸𛆹𛆺𛆻𛆼𛆽𛆾𛆿𛇀𛇁𛇂𛇃𛇄𛇅𛇆𛇇𛇈𛇉𛇊𛇋𛇌𛇍𛇎𛇏𛇐𛇑𛇒𛇓𛇔𛇕𛇖𛇗𛇘𛇙𛇚𛇛𛇜𛇝𛇞𛇟𛇠𛇡𛇢𛇣𛇤𛇥𛇦𛇧𛇨𛇩𛇪𛇫𛇬𛇭𛇮𛇯𛇰𛇱𛇲𛇳𛇴𛇵𛇶𛇷𛇸𛇹𛇺𛇻𛇼𛇽𛇾𛇿𛈀𛈁𛈂𛈃𛈄𛈅𛈆𛈇𛈈𛈉𛈊𛈋𛈌𛈍𛈎𛈏𛈐𛈑𛈒𛈓𛈔𛈕𛈖𛈗𛈘𛈙𛈚𛈛𛈜𛈝𛈞𛈟𛈠𛈡𛈢𛈣𛈤𛈥𛈦𛈧𛈨𛈩𛈪𛈫𛈬𛈭𛈮𛈯𛈰𛈱𛈲𛈳𛈴𛈵𛈶𛈷𛈸𛈹𛈺𛈻𛈼𛈽𛈾𛈿𛉀𛉁𛉂𛉃𛉄𛉅𛉆𛉇𛉈𛉉𛉊𛉋𛉌𛉍𛉎𛉏𛉐𛉑𛉒𛉓𛉔𛉕𛉖𛉗𛉘𛉙𛉚𛉛𛉜𛉝𛉞𛉟𛉠𛉡𛉢𛉣𛉤𛉥𛉦𛉧𛉨𛉩𛉪𛉫𛉬𛉭𛉮𛉯𛉰𛉱𛉲𛉳𛉴𛉵𛉶𛉷𛉸𛉹𛉺𛉻𛉼𛉽𛉾𛉿𛊀𛊁𛊂𛊃𛊄𛊅𛊆𛊇𛊈𛊉𛊊𛊋𛊌𛊍𛊎𛊏𛊐𛊑𛊒𛊓𛊔𛊕𛊖𛊗𛊘𛊙𛊚𛊛𛊜𛊝𛊞𛊟𛊠𛊡𛊢𛊣𛊤𛊥𛊦𛊧𛊨𛊩𛊪𛊫𛊬𛊭𛊮𛊯𛊰𛊱𛊲𛊳𛊴𛊵𛊶𛊷𛊸𛊹𛊺𛊻𛊼𛊽𛊾𛊿𛋀𛋁𛋂𛋃𛋄𛋅𛋆𛋇𛋈𛋉𛋊𛋋𛋌𛋍𛋎𛋏𛋐𛋑𛋒𛋓𛋔𛋕𛋖𛋗𛋘𛋙𛋚𛋛𛋜𛋝𛋞𛋟𛋠𛋡𛋢𛋣𛋤𛋥𛋦𛋧𛋨𛋩𛋪𛋫𛋬𛋭𛋮𛋯𛋰𛋱𛋲𛋳𛋴𛋵𛋶𛋷𛋸𛋹𛋺𛋻𬺰𬺱𬺲𬺳𬺴𬺵𬺶𬺷𬺸𬺹𬺺𬺻𬺼𬺽𬺾𬺿𬻀𬻁𬻂𬻃𬻄𬻅𬻆𬻇𬻈𬻉𬻊𬻋𬻌𬻍𬻎𬻏𬻐𬻑𬻒𬻓𬻔𬻕𬻖𬻗𬻘𬻙𬻚𬻛𬻜𬻝𬻞𬻟𬻠𬻡𬻢𬻣𬻤𬻥𬻦𬻧𬻨𬻩𬻪𬻫𬻬𬻭𬻮𬻯𬻰𬻱𬻲𬻳𬻴𬻵𬻶𬻷𬻸𬻹𬻺𬻻𬻼𬻽𬻾𬻿𬼀𬼁𬼂𬼃𬼄𬼅𬼆𬼇𬼈𬼉𬼊𬼋𬼌𬼍𬼎𬼏𬼐𬼑𬼒𬼓𬼔𬼕𬼖𬼗𬼘𬼙𬼚𬼛𬼜𬼝𬼞𬼟𬼠𬼡𬼢𬼣𬼤𬼥𬼦𬼧𬼨𬼩𬼪𬼫𬼬𬼭𬼮𬼯𬼰𬼱𬼲𬼳𬼴𬼵𬼶𬼷𬼸𬼹𬼺𬼻𬼼𬼽𬼾𬼿𬽀𬽁𬽂𬽃𬽄𬽅𬽆𬽇𬽈𬽉𬽊𬽋𬽌𬽍𬽎𬽏𬽐𬽑𬽒𬽓𬽔𬽕𬽖𬽗𬽘𬽙𬽚𬽛𬽜𬽝𬽞𬽟𬽠𬽡𬽢𬽣𬽤𬽥𬽦𬽧𬽨𬽩𬽪𬽫𬽬𬽭𬽮𬽯𬽰𬽱𬽲𬽳𬽴𬽵𬽶𬽷𬽸𬽹𬽺𬽻𬽼𬽽𬽾𬽿𬾀𬾁𬾂𬾃𬾄𬾅𬾆𬾇𬾈𬾉𬾊𬾋𬾌𬾍𬾎𬾏𬾐𬾑𬾒𬾓𬾔𬾕𬾖𬾗𬾘𬾙𬾚𬾛𬾜𬾝𬾞𬾟𬾠𬾡𬾢𬾣𬾤𬾥𬾦𬾧𬾨𬾩𬾪𬾫𬾬𬾭𬾮𬾯𬾰𬾱𬾲𬾳𬾴𬾵𬾶𬾷𬾸𬾹𬾺𬾻𬾼𬾽𬾾𬾿𬿀𬿁𬿂𬿃𬿄𬿅𬿆𬿇𬿈𬿉𬿊𬿋𬿌𬿍𬿎𬿏𬿐𬿑𬿒𬿓𬿔𬿕𬿖𬿗𬿘𬿙𬿚𬿛𬿜𬿝𬿞𬿟𬿠𬿡𬿢𬿣𬿤𬿥𬿦𬿧𬿨𬿩𬿪𬿫𬿬𬿭𬿮𬿯𬿰𬿱𬿲𬿳𬿴𬿵𬿶𬿷𬿸𬿹𬿺𬿻𬿼𬿽𬿾𬿿𭀀𭀁𭀂𭀃𭀄𭀅𭀆𭀇𭀈𭀉𭀊𭀋𭀌𭀍𭀎𭀏𭀐𭀑𭀒𭀓𭀔𭀕𭀖𭀗𭀘𭀙𭀚𭀛𭀜𭀝𭀞𭀟𭀠𭀡𭀢𭀣𭀤𭀥𭀦𭀧𭀨𭀩𭀪𭀫𭀬𭀭𭀮𭀯𭀰𭀱𭀲𭀳𭀴𭀵𭀶𭀷𭀸𭀹𭀺𭀻𭀼𭀽𭀾𭀿𭁀𭁁𭁂𭁃𭁄𭁅𭁆𭁇𭁈𭁉𭁊𭁋𭁌𭁍𭁎𭁏𭁐𭁑𭁒𭁓𭁔𭁕𭁖𭁗𭁘𭁙𭁚𭁛𭁜𭁝𭁞𭁟𭁠𭁡𭁢𭁣𭁤𭁥𭁦𭁧𭁨𭁩𭁪𭁫𭁬𭁭𭁮𭁯𭁰𭁱𭁲𭁳𭁴𭁵𭁶𭁷𭁸𭁹𭁺𭁻𭁼𭁽𭁾𭁿𭂀𭂁𭂂𭂃𭂄𭂅𭂆𭂇𭂈𭂉𭂊𭂋𭂌𭂍𭂎𭂏𭂐𭂑𭂒𭂓𭂔𭂕𭂖𭂗𭂘𭂙𭂚𭂛𭂜𭂝𭂞𭂟𭂠𭂡𭂢𭂣𭂤𭂥𭂦𭂧𭂨𭂩𭂪𭂫𭂬𭂭𭂮𭂯𭂰𭂱𭂲𭂳𭂴𭂵𭂶𭂷𭂸𭂹𭂺𭂻𭂼𭂽𭂾𭂿𭃀𭃁𭃂𭃃𭃄𭃅𭃆𭃇𭃈𭃉𭃊𭃋𭃌𭃍𭃎𭃏𭃐𭃑𭃒𭃓𭃔𭃕𭃖𭃗𭃘𭃙𭃚𭃛𭃜𭃝𭃞𭃟𭃠𭃡𭃢𭃣𭃤𭃥𭃦𭃧𭃨𭃩𭃪𭃫𭃬𭃭𭃮𭃯𭃰𭃱𭃲𭃳𭃴𭃵𭃶𭃷𭃸𭃹𭃺𭃻𭃼𭃽𭃾𭃿𭄀𭄁𭄂𭄃𭄄𭄅𭄆𭄇𭄈𭄉𭄊𭄋𭄌𭄍𭄎𭄏𭄐𭄑𭄒𭄓𭄔𭄕𭄖𭄗𭄘𭄙𭄚𭄛𭄜𭄝𭄞𭄟𭄠𭄡𭄢𭄣𭄤𭄥𭄦𭄧𭄨𭄩𭄪𭄫𭄬𭄭𭄮𭄯𭄰𭄱𭄲𭄳𭄴𭄵𭄶𭄷𭄸𭄹𭄺𭄻𭄼𭄽𭄾𭄿𭅀𭅁𭅂𭅃𭅄𭅅𭅆𭅇𭅈𭅉𭅊𭅋𭅌𭅍𭅎𭅏𭅐𭅑𭅒𭅓𭅔𭅕𭅖𭅗𭅘𭅙𭅚𭅛𭅜𭅝𭅞𭅟𭅠𭅡𭅢𭅣𭅤𭅥𭅦𭅧𭅨𭅩𭅪𭅫𭅬𭅭𭅮𭅯𭅰𭅱𭅲𭅳𭅴𭅵𭅶𭅷𭅸𭅹𭅺𭅻𭅼𭅽𭅾𭅿𭆀𭆁𭆂𭆃𭆄𭆅𭆆𭆇𭆈𭆉𭆊𭆋𭆌𭆍𭆎𭆏𭆐𭆑𭆒𭆓𭆔𭆕𭆖𭆗𭆘𭆙𭆚𭆛𭆜𭆝𭆞𭆟𭆠𭆡𭆢𭆣𭆤𭆥𭆦𭆧𭆨𭆩𭆪𭆫𭆬𭆭𭆮𭆯𭆰𭆱𭆲𭆳𭆴𭆵𭆶𭆷𭆸𭆹𭆺𭆻𭆼𭆽𭆾𭆿𭇀𭇁𭇂𭇃𭇄𭇅𭇆𭇇𭇈𭇉𭇊𭇋𭇌𭇍𭇎𭇏𭇐𭇑𭇒𭇓𭇔𭇕𭇖𭇗𭇘𭇙𭇚𭇛𭇜𭇝𭇞𭇟𭇠𭇡𭇢𭇣𭇤𭇥𭇦𭇧𭇨𭇩𭇪𭇫𭇬𭇭𭇮𭇯𭇰𭇱𭇲𭇳𭇴𭇵𭇶𭇷𭇸𭇹𭇺𭇻𭇼𭇽𭇾𭇿𭈀𭈁𭈂𭈃𭈄𭈅𭈆𭈇𭈈𭈉𭈊𭈋𭈌𭈍𭈎𭈏𭈐𭈑𭈒𭈓𭈔𭈕𭈖𭈗𭈘𭈙𭈚𭈛𭈜𭈝𭈞𭈟𭈠𭈡𭈢𭈣𭈤𭈥𭈦𭈧𭈨𭈩𭈪𭈫𭈬𭈭𭈮𭈯𭈰𭈱𭈲𭈳𭈴𭈵𭈶𭈷𭈸𭈹𭈺𭈻𭈼𭈽𭈾𭈿𭉀𭉁𭉂𭉃𭉄𭉅𭉆𭉇𭉈𭉉𭉊𭉋𭉌𭉍𭉎𭉏𭉐𭉑𭉒𭉓𭉔𭉕𭉖𭉗𭉘𭉙𭉚𭉛𭉜𭉝𭉞𭉟𭉠𭉡𭉢𭉣𭉤𭉥𭉦𭉧𭉨𭉩𭉪𭉫𭉬𭉭𭉮𭉯𭉰𭉱𭉲𭉳𭉴𭉵𭉶𭉷𭉸𭉹𭉺𭉻𭉼𭉽𭉾𭉿𭊀𭊁𭊂𭊃𭊄𭊅𭊆𭊇𭊈𭊉𭊊𭊋𭊌𭊍𭊎𭊏𭊐𭊑𭊒𭊓𭊔𭊕𭊖𭊗𭊘𭊙𭊚𭊛𭊜𭊝𭊞𭊟𭊠𭊡𭊢𭊣𭊤𭊥𭊦𭊧𭊨𭊩𭊪𭊫𭊬𭊭𭊮𭊯𭊰𭊱𭊲𭊳𭊴𭊵𭊶𭊷𭊸𭊹𭊺𭊻𭊼𭊽𭊾𭊿𭋀𭋁𭋂𭋃𭋄𭋅𭋆𭋇𭋈𭋉𭋊𭋋𭋌𭋍𭋎𭋏𭋐𭋑𭋒𭋓𭋔𭋕𭋖𭋗𭋘𭋙𭋚𭋛𭋜𭋝𭋞𭋟𭋠𭋡𭋢𭋣𭋤𭋥𭋦𭋧𭋨𭋩𭋪𭋫𭋬𭋭𭋮𭋯𭋰𭋱𭋲𭋳𭋴𭋵𭋶𭋷𭋸𭋹𭋺𭋻𭋼𭋽𭋾𭋿𭌀𭌁𭌂𭌃𭌄𭌅𭌆𭌇𭌈𭌉𭌊𭌋𭌌𭌍𭌎𭌏𭌐𭌑𭌒𭌓𭌔𭌕𭌖𭌗𭌘𭌙𭌚𭌛𭌜𭌝𭌞𭌟𭌠𭌡𭌢𭌣𭌤𭌥𭌦𭌧𭌨𭌩𭌪𭌫𭌬𭌭𭌮𭌯𭌰𭌱𭌲𭌳𭌴𭌵𭌶𭌷𭌸𭌹𭌺𭌻𭌼𭌽𭌾𭌿𭍀𭍁𭍂𭍃𭍄𭍅𭍆𭍇𭍈𭍉𭍊𭍋𭍌𭍍𭍎𭍏𭍐𭍑𭍒𭍓𭍔𭍕𭍖𭍗𭍘𭍙𭍚𭍛𭍜𭍝𭍞𭍟𭍠𭍡𭍢𭍣𭍤𭍥𭍦𭍧𭍨𭍩𭍪𭍫𭍬𭍭𭍮𭍯𭍰𭍱𭍲𭍳𭍴𭍵𭍶𭍷𭍸𭍹𭍺𭍻𭍼𭍽𭍾𭍿𭎀𭎁𭎂𭎃𭎄𭎅𭎆𭎇𭎈𭎉𭎊𭎋𭎌𭎍𭎎𭎏𭎐𭎑𭎒𭎓𭎔𭎕𭎖𭎗𭎘𭎙𭎚𭎛𭎜𭎝𭎞𭎟𭎠𭎡𭎢𭎣𭎤𭎥𭎦𭎧𭎨𭎩𭎪𭎫𭎬𭎭𭎮𭎯𭎰𭎱𭎲𭎳𭎴𭎵𭎶𭎷𭎸𭎹𭎺𭎻𭎼𭎽𭎾𭎿𭏀𭏁𭏂𭏃𭏄𭏅𭏆𭏇𭏈𭏉𭏊𭏋𭏌𭏍𭏎𭏏𭏐𭏑𭏒𭏓𭏔𭏕𭏖𭏗𭏘𭏙𭏚𭏛𭏜𭏝𭏞𭏟𭏠𭏡𭏢𭏣𭏤𭏥𭏦𭏧𭏨𭏩𭏪𭏫𭏬𭏭𭏮𭏯𭏰𭏱𭏲𭏳𭏴𭏵𭏶𭏷𭏸𭏹𭏺𭏻𭏼𭏽𭏾𭏿𭐀𭐁𭐂𭐃𭐄𭐅𭐆𭐇𭐈𭐉𭐊𭐋𭐌𭐍𭐎𭐏𭐐𭐑𭐒𭐓𭐔𭐕𭐖𭐗𭐘𭐙𭐚𭐛𭐜𭐝𭐞𭐟𭐠𭐡𭐢𭐣𭐤𭐥𭐦𭐧𭐨𭐩𭐪𭐫𭐬𭐭𭐮𭐯𭐰𭐱𭐲𭐳𭐴𭐵𭐶𭐷𭐸𭐹𭐺𭐻𭐼𭐽𭐾𭐿𭑀𭑁𭑂𭑃𭑄𭑅𭑆𭑇𭑈𭑉𭑊𭑋𭑌𭑍𭑎𭑏𭑐𭑑𭑒𭑓𭑔𭑕𭑖𭑗𭑘𭑙𭑚𭑛𭑜𭑝𭑞𭑟𭑠𭑡𭑢𭑣𭑤𭑥𭑦𭑧𭑨𭑩𭑪𭑫𭑬𭑭𭑮𭑯𭑰𭑱𭑲𭑳𭑴𭑵𭑶𭑷𭑸𭑹𭑺𭑻𭑼𭑽𭑾𭑿𭒀𭒁𭒂𭒃𭒄𭒅𭒆𭒇𭒈𭒉𭒊𭒋𭒌𭒍𭒎𭒏𭒐𭒑𭒒𭒓𭒔𭒕𭒖𭒗𭒘𭒙𭒚𭒛𭒜𭒝𭒞𭒟𭒠𭒡𭒢𭒣𭒤𭒥𭒦𭒧𭒨𭒩𭒪𭒫𭒬𭒭𭒮𭒯𭒰𭒱𭒲𭒳𭒴𭒵𭒶𭒷𭒸𭒹𭒺𭒻𭒼𭒽𭒾𭒿𭓀𭓁𭓂𭓃𭓄𭓅𭓆𭓇𭓈𭓉𭓊𭓋𭓌𭓍𭓎𭓏𭓐𭓑𭓒𭓓𭓔𭓕𭓖𭓗𭓘𭓙𭓚𭓛𭓜𭓝𭓞𭓟𭓠𭓡𭓢𭓣𭓤𭓥𭓦𭓧𭓨𭓩𭓪𭓫𭓬𭓭𭓮𭓯𭓰𭓱𭓲𭓳𭓴𭓵𭓶𭓷𭓸𭓹𭓺𭓻𭓼𭓽𭓾𭓿𭔀𭔁𭔂𭔃𭔄𭔅𭔆𭔇𭔈𭔉𭔊𭔋𭔌𭔍𭔎𭔏𭔐𭔑𭔒𭔓𭔔𭔕𭔖𭔗𭔘𭔙𭔚𭔛𭔜𭔝𭔞𭔟𭔠𭔡𭔢𭔣𭔤𭔥𭔦𭔧𭔨𭔩𭔪𭔫𭔬𭔭𭔮𭔯𭔰𭔱𭔲𭔳𭔴𭔵𭔶𭔷𭔸𭔹𭔺𭔻𭔼𭔽𭔾𭔿𭕀𭕁𭕂𭕃𭕄𭕅𭕆𭕇𭕈𭕉𭕊𭕋𭕌𭕍𭕎𭕏𭕐𭕑𭕒𭕓𭕔𭕕𭕖𭕗𭕘𭕙𭕚𭕛𭕜𭕝𭕞𭕟𭕠𭕡𭕢𭕣𭕤𭕥𭕦𭕧𭕨𭕩𭕪𭕫𭕬𭕭𭕮𭕯𭕰𭕱𭕲𭕳𭕴𭕵𭕶𭕷𭕸𭕹𭕺𭕻𭕼𭕽𭕾𭕿𭖀𭖁𭖂𭖃𭖄𭖅𭖆𭖇𭖈𭖉𭖊𭖋𭖌𭖍𭖎𭖏𭖐𭖑𭖒𭖓𭖔𭖕𭖖𭖗𭖘𭖙𭖚𭖛𭖜𭖝𭖞𭖟𭖠𭖡𭖢𭖣𭖤𭖥𭖦𭖧𭖨𭖩𭖪𭖫𭖬𭖭𭖮𭖯𭖰𭖱𭖲𭖳𭖴𭖵𭖶𭖷𭖸𭖹𭖺𭖻𭖼𭖽𭖾𭖿𭗀𭗁𭗂𭗃𭗄𭗅𭗆𭗇𭗈𭗉𭗊𭗋𭗌𭗍𭗎𭗏𭗐𭗑𭗒𭗓𭗔𭗕𭗖𭗗𭗘𭗙𭗚𭗛𭗜𭗝𭗞𭗟𭗠𭗡𭗢𭗣𭗤𭗥𭗦𭗧𭗨𭗩𭗪𭗫𭗬𭗭𭗮𭗯𭗰𭗱𭗲𭗳𭗴𭗵𭗶𭗷𭗸𭗹𭗺𭗻𭗼𭗽𭗾𭗿𭘀𭘁𭘂𭘃𭘄𭘅𭘆𭘇𭘈𭘉𭘊𭘋𭘌𭘍𭘎𭘏𭘐𭘑𭘒𭘓𭘔𭘕𭘖𭘗𭘘𭘙𭘚𭘛𭘜𭘝𭘞𭘟𭘠𭘡𭘢𭘣𭘤𭘥𭘦𭘧𭘨𭘩𭘪𭘫𭘬𭘭𭘮𭘯𭘰𭘱𭘲𭘳𭘴𭘵𭘶𭘷𭘸𭘹𭘺𭘻𭘼𭘽𭘾𭘿𭙀𭙁𭙂𭙃𭙄𭙅𭙆𭙇𭙈𭙉𭙊𭙋𭙌𭙍𭙎𭙏𭙐𭙑𭙒𭙓𭙔𭙕𭙖𭙗𭙘𭙙𭙚𭙛𭙜𭙝𭙞𭙟𭙠𭙡𭙢𭙣𭙤𭙥𭙦𭙧𭙨𭙩𭙪𭙫𭙬𭙭𭙮𭙯𭙰𭙱𭙲𭙳𭙴𭙵𭙶𭙷𭙸𭙹𭙺𭙻𭙼𭙽𭙾𭙿𭚀𭚁𭚂𭚃𭚄𭚅𭚆𭚇𭚈𭚉𭚊𭚋𭚌𭚍𭚎𭚏𭚐𭚑𭚒𭚓𭚔𭚕𭚖𭚗𭚘𭚙𭚚𭚛𭚜𭚝𭚞𭚟𭚠𭚡𭚢𭚣𭚤𭚥𭚦𭚧𭚨𭚩𭚪𭚫𭚬𭚭𭚮𭚯𭚰𭚱𭚲𭚳𭚴𭚵𭚶𭚷𭚸𭚹𭚺𭚻𭚼𭚽𭚾𭚿𭛀𭛁𭛂𭛃𭛄𭛅𭛆𭛇𭛈𭛉𭛊𭛋𭛌𭛍𭛎𭛏𭛐𭛑𭛒𭛓𭛔𭛕𭛖𭛗𭛘𭛙𭛚𭛛𭛜𭛝𭛞𭛟𭛠𭛡𭛢𭛣𭛤𭛥𭛦𭛧𭛨𭛩𭛪𭛫𭛬𭛭𭛮𭛯𭛰𭛱𭛲𭛳𭛴𭛵𭛶𭛷𭛸𭛹𭛺𭛻𭛼𭛽𭛾𭛿𭜀𭜁𭜂𭜃𭜄𭜅𭜆𭜇𭜈𭜉𭜊𭜋𭜌𭜍𭜎𭜏𭜐𭜑𭜒𭜓𭜔𭜕𭜖𭜗𭜘𭜙𭜚𭜛𭜜𭜝𭜞𭜟𭜠𭜡𭜢𭜣𭜤𭜥𭜦𭜧𭜨𭜩𭜪𭜫𭜬𭜭𭜮𭜯𭜰𭜱𭜲𭜳𭜴𭜵𭜶𭜷𭜸𭜹𭜺𭜻𭜼𭜽𭜾𭜿𭝀𭝁𭝂𭝃𭝄𭝅𭝆𭝇𭝈𭝉𭝊𭝋𭝌𭝍𭝎𭝏𭝐𭝑𭝒𭝓𭝔𭝕𭝖𭝗𭝘𭝙𭝚𭝛𭝜𭝝𭝞𭝟𭝠𭝡𭝢𭝣𭝤𭝥𭝦𭝧𭝨𭝩𭝪𭝫𭝬𭝭𭝮𭝯𭝰𭝱𭝲𭝳𭝴𭝵𭝶𭝷𭝸𭝹𭝺𭝻𭝼𭝽𭝾𭝿𭞀𭞁𭞂𭞃𭞄𭞅𭞆𭞇𭞈𭞉𭞊𭞋𭞌𭞍𭞎𭞏𭞐𭞑𭞒𭞓𭞔𭞕𭞖𭞗𭞘𭞙𭞚𭞛𭞜𭞝𭞞𭞟𭞠𭞡𭞢𭞣𭞤𭞥𭞦𭞧𭞨𭞩𭞪𭞫𭞬𭞭𭞮𭞯𭞰𭞱𭞲𭞳𭞴𭞵𭞶𭞷𭞸𭞹𭞺𭞻𭞼𭞽𭞾𭞿𭟀𭟁𭟂𭟃𭟄𭟅𭟆𭟇𭟈𭟉𭟊𭟋𭟌𭟍𭟎𭟏𭟐𭟑𭟒𭟓𭟔𭟕𭟖𭟗𭟘𭟙𭟚𭟛𭟜𭟝𭟞𭟟𭟠𭟡𭟢𭟣𭟤𭟥𭟦𭟧𭟨𭟩𭟪𭟫𭟬𭟭𭟮𭟯𭟰𭟱𭟲𭟳𭟴𭟵𭟶𭟷𭟸𭟹𭟺𭟻𭟼𭟽𭟾𭟿𭠀𭠁𭠂𭠃𭠄𭠅𭠆𭠇𭠈𭠉𭠊𭠋𭠌𭠍𭠎𭠏𭠐𭠑𭠒𭠓𭠔𭠕𭠖𭠗𭠘𭠙𭠚𭠛𭠜𭠝𭠞𭠟𭠠𭠡𭠢𭠣𭠤𭠥𭠦𭠧𭠨𭠩𭠪𭠫𭠬𭠭𭠮𭠯𭠰𭠱𭠲𭠳𭠴𭠵𭠶𭠷𭠸𭠹𭠺𭠻𭠼𭠽𭠾𭠿𭡀𭡁𭡂𭡃𭡄𭡅𭡆𭡇𭡈𭡉𭡊𭡋𭡌𭡍𭡎𭡏𭡐𭡑𭡒𭡓𭡔𭡕𭡖𭡗𭡘𭡙𭡚𭡛𭡜𭡝𭡞𭡟𭡠𭡡𭡢𭡣𭡤𭡥𭡦𭡧𭡨𭡩𭡪𭡫𭡬𭡭𭡮𭡯𭡰𭡱𭡲𭡳𭡴𭡵𭡶𭡷𭡸𭡹𭡺𭡻𭡼𭡽𭡾𭡿𭢀𭢁𭢂𭢃𭢄𭢅𭢆𭢇𭢈𭢉𭢊𭢋𭢌𭢍𭢎𭢏𭢐𭢑𭢒𭢓𭢔𭢕𭢖𭢗𭢘𭢙𭢚𭢛𭢜𭢝𭢞𭢟𭢠𭢡𭢢𭢣𭢤𭢥𭢦𭢧𭢨𭢩𭢪𭢫𭢬𭢭𭢮𭢯𭢰𭢱𭢲𭢳𭢴𭢵𭢶𭢷𭢸𭢹𭢺𭢻𭢼𭢽𭢾𭢿𭣀𭣁𭣂𭣃𭣄𭣅𭣆𭣇𭣈𭣉𭣊𭣋𭣌𭣍𭣎𭣏𭣐𭣑𭣒𭣓𭣔𭣕𭣖𭣗𭣘𭣙𭣚𭣛𭣜𭣝𭣞𭣟𭣠𭣡𭣢𭣣𭣤𭣥𭣦𭣧𭣨𭣩𭣪𭣫𭣬𭣭𭣮𭣯𭣰𭣱𭣲𭣳𭣴𭣵𭣶𭣷𭣸𭣹𭣺𭣻𭣼𭣽𭣾𭣿𭤀𭤁𭤂𭤃𭤄𭤅𭤆𭤇𭤈𭤉𭤊𭤋𭤌𭤍𭤎𭤏𭤐𭤑𭤒𭤓𭤔𭤕𭤖𭤗𭤘𭤙𭤚𭤛𭤜𭤝𭤞𭤟𭤠𭤡𭤢𭤣𭤤𭤥𭤦𭤧𭤨𭤩𭤪𭤫𭤬𭤭𭤮𭤯𭤰𭤱𭤲𭤳𭤴𭤵𭤶𭤷𭤸𭤹𭤺𭤻𭤼𭤽𭤾𭤿𭥀𭥁𭥂𭥃𭥄𭥅𭥆𭥇𭥈𭥉𭥊𭥋𭥌𭥍𭥎𭥏𭥐𭥑𭥒𭥓𭥔𭥕𭥖𭥗𭥘𭥙𭥚𭥛𭥜𭥝𭥞𭥟𭥠𭥡𭥢𭥣𭥤𭥥𭥦𭥧𭥨𭥩𭥪𭥫𭥬𭥭𭥮𭥯𭥰𭥱𭥲𭥳𭥴𭥵𭥶𭥷𭥸𭥹𭥺𭥻𭥼𭥽𭥾𭥿𭦀𭦁𭦂𭦃𭦄𭦅𭦆𭦇𭦈𭦉𭦊𭦋𭦌𭦍𭦎𭦏𭦐𭦑𭦒𭦓𭦔𭦕𭦖𭦗𭦘𭦙𭦚𭦛𭦜𭦝𭦞𭦟𭦠𭦡𭦢𭦣𭦤𭦥𭦦𭦧𭦨𭦩𭦪𭦫𭦬𭦭𭦮𭦯𭦰𭦱𭦲𭦳𭦴𭦵𭦶𭦷𭦸𭦹𭦺𭦻𭦼𭦽𭦾𭦿𭧀𭧁𭧂𭧃𭧄𭧅𭧆𭧇𭧈𭧉𭧊𭧋𭧌𭧍𭧎𭧏𭧐𭧑𭧒𭧓𭧔𭧕𭧖𭧗𭧘𭧙𭧚𭧛𭧜𭧝𭧞𭧟𭧠𭧡𭧢𭧣𭧤𭧥𭧦𭧧𭧨𭧩𭧪𭧫𭧬𭧭𭧮𭧯𭧰𭧱𭧲𭧳𭧴𭧵𭧶𭧷𭧸𭧹𭧺𭧻𭧼𭧽𭧾𭧿𭨀𭨁𭨂𭨃𭨄𭨅𭨆𭨇𭨈𭨉𭨊𭨋𭨌𭨍𭨎𭨏𭨐𭨑𭨒𭨓𭨔𭨕𭨖𭨗𭨘𭨙𭨚𭨛𭨜𭨝𭨞𭨟𭨠𭨡𭨢𭨣𭨤𭨥𭨦𭨧𭨨𭨩𭨪𭨫𭨬𭨭𭨮𭨯𭨰𭨱𭨲𭨳𭨴𭨵𭨶𭨷𭨸𭨹𭨺𭨻𭨼𭨽𭨾𭨿𭩀𭩁𭩂𭩃𭩄𭩅𭩆𭩇𭩈𭩉𭩊𭩋𭩌𭩍𭩎𭩏𭩐𭩑𭩒𭩓𭩔𭩕𭩖𭩗𭩘𭩙𭩚𭩛𭩜𭩝𭩞𭩟𭩠𭩡𭩢𭩣𭩤𭩥𭩦𭩧𭩨𭩩𭩪𭩫𭩬𭩭𭩮𭩯𭩰𭩱𭩲𭩳𭩴𭩵𭩶𭩷𭩸𭩹𭩺𭩻𭩼𭩽𭩾𭩿𭪀𭪁𭪂𭪃𭪄𭪅𭪆𭪇𭪈𭪉𭪊𭪋𭪌𭪍𭪎𭪏𭪐𭪑𭪒𭪓𭪔𭪕𭪖𭪗𭪘𭪙𭪚𭪛𭪜𭪝𭪞𭪟𭪠𭪡𭪢𭪣𭪤𭪥𭪦𭪧𭪨𭪩𭪪𭪫𭪬𭪭𭪮𭪯𭪰𭪱𭪲𭪳𭪴𭪵𭪶𭪷𭪸𭪹𭪺𭪻𭪼𭪽𭪾𭪿𭫀𭫁𭫂𭫃𭫄𭫅𭫆𭫇𭫈𭫉𭫊𭫋𭫌𭫍𭫎𭫏𭫐𭫑𭫒𭫓𭫔𭫕𭫖𭫗𭫘𭫙𭫚𭫛𭫜𭫝𭫞𭫟𭫠𭫡𭫢𭫣𭫤𭫥𭫦𭫧𭫨𭫩𭫪𭫫𭫬𭫭𭫮𭫯𭫰𭫱𭫲𭫳𭫴𭫵𭫶𭫷𭫸𭫹𭫺𭫻𭫼𭫽𭫾𭫿𭬀𭬁𭬂𭬃𭬄𭬅𭬆𭬇𭬈𭬉𭬊𭬋𭬌𭬍𭬎𭬏𭬐𭬑𭬒𭬓𭬔𭬕𭬖𭬗𭬘𭬙𭬚𭬛𭬜𭬝𭬞𭬟𭬠𭬡𭬢𭬣𭬤𭬥𭬦𭬧𭬨𭬩𭬪𭬫𭬬𭬭𭬮𭬯𭬰𭬱𭬲𭬳𭬴𭬵𭬶𭬷𭬸𭬹𭬺𭬻𭬼𭬽𭬾𭬿𭭀𭭁𭭂𭭃𭭄𭭅𭭆𭭇𭭈𭭉𭭊𭭋𭭌𭭍𭭎𭭏𭭐𭭑𭭒𭭓𭭔𭭕𭭖𭭗𭭘𭭙𭭚𭭛𭭜𭭝𭭞𭭟𭭠𭭡𭭢𭭣𭭤𭭥𭭦𭭧𭭨𭭩𭭪𭭫𭭬𭭭𭭮𭭯𭭰𭭱𭭲𭭳𭭴𭭵𭭶𭭷𭭸𭭹𭭺𭭻𭭼𭭽𭭾𭭿𭮀𭮁𭮂𭮃𭮄𭮅𭮆𭮇𭮈𭮉𭮊𭮋𭮌𭮍𭮎𭮏𭮐𭮑𭮒𭮓𭮔𭮕𭮖𭮗𭮘𭮙𭮚𭮛𭮜𭮝𭮞𭮟𭮠𭮡𭮢𭮣𭮤𭮥𭮦𭮧𭮨𭮩𭮪𭮫𭮬𭮭𭮮𭮯𭮰𭮱𭮲𭮳𭮴𭮵𭮶𭮷𭮸𭮹𭮺𭮻𭮼𭮽𭮾𭮿𭯀𭯁𭯂𭯃𭯄𭯅𭯆𭯇𭯈𭯉𭯊𭯋𭯌𭯍𭯎𭯏𭯐𭯑𭯒𭯓𭯔𭯕𭯖𭯗𭯘𭯙𭯚𭯛𭯜𭯝𭯞𭯟𭯠𭯡𭯢𭯣𭯤𭯥𭯦𭯧𭯨𭯩𭯪𭯫𭯬𭯭𭯮𭯯𭯰𭯱𭯲𭯳𭯴𭯵𭯶𭯷𭯸𭯹𭯺𭯻𭯼𭯽𭯾𭯿𭰀𭰁𭰂𭰃𭰄𭰅𭰆𭰇𭰈𭰉𭰊𭰋𭰌𭰍𭰎𭰏𭰐𭰑𭰒𭰓𭰔𭰕𭰖𭰗𭰘𭰙𭰚𭰛𭰜𭰝𭰞𭰟𭰠𭰡𭰢𭰣𭰤𭰥𭰦𭰧𭰨𭰩𭰪𭰫𭰬𭰭𭰮𭰯𭰰𭰱𭰲𭰳𭰴𭰵𭰶𭰷𭰸𭰹𭰺𭰻𭰼𭰽𭰾𭰿𭱀𭱁𭱂𭱃𭱄𭱅𭱆𭱇𭱈𭱉𭱊𭱋𭱌𭱍𭱎𭱏𭱐𭱑𭱒𭱓𭱔𭱕𭱖𭱗𭱘𭱙𭱚𭱛𭱜𭱝𭱞𭱟𭱠𭱡𭱢𭱣𭱤𭱥𭱦𭱧𭱨𭱩𭱪𭱫𭱬𭱭𭱮𭱯𭱰𭱱𭱲𭱳𭱴𭱵𭱶𭱷𭱸𭱹𭱺𭱻𭱼𭱽𭱾𭱿𭲀𭲁𭲂𭲃𭲄𭲅𭲆𭲇𭲈𭲉𭲊𭲋𭲌𭲍𭲎𭲏𭲐𭲑𭲒𭲓𭲔𭲕𭲖𭲗𭲘𭲙𭲚𭲛𭲜𭲝𭲞𭲟𭲠𭲡𭲢𭲣𭲤𭲥𭲦𭲧𭲨𭲩𭲪𭲫𭲬𭲭𭲮𭲯𭲰𭲱𭲲𭲳𭲴𭲵𭲶𭲷𭲸𭲹𭲺𭲻𭲼𭲽𭲾𭲿𭳀𭳁𭳂𭳃𭳄𭳅𭳆𭳇𭳈𭳉𭳊𭳋𭳌𭳍𭳎𭳏𭳐𭳑𭳒𭳓𭳔𭳕𭳖𭳗𭳘𭳙𭳚𭳛𭳜𭳝𭳞𭳟𭳠𭳡𭳢𭳣𭳤𭳥𭳦𭳧𭳨𭳩𭳪𭳫𭳬𭳭𭳮𭳯𭳰𭳱𭳲𭳳𭳴𭳵𭳶𭳷𭳸𭳹𭳺𭳻𭳼𭳽𭳾𭳿𭴀𭴁𭴂𭴃𭴄𭴅𭴆𭴇𭴈𭴉𭴊𭴋𭴌𭴍𭴎𭴏𭴐𭴑𭴒𭴓𭴔𭴕𭴖𭴗𭴘𭴙𭴚𭴛𭴜𭴝𭴞𭴟𭴠𭴡𭴢𭴣𭴤𭴥𭴦𭴧𭴨𭴩𭴪𭴫𭴬𭴭𭴮𭴯𭴰𭴱𭴲𭴳𭴴𭴵𭴶𭴷𭴸𭴹𭴺𭴻𭴼𭴽𭴾𭴿𭵀𭵁𭵂𭵃𭵄𭵅𭵆𭵇𭵈𭵉𭵊𭵋𭵌𭵍𭵎𭵏𭵐𭵑𭵒𭵓𭵔𭵕𭵖𭵗𭵘𭵙𭵚𭵛𭵜𭵝𭵞𭵟𭵠𭵡𭵢𭵣𭵤𭵥𭵦𭵧𭵨𭵩𭵪𭵫𭵬𭵭𭵮𭵯𭵰𭵱𭵲𭵳𭵴𭵵𭵶𭵷𭵸𭵹𭵺𭵻𭵼𭵽𭵾𭵿𭶀𭶁𭶂𭶃𭶄𭶅𭶆𭶇𭶈𭶉𭶊𭶋𭶌𭶍𭶎𭶏𭶐𭶑𭶒𭶓𭶔𭶕𭶖𭶗𭶘𭶙𭶚𭶛𭶜𭶝𭶞𭶟𭶠𭶡𭶢𭶣𭶤𭶥𭶦𭶧𭶨𭶩𭶪𭶫𭶬𭶭𭶮𭶯𭶰𭶱𭶲𭶳𭶴𭶵𭶶𭶷𭶸𭶹𭶺𭶻𭶼𭶽𭶾𭶿𭷀𭷁𭷂𭷃𭷄𭷅𭷆𭷇𭷈𭷉𭷊𭷋𭷌𭷍𭷎𭷏𭷐𭷑𭷒𭷓𭷔𭷕𭷖𭷗𭷘𭷙𭷚𭷛𭷜𭷝𭷞𭷟𭷠𭷡𭷢𭷣𭷤𭷥𭷦𭷧𭷨𭷩𭷪𭷫𭷬𭷭𭷮𭷯𭷰𭷱𭷲𭷳𭷴𭷵𭷶𭷷𭷸𭷹𭷺𭷻𭷼𭷽𭷾𭷿𭸀𭸁𭸂𭸃𭸄𭸅𭸆𭸇𭸈𭸉𭸊𭸋𭸌𭸍𭸎𭸏𭸐𭸑𭸒𭸓𭸔𭸕𭸖𭸗𭸘𭸙𭸚𭸛𭸜𭸝𭸞𭸟𭸠𭸡𭸢𭸣𭸤𭸥𭸦𭸧𭸨𭸩𭸪𭸫𭸬𭸭𭸮𭸯𭸰𭸱𭸲𭸳𭸴𭸵𭸶𭸷𭸸𭸹𭸺𭸻𭸼𭸽𭸾𭸿𭹀𭹁𭹂𭹃𭹄𭹅𭹆𭹇𭹈𭹉𭹊𭹋𭹌𭹍𭹎𭹏𭹐𭹑𭹒𭹓𭹔𭹕𭹖𭹗𭹘𭹙𭹚𭹛𭹜𭹝𭹞𭹟𭹠𭹡𭹢𭹣𭹤𭹥𭹦𭹧𭹨𭹩𭹪𭹫𭹬𭹭𭹮𭹯𭹰𭹱𭹲𭹳𭹴𭹵𭹶𭹷𭹸𭹹𭹺𭹻𭹼𭹽𭹾𭹿𭺀𭺁𭺂𭺃𭺄𭺅𭺆𭺇𭺈𭺉𭺊𭺋𭺌𭺍𭺎𭺏𭺐𭺑𭺒𭺓𭺔𭺕𭺖𭺗𭺘𭺙𭺚𭺛𭺜𭺝𭺞𭺟𭺠𭺡𭺢𭺣𭺤𭺥𭺦𭺧𭺨𭺩𭺪𭺫𭺬𭺭𭺮𭺯𭺰𭺱𭺲𭺳𭺴𭺵𭺶𭺷𭺸𭺹𭺺𭺻𭺼𭺽𭺾𭺿𭻀𭻁𭻂𭻃𭻄𭻅𭻆𭻇𭻈𭻉𭻊𭻋𭻌𭻍𭻎𭻏𭻐𭻑𭻒𭻓𭻔𭻕𭻖𭻗𭻘𭻙𭻚𭻛𭻜𭻝𭻞𭻟𭻠𭻡𭻢𭻣𭻤𭻥𭻦𭻧𭻨𭻩𭻪𭻫𭻬𭻭𭻮𭻯𭻰𭻱𭻲𭻳𭻴𭻵𭻶𭻷𭻸𭻹𭻺𭻻𭻼𭻽𭻾𭻿𭼀𭼁𭼂𭼃𭼄𭼅𭼆𭼇𭼈𭼉𭼊𭼋𭼌𭼍𭼎𭼏𭼐𭼑𭼒𭼓𭼔𭼕𭼖𭼗𭼘𭼙𭼚𭼛𭼜𭼝𭼞𭼟𭼠𭼡𭼢𭼣𭼤𭼥𭼦𭼧𭼨𭼩𭼪𭼫𭼬𭼭𭼮𭼯𭼰𭼱𭼲𭼳𭼴𭼵𭼶𭼷𭼸𭼹𭼺𭼻𭼼𭼽𭼾𭼿𭽀𭽁𭽂𭽃𭽄𭽅𭽆𭽇𭽈𭽉𭽊𭽋𭽌𭽍𭽎𭽏𭽐𭽑𭽒𭽓𭽔𭽕𭽖𭽗𭽘𭽙𭽚𭽛𭽜𭽝𭽞𭽟𭽠𭽡𭽢𭽣𭽤𭽥𭽦𭽧𭽨𭽩𭽪𭽫𭽬𭽭𭽮𭽯𭽰𭽱𭽲𭽳𭽴𭽵𭽶𭽷𭽸𭽹𭽺𭽻𭽼𭽽𭽾𭽿𭾀𭾁𭾂𭾃𭾄𭾅𭾆𭾇𭾈𭾉𭾊𭾋𭾌𭾍𭾎𭾏𭾐𭾑𭾒𭾓𭾔𭾕𭾖𭾗𭾘𭾙𭾚𭾛𭾜𭾝𭾞𭾟𭾠𭾡𭾢𭾣𭾤𭾥𭾦𭾧𭾨𭾩𭾪𭾫𭾬𭾭𭾮𭾯𭾰𭾱𭾲𭾳𭾴𭾵𭾶𭾷𭾸𭾹𭾺𭾻𭾼𭾽𭾾𭾿𭿀𭿁𭿂𭿃𭿄𭿅𭿆𭿇𭿈𭿉𭿊𭿋𭿌𭿍𭿎𭿏𭿐𭿑𭿒𭿓𭿔𭿕𭿖𭿗𭿘𭿙𭿚𭿛𭿜𭿝𭿞𭿟𭿠𭿡𭿢𭿣𭿤𭿥𭿦𭿧𭿨𭿩𭿪𭿫𭿬𭿭𭿮𭿯𭿰𭿱𭿲𭿳𭿴𭿵𭿶𭿷𭿸𭿹𭿺𭿻𭿼𭿽𭿾𭿿𮀀𮀁𮀂𮀃𮀄𮀅𮀆𮀇𮀈𮀉𮀊𮀋𮀌𮀍𮀎𮀏𮀐𮀑𮀒𮀓𮀔𮀕𮀖𮀗𮀘𮀙𮀚𮀛𮀜𮀝𮀞𮀟𮀠𮀡𮀢𮀣𮀤𮀥𮀦𮀧𮀨𮀩𮀪𮀫𮀬𮀭𮀮𮀯𮀰𮀱𮀲𮀳𮀴𮀵𮀶𮀷𮀸𮀹𮀺𮀻𮀼𮀽𮀾𮀿𮁀𮁁𮁂𮁃𮁄𮁅𮁆𮁇𮁈𮁉𮁊𮁋𮁌𮁍𮁎𮁏𮁐𮁑𮁒𮁓𮁔𮁕𮁖𮁗𮁘𮁙𮁚𮁛𮁜𮁝𮁞𮁟𮁠𮁡𮁢𮁣𮁤𮁥𮁦𮁧𮁨𮁩𮁪𮁫𮁬𮁭𮁮𮁯𮁰𮁱𮁲𮁳𮁴𮁵𮁶𮁷𮁸𮁹𮁺𮁻𮁼𮁽𮁾𮁿𮂀𮂁𮂂𮂃𮂄𮂅𮂆𮂇𮂈𮂉𮂊𮂋𮂌𮂍𮂎𮂏𮂐𮂑𮂒𮂓𮂔𮂕𮂖𮂗𮂘𮂙𮂚𮂛𮂜𮂝𮂞𮂟𮂠𮂡𮂢𮂣𮂤𮂥𮂦𮂧𮂨𮂩𮂪𮂫𮂬𮂭𮂮𮂯𮂰𮂱𮂲𮂳𮂴𮂵𮂶𮂷𮂸𮂹𮂺𮂻𮂼𮂽𮂾𮂿𮃀𮃁𮃂𮃃𮃄𮃅𮃆𮃇𮃈𮃉𮃊𮃋𮃌𮃍𮃎𮃏𮃐𮃑𮃒𮃓𮃔𮃕𮃖𮃗𮃘𮃙𮃚𮃛𮃜𮃝𮃞𮃟𮃠𮃡𮃢𮃣𮃤𮃥𮃦𮃧𮃨𮃩𮃪𮃫𮃬𮃭𮃮𮃯𮃰𮃱𮃲𮃳𮃴𮃵𮃶𮃷𮃸𮃹𮃺𮃻𮃼𮃽𮃾𮃿𮄀𮄁𮄂𮄃𮄄𮄅𮄆𮄇𮄈𮄉𮄊𮄋𮄌𮄍𮄎𮄏𮄐𮄑𮄒𮄓𮄔𮄕𮄖𮄗𮄘𮄙𮄚𮄛𮄜𮄝𮄞𮄟𮄠𮄡𮄢𮄣𮄤𮄥𮄦𮄧𮄨𮄩𮄪𮄫𮄬𮄭𮄮𮄯𮄰𮄱𮄲𮄳𮄴𮄵𮄶𮄷𮄸𮄹𮄺𮄻𮄼𮄽𮄾𮄿𮅀𮅁𮅂𮅃𮅄𮅅𮅆𮅇𮅈𮅉𮅊𮅋𮅌𮅍𮅎𮅏𮅐𮅑𮅒𮅓𮅔𮅕𮅖𮅗𮅘𮅙𮅚𮅛𮅜𮅝𮅞𮅟𮅠𮅡𮅢𮅣𮅤𮅥𮅦𮅧𮅨𮅩𮅪𮅫𮅬𮅭𮅮𮅯𮅰𮅱𮅲𮅳𮅴𮅵𮅶𮅷𮅸𮅹𮅺𮅻𮅼𮅽𮅾𮅿𮆀𮆁𮆂𮆃𮆄𮆅𮆆𮆇𮆈𮆉𮆊𮆋𮆌𮆍𮆎𮆏𮆐𮆑𮆒𮆓𮆔𮆕𮆖𮆗𮆘𮆙𮆚𮆛𮆜𮆝𮆞𮆟𮆠𮆡𮆢𮆣𮆤𮆥𮆦𮆧𮆨𮆩𮆪𮆫𮆬𮆭𮆮𮆯𮆰𮆱𮆲𮆳𮆴𮆵𮆶𮆷𮆸𮆹𮆺𮆻𮆼𮆽𮆾𮆿𮇀𮇁𮇂𮇃𮇄𮇅𮇆𮇇𮇈𮇉𮇊𮇋𮇌𮇍𮇎𮇏𮇐𮇑𮇒𮇓𮇔𮇕𮇖𮇗𮇘𮇙𮇚𮇛𮇜𮇝𮇞𮇟𮇠𮇡𮇢𮇣𮇤𮇥𮇦𮇧𮇨𮇩𮇪𮇫𮇬𮇭𮇮𮇯𮇰𮇱𮇲𮇳𮇴𮇵𮇶𮇷𮇸𮇹𮇺𮇻𮇼𮇽𮇾𮇿𮈀𮈁𮈂𮈃𮈄𮈅𮈆𮈇𮈈𮈉𮈊𮈋𮈌𮈍𮈎𮈏𮈐𮈑𮈒𮈓𮈔𮈕𮈖𮈗𮈘𮈙𮈚𮈛𮈜𮈝𮈞𮈟𮈠𮈡𮈢𮈣𮈤𮈥𮈦𮈧𮈨𮈩𮈪𮈫𮈬𮈭𮈮𮈯𮈰𮈱𮈲𮈳𮈴𮈵𮈶𮈷𮈸𮈹𮈺𮈻𮈼𮈽𮈾𮈿𮉀𮉁𮉂𮉃𮉄𮉅𮉆𮉇𮉈𮉉𮉊𮉋𮉌𮉍𮉎𮉏𮉐𮉑𮉒𮉓𮉔𮉕𮉖𮉗𮉘𮉙𮉚𮉛𮉜𮉝𮉞𮉟𮉠𮉡𮉢𮉣𮉤𮉥𮉦𮉧𮉨𮉩𮉪𮉫𮉬𮉭𮉮𮉯𮉰𮉱𮉲𮉳𮉴𮉵𮉶𮉷𮉸𮉹𮉺𮉻𮉼𮉽𮉾𮉿𮊀𮊁𮊂𮊃𮊄𮊅𮊆𮊇𮊈𮊉𮊊𮊋𮊌𮊍𮊎𮊏𮊐𮊑𮊒𮊓𮊔𮊕𮊖𮊗𮊘𮊙𮊚𮊛𮊜𮊝𮊞𮊟𮊠𮊡𮊢𮊣𮊤𮊥𮊦𮊧𮊨𮊩𮊪𮊫𮊬𮊭𮊮𮊯𮊰𮊱𮊲𮊳𮊴𮊵𮊶𮊷𮊸𮊹𮊺𮊻𮊼𮊽𮊾𮊿𮋀𮋁𮋂𮋃𮋄𮋅𮋆𮋇𮋈𮋉𮋊𮋋𮋌𮋍𮋎𮋏𮋐𮋑𮋒𮋓𮋔𮋕𮋖𮋗𮋘𮋙𮋚𮋛𮋜𮋝𮋞𮋟𮋠𮋡𮋢𮋣𮋤𮋥𮋦𮋧𮋨𮋩𮋪𮋫𮋬𮋭𮋮𮋯𮋰𮋱𮋲𮋳𮋴𮋵𮋶𮋷𮋸𮋹𮋺𮋻𮋼𮋽𮋾𮋿𮌀𮌁𮌂𮌃𮌄𮌅𮌆𮌇𮌈𮌉𮌊𮌋𮌌𮌍𮌎𮌏𮌐𮌑𮌒𮌓𮌔𮌕𮌖𮌗𮌘𮌙𮌚𮌛𮌜𮌝𮌞𮌟𮌠𮌡𮌢𮌣𮌤𮌥𮌦𮌧𮌨𮌩𮌪𮌫𮌬𮌭𮌮𮌯𮌰𮌱𮌲𮌳𮌴𮌵𮌶𮌷𮌸𮌹𮌺𮌻𮌼𮌽𮌾𮌿𮍀𮍁𮍂𮍃𮍄𮍅𮍆𮍇𮍈𮍉𮍊𮍋𮍌𮍍𮍎𮍏𮍐𮍑𮍒𮍓𮍔𮍕𮍖𮍗𮍘𮍙𮍚𮍛𮍜𮍝𮍞𮍟𮍠𮍡𮍢𮍣𮍤𮍥𮍦𮍧𮍨𮍩𮍪𮍫𮍬𮍭𮍮𮍯𮍰𮍱𮍲𮍳𮍴𮍵𮍶𮍷𮍸𮍹𮍺𮍻𮍼𮍽𮍾𮍿𮎀𮎁𮎂𮎃𮎄𮎅𮎆𮎇𮎈𮎉𮎊𮎋𮎌𮎍𮎎𮎏𮎐𮎑𮎒𮎓𮎔𮎕𮎖𮎗𮎘𮎙𮎚𮎛𮎜𮎝𮎞𮎟𮎠𮎡𮎢𮎣𮎤𮎥𮎦𮎧𮎨𮎩𮎪𮎫𮎬𮎭𮎮𮎯𮎰𮎱𮎲𮎳𮎴𮎵𮎶𮎷𮎸𮎹𮎺𮎻𮎼𮎽𮎾𮎿𮏀𮏁𮏂𮏃𮏄𮏅𮏆𮏇𮏈𮏉𮏊𮏋𮏌𮏍𮏎𮏏𮏐𮏑𮏒𮏓𮏔𮏕𮏖𮏗𮏘𮏙𮏚𮏛𮏜𮏝𮏞𮏟𮏠𮏡𮏢𮏣𮏤𮏥𮏦𮏧𮏨𮏩𮏪𮏫𮏬𮏭𮏮𮏯𮏰𮏱𮏲𮏳𮏴𮏵𮏶𮏷𮏸𮏹𮏺𮏻𮏼𮏽𮏾𮏿𮐀𮐁𮐂𮐃𮐄𮐅𮐆𮐇𮐈𮐉𮐊𮐋𮐌𮐍𮐎𮐏𮐐𮐑𮐒𮐓𮐔𮐕𮐖𮐗𮐘𮐙𮐚𮐛𮐜𮐝𮐞𮐟𮐠𮐡𮐢𮐣𮐤𮐥𮐦𮐧𮐨𮐩𮐪𮐫𮐬𮐭𮐮𮐯𮐰𮐱𮐲𮐳𮐴𮐵𮐶𮐷𮐸𮐹𮐺𮐻𮐼𮐽𮐾𮐿𮑀𮑁𮑂𮑃𮑄𮑅𮑆𮑇𮑈𮑉𮑊𮑋𮑌𮑍𮑎𮑏𮑐𮑑𮑒𮑓𮑔𮑕𮑖𮑗𮑘𮑙𮑚𮑛𮑜𮑝𮑞𮑟𮑠𮑡𮑢𮑣𮑤𮑥𮑦𮑧𮑨𮑩𮑪𮑫𮑬𮑭𮑮𮑯𮑰𮑱𮑲𮑳𮑴𮑵𮑶𮑷𮑸𮑹𮑺𮑻𮑼𮑽𮑾𮑿𮒀𮒁𮒂𮒃𮒄𮒅𮒆𮒇𮒈𮒉𮒊𮒋𮒌𮒍𮒎𮒏𮒐𮒑𮒒𮒓𮒔𮒕𮒖𮒗𮒘𮒙𮒚𮒛𮒜𮒝𮒞𮒟𮒠𮒡𮒢𮒣𮒤𮒥𮒦𮒧𮒨𮒩𮒪𮒫𮒬𮒭𮒮𮒯𮒰𮒱𮒲𮒳𮒴𮒵𮒶𮒷𮒸𮒹𮒺𮒻𮒼𮒽𮒾𮒿𮓀𮓁𮓂𮓃𮓄𮓅𮓆𮓇𮓈𮓉𮓊𮓋𮓌𮓍𮓎𮓏𮓐𮓑𮓒𮓓𮓔𮓕𮓖𮓗𮓘𮓙𮓚𮓛𮓜𮓝𮓞𮓟𮓠𮓡𮓢𮓣𮓤𮓥𮓦𮓧𮓨𮓩𮓪𮓫𮓬𮓭𮓮𮓯𮓰𮓱𮓲𮓳𮓴𮓵𮓶𮓷𮓸𮓹𮓺𮓻𮓼𮓽𮓾𮓿𮔀𮔁𮔂𮔃𮔄𮔅𮔆𮔇𮔈𮔉𮔊𮔋𮔌𮔍𮔎𮔏𮔐𮔑𮔒𮔓𮔔𮔕𮔖𮔗𮔘𮔙𮔚𮔛𮔜𮔝𮔞𮔟𮔠𮔡𮔢𮔣𮔤𮔥𮔦𮔧𮔨𮔩𮔪𮔫𮔬𮔭𮔮𮔯𮔰𮔱𮔲𮔳𮔴𮔵𮔶𮔷𮔸𮔹𮔺𮔻𮔼𮔽𮔾𮔿𮕀𮕁𮕂𮕃𮕄𮕅𮕆𮕇𮕈𮕉𮕊𮕋𮕌𮕍𮕎𮕏𮕐𮕑𮕒𮕓𮕔𮕕𮕖𮕗𮕘𮕙𮕚𮕛𮕜𮕝𮕞𮕟𮕠𮕡𮕢𮕣𮕤𮕥𮕦𮕧𮕨𮕩𮕪𮕫𮕬𮕭𮕮𮕯𮕰𮕱𮕲𮕳𮕴𮕵𮕶𮕷𮕸𮕹𮕺𮕻𮕼𮕽𮕾𮕿𮖀𮖁𮖂𮖃𮖄𮖅𮖆𮖇𮖈𮖉𮖊𮖋𮖌𮖍𮖎𮖏𮖐𮖑𮖒𮖓𮖔𮖕𮖖𮖗𮖘𮖙𮖚𮖛𮖜𮖝𮖞𮖟𮖠𮖡𮖢𮖣𮖤𮖥𮖦𮖧𮖨𮖩𮖪𮖫𮖬𮖭𮖮𮖯𮖰𮖱𮖲𮖳𮖴𮖵𮖶𮖷𮖸𮖹𮖺𮖻𮖼𮖽𮖾𮖿𮗀𮗁𮗂𮗃𮗄𮗅𮗆𮗇𮗈𮗉𮗊𮗋𮗌𮗍𮗎𮗏𮗐𮗑𮗒𮗓𮗔𮗕𮗖𮗗𮗘𮗙𮗚𮗛𮗜𮗝𮗞𮗟𮗠𮗡𮗢𮗣𮗤𮗥𮗦𮗧𮗨𮗩𮗪𮗫𮗬𮗭𮗮𮗯𮗰𮗱𮗲𮗳𮗴𮗵𮗶𮗷𮗸𮗹𮗺𮗻𮗼𮗽𮗾𮗿𮘀𮘁𮘂𮘃𮘄𮘅𮘆𮘇𮘈𮘉𮘊𮘋𮘌𮘍𮘎𮘏𮘐𮘑𮘒𮘓𮘔𮘕𮘖𮘗𮘘𮘙𮘚𮘛𮘜𮘝𮘞𮘟𮘠𮘡𮘢𮘣𮘤𮘥𮘦𮘧𮘨𮘩𮘪𮘫𮘬𮘭𮘮𮘯𮘰𮘱𮘲𮘳𮘴𮘵𮘶𮘷𮘸𮘹𮘺𮘻𮘼𮘽𮘾𮘿𮙀𮙁𮙂𮙃𮙄𮙅𮙆𮙇𮙈𮙉𮙊𮙋𮙌𮙍𮙎𮙏𮙐𮙑𮙒𮙓𮙔𮙕𮙖𮙗𮙘𮙙𮙚𮙛𮙜𮙝𮙞𮙟𮙠𮙡𮙢𮙣𮙤𮙥𮙦𮙧𮙨𮙩𮙪𮙫𮙬𮙭𮙮𮙯𮙰𮙱𮙲𮙳𮙴𮙵𮙶𮙷𮙸𮙹𮙺𮙻𮙼𮙽𮙾𮙿𮚀𮚁𮚂𮚃𮚄𮚅𮚆𮚇𮚈𮚉𮚊𮚋𮚌𮚍𮚎𮚏𮚐𮚑𮚒𮚓𮚔𮚕𮚖𮚗𮚘𮚙𮚚𮚛𮚜𮚝𮚞𮚟𮚠𮚡𮚢𮚣𮚤𮚥𮚦𮚧𮚨𮚩𮚪𮚫𮚬𮚭𮚮𮚯𮚰𮚱𮚲𮚳𮚴𮚵𮚶𮚷𮚸𮚹𮚺𮚻𮚼𮚽𮚾𮚿𮛀𮛁𮛂𮛃𮛄𮛅𮛆𮛇𮛈𮛉𮛊𮛋𮛌𮛍𮛎𮛏𮛐𮛑𮛒𮛓𮛔𮛕𮛖𮛗𮛘𮛙𮛚𮛛𮛜𮛝𮛞𮛟𮛠𮛡𮛢𮛣𮛤𮛥𮛦𮛧𮛨𮛩𮛪𮛫𮛬𮛭𮛮𮛯𮛰𮛱𮛲𮛳𮛴𮛵𮛶𮛷𮛸𮛹𮛺𮛻𮛼𮛽𮛾𮛿𮜀𮜁𮜂𮜃𮜄𮜅𮜆𮜇𮜈𮜉𮜊𮜋𮜌𮜍𮜎𮜏𮜐𮜑𮜒𮜓𮜔𮜕𮜖𮜗𮜘𮜙𮜚𮜛𮜜𮜝𮜞𮜟𮜠𮜡𮜢𮜣𮜤𮜥𮜦𮜧𮜨𮜩𮜪𮜫𮜬𮜭𮜮𮜯𮜰𮜱𮜲𮜳𮜴𮜵𮜶𮜷𮜸𮜹𮜺𮜻𮜼𮜽𮜾𮜿𮝀𮝁𮝂𮝃𮝄𮝅𮝆𮝇𮝈𮝉𮝊𮝋𮝌𮝍𮝎𮝏𮝐𮝑𮝒𮝓𮝔𮝕𮝖𮝗𮝘𮝙𮝚𮝛𮝜𮝝𮝞𮝟𮝠𮝡𮝢𮝣𮝤𮝥𮝦𮝧𮝨𮝩𮝪𮝫𮝬𮝭𮝮𮝯𮝰𮝱𮝲𮝳𮝴𮝵𮝶𮝷𮝸𮝹𮝺𮝻𮝼𮝽𮝾𮝿𮞀𮞁𮞂𮞃𮞄𮞅𮞆𮞇𮞈𮞉𮞊𮞋𮞌𮞍𮞎𮞏𮞐𮞑𮞒𮞓𮞔𮞕𮞖𮞗𮞘𮞙𮞚𮞛𮞜𮞝𮞞𮞟𮞠𮞡𮞢𮞣𮞤𮞥𮞦𮞧𮞨𮞩𮞪𮞫𮞬𮞭𮞮𮞯𮞰𮞱𮞲𮞳𮞴𮞵𮞶𮞷𮞸𮞹𮞺𮞻𮞼𮞽𮞾𮞿𮟀𮟁𮟂𮟃𮟄𮟅𮟆𮟇𮟈𮟉𮟊𮟋𮟌𮟍𮟎𮟏𮟐𮟑𮟒𮟓𮟔𮟕𮟖𮟗𮟘𮟙𮟚𮟛𮟜𮟝𮟞𮟟𮟠𮟡𮟢𮟣𮟤𮟥𮟦𮟧𮟨𮟩𮟪𮟫𮟬𮟭𮟮𮟯𮟰𮟱𮟲𮟳𮟴𮟵𮟶𮟷𮟸𮟹𮟺𮟻𮟼𮟽𮟾𮟿𮠀𮠁𮠂𮠃𮠄𮠅𮠆𮠇𮠈𮠉𮠊𮠋𮠌𮠍𮠎𮠏𮠐𮠑𮠒𮠓𮠔𮠕𮠖𮠗𮠘𮠙𮠚𮠛𮠜𮠝𮠞𮠟𮠠𮠡𮠢𮠣𮠤𮠥𮠦𮠧𮠨𮠩𮠪𮠫𮠬𮠭𮠮𮠯𮠰𮠱𮠲𮠳𮠴𮠵𮠶𮠷𮠸𮠹𮠺𮠻𮠼𮠽𮠾𮠿𮡀𮡁𮡂𮡃𮡄𮡅𮡆𮡇𮡈𮡉𮡊𮡋𮡌𮡍𮡎𮡏𮡐𮡑𮡒𮡓𮡔𮡕𮡖𮡗𮡘𮡙𮡚𮡛𮡜𮡝𮡞𮡟𮡠𮡡𮡢𮡣𮡤𮡥𮡦𮡧𮡨𮡩𮡪𮡫𮡬𮡭𮡮𮡯𮡰𮡱𮡲𮡳𮡴𮡵𮡶𮡷𮡸𮡹𮡺𮡻𮡼𮡽𮡾𮡿𮢀𮢁𮢂𮢃𮢄𮢅𮢆𮢇𮢈𮢉𮢊𮢋𮢌𮢍𮢎𮢏𮢐𮢑𮢒𮢓𮢔𮢕𮢖𮢗𮢘𮢙𮢚𮢛𮢜𮢝𮢞𮢟𮢠𮢡𮢢𮢣𮢤𮢥𮢦𮢧𮢨𮢩𮢪𮢫𮢬𮢭𮢮𮢯𮢰𮢱𮢲𮢳𮢴𮢵𮢶𮢷𮢸𮢹𮢺𮢻𮢼𮢽𮢾𮢿𮣀𮣁𮣂𮣃𮣄𮣅𮣆𮣇𮣈𮣉𮣊𮣋𮣌𮣍𮣎𮣏𮣐𮣑𮣒𮣓𮣔𮣕𮣖𮣗𮣘𮣙𮣚𮣛𮣜𮣝𮣞𮣟𮣠𮣡𮣢𮣣𮣤𮣥𮣦𮣧𮣨𮣩𮣪𮣫𮣬𮣭𮣮𮣯𮣰𮣱𮣲𮣳𮣴𮣵𮣶𮣷𮣸𮣹𮣺𮣻𮣼𮣽𮣾𮣿𮤀𮤁𮤂𮤃𮤄𮤅𮤆𮤇𮤈𮤉𮤊𮤋𮤌𮤍𮤎𮤏𮤐𮤑𮤒𮤓𮤔𮤕𮤖𮤗𮤘𮤙𮤚𮤛𮤜𮤝𮤞𮤟𮤠𮤡𮤢𮤣𮤤𮤥𮤦𮤧𮤨𮤩𮤪𮤫𮤬𮤭𮤮𮤯𮤰𮤱𮤲𮤳𮤴𮤵𮤶𮤷𮤸𮤹𮤺𮤻𮤼𮤽𮤾𮤿𮥀𮥁𮥂𮥃𮥄𮥅𮥆𮥇𮥈𮥉𮥊𮥋𮥌𮥍𮥎𮥏𮥐𮥑𮥒𮥓𮥔𮥕𮥖𮥗𮥘𮥙𮥚𮥛𮥜𮥝𮥞𮥟𮥠𮥡𮥢𮥣𮥤𮥥𮥦𮥧𮥨𮥩𮥪𮥫𮥬𮥭𮥮𮥯𮥰𮥱𮥲𮥳𮥴𮥵𮥶𮥷𮥸𮥹𮥺𮥻𮥼𮥽𮥾𮥿𮦀𮦁𮦂𮦃𮦄𮦅𮦆𮦇𮦈𮦉𮦊𮦋𮦌𮦍𮦎𮦏𮦐𮦑𮦒𮦓𮦔𮦕𮦖𮦗𮦘𮦙𮦚𮦛𮦜𮦝𮦞𮦟𮦠𮦡𮦢𮦣𮦤𮦥𮦦𮦧𮦨𮦩𮦪𮦫𮦬𮦭𮦮𮦯𮦰𮦱𮦲𮦳𮦴𮦵𮦶𮦷𮦸𮦹𮦺𮦻𮦼𮦽𮦾𮦿𮧀𮧁𮧂𮧃𮧄𮧅𮧆𮧇𮧈𮧉𮧊𮧋𮧌𮧍𮧎𮧏𮧐𮧑𮧒𮧓𮧔𮧕𮧖𮧗𮧘𮧙𮧚𮧛𮧜𮧝𮧞𮧟𮧠𮧡𮧢𮧣𮧤𮧥𮧦𮧧𮧨𮧩𮧪𮧫𮧬𮧭𮧮𮧯𮧰𮧱𮧲𮧳𮧴𮧵𮧶𮧷𮧸𮧹𮧺𮧻𮧼𮧽𮧾𮧿𮨀𮨁𮨂𮨃𮨄𮨅𮨆𮨇𮨈𮨉𮨊𮨋𮨌𮨍𮨎𮨏𮨐𮨑𮨒𮨓𮨔𮨕𮨖𮨗𮨘𮨙𮨚𮨛𮨜𮨝𮨞𮨟𮨠𮨡𮨢𮨣𮨤𮨥𮨦𮨧𮨨𮨩𮨪𮨫𮨬𮨭𮨮𮨯𮨰𮨱𮨲𮨳𮨴𮨵𮨶𮨷𮨸𮨹𮨺𮨻𮨼𮨽𮨾𮨿𮩀𮩁𮩂𮩃𮩄𮩅𮩆𮩇𮩈𮩉𮩊𮩋𮩌𮩍𮩎𮩏𮩐𮩑𮩒𮩓𮩔𮩕𮩖𮩗𮩘𮩙𮩚𮩛𮩜𮩝𮩞𮩟𮩠𮩡𮩢𮩣𮩤𮩥𮩦𮩧𮩨𮩩𮩪𮩫𮩬𮩭𮩮𮩯𮩰𮩱𮩲𮩳𮩴𮩵𮩶𮩷𮩸𮩹𮩺𮩻𮩼𮩽𮩾𮩿𮪀𮪁𮪂𮪃𮪄𮪅𮪆𮪇𮪈𮪉𮪊𮪋𮪌𮪍𮪎𮪏𮪐𮪑𮪒𮪓𮪔𮪕𮪖𮪗𮪘𮪙𮪚𮪛𮪜𮪝𮪞𮪟𮪠𮪡𮪢𮪣𮪤𮪥𮪦𮪧𮪨𮪩𮪪𮪫𮪬𮪭𮪮𮪯𮪰𮪱𮪲𮪳𮪴𮪵𮪶𮪷𮪸𮪹𮪺𮪻𮪼𮪽𮪾𮪿𮫀𮫁𮫂𮫃𮫄𮫅𮫆𮫇𮫈𮫉𮫊𮫋𮫌𮫍𮫎𮫏𮫐𮫑𮫒𮫓𮫔𮫕𮫖𮫗𮫘𮫙𮫚𮫛𮫜𮫝𮫞𮫟𮫠𮫡𮫢𮫣𮫤𮫥𮫦𮫧𮫨𮫩𮫪𮫫𮫬𮫭𮫮𮫯𮫰𮫱𮫲𮫳𮫴𮫵𮫶𮫷𮫸𮫹𮫺𮫻𮫼𮫽𮫾𮫿𮬀𮬁𮬂𮬃𮬄𮬅𮬆𮬇𮬈𮬉𮬊𮬋𮬌𮬍𮬎𮬏𮬐𮬑𮬒𮬓𮬔𮬕𮬖𮬗𮬘𮬙𮬚𮬛𮬜𮬝𮬞𮬟𮬠𮬡𮬢𮬣𮬤𮬥𮬦𮬧𮬨𮬩𮬪𮬫𮬬𮬭𮬮𮬯𮬰𮬱𮬲𮬳𮬴𮬵𮬶𮬷𮬸𮬹𮬺𮬻𮬼𮬽𮬾𮬿𮭀𮭁𮭂𮭃𮭄𮭅𮭆𮭇𮭈𮭉𮭊𮭋𮭌𮭍𮭎𮭏𮭐𮭑𮭒𮭓𮭔𮭕𮭖𮭗𮭘𮭙𮭚𮭛𮭜𮭝𮭞𮭟𮭠𮭡𮭢𮭣𮭤𮭥𮭦𮭧𮭨𮭩𮭪𮭫𮭬𮭭𮭮𮭯𮭰𮭱𮭲𮭳𮭴𮭵𮭶𮭷𮭸𮭹𮭺𮭻𮭼𮭽𮭾𮭿𮮀𮮁𮮂𮮃𮮄𮮅𮮆𮮇𮮈𮮉𮮊𮮋𮮌𮮍𮮎𮮏𮮐𮮑𮮒𮮓𮮔𮮕𮮖𮮗𮮘𮮙𮮚𮮛𮮜𮮝𮮞𮮟𮮠𮮡𮮢𮮣𮮤𮮥𮮦𮮧𮮨𮮩𮮪𮮫𮮬𮮭𮮮𮮯𮮰𮮱𮮲𮮳𮮴𮮵𮮶𮮷𮮸𮮹𮮺𮮻𮮼𮮽𮮾𮮿𮯀𮯁𮯂𮯃𮯄𮯅𮯆𮯇𮯈𮯉𮯊𮯋𮯌𮯍𮯎𮯏𮯐𮯑𮯒𮯓𮯔𮯕𮯖𮯗𮯘𮯙𮯚𮯛𮯜𮯝𮯞𮯟𮯠; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-escaped.js index 4f1852e61d7f..c14c0e65907b 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-10.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-10.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-10.0.0.js index a676f60f7f4f..b7b987dca1ea 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-10.0.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-10.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-class-escaped.js new file mode 100644 index 000000000000..14088e0290bd --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v11.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u0560\u0588\u05EF\u1878\u1C90\u1C91\u1C92\u1C93\u1C94\u1C95\u1C96\u1C97\u1C98\u1C99\u1C9A\u1C9B\u1C9C\u1C9D\u1C9E\u1C9F\u1CA0\u1CA1\u1CA2\u1CA3\u1CA4\u1CA5\u1CA6\u1CA7\u1CA8\u1CA9\u1CAA\u1CAB\u1CAC\u1CAD\u1CAE\u1CAF\u1CB0\u1CB1\u1CB2\u1CB3\u1CB4\u1CB5\u1CB6\u1CB7\u1CB8\u1CB9\u1CBA\u1CBD\u1CBE\u1CBF\u312F\u9FEB\u9FEC\u9FED\u9FEE\u9FEF\uA7AF\uA7B8\uA7B9\uA8FE\u{10A34}\u{10A35}\u{10D00}\u{10D01}\u{10D02}\u{10D03}\u{10D04}\u{10D05}\u{10D06}\u{10D07}\u{10D08}\u{10D09}\u{10D0A}\u{10D0B}\u{10D0C}\u{10D0D}\u{10D0E}\u{10D0F}\u{10D10}\u{10D11}\u{10D12}\u{10D13}\u{10D14}\u{10D15}\u{10D16}\u{10D17}\u{10D18}\u{10D19}\u{10D1A}\u{10D1B}\u{10D1C}\u{10D1D}\u{10D1E}\u{10D1F}\u{10D20}\u{10D21}\u{10D22}\u{10D23}\u{10F00}\u{10F01}\u{10F02}\u{10F03}\u{10F04}\u{10F05}\u{10F06}\u{10F07}\u{10F08}\u{10F09}\u{10F0A}\u{10F0B}\u{10F0C}\u{10F0D}\u{10F0E}\u{10F0F}\u{10F10}\u{10F11}\u{10F12}\u{10F13}\u{10F14}\u{10F15}\u{10F16}\u{10F17}\u{10F18}\u{10F19}\u{10F1A}\u{10F1B}\u{10F1C}\u{10F27}\u{10F30}\u{10F31}\u{10F32}\u{10F33}\u{10F34}\u{10F35}\u{10F36}\u{10F37}\u{10F38}\u{10F39}\u{10F3A}\u{10F3B}\u{10F3C}\u{10F3D}\u{10F3E}\u{10F3F}\u{10F40}\u{10F41}\u{10F42}\u{10F43}\u{10F44}\u{10F45}\u{11144}\u{1171A}\u{11800}\u{11801}\u{11802}\u{11803}\u{11804}\u{11805}\u{11806}\u{11807}\u{11808}\u{11809}\u{1180A}\u{1180B}\u{1180C}\u{1180D}\u{1180E}\u{1180F}\u{11810}\u{11811}\u{11812}\u{11813}\u{11814}\u{11815}\u{11816}\u{11817}\u{11818}\u{11819}\u{1181A}\u{1181B}\u{1181C}\u{1181D}\u{1181E}\u{1181F}\u{11820}\u{11821}\u{11822}\u{11823}\u{11824}\u{11825}\u{11826}\u{11827}\u{11828}\u{11829}\u{1182A}\u{1182B}\u{11A9D}\u{11D60}\u{11D61}\u{11D62}\u{11D63}\u{11D64}\u{11D65}\u{11D67}\u{11D68}\u{11D6A}\u{11D6B}\u{11D6C}\u{11D6D}\u{11D6E}\u{11D6F}\u{11D70}\u{11D71}\u{11D72}\u{11D73}\u{11D74}\u{11D75}\u{11D76}\u{11D77}\u{11D78}\u{11D79}\u{11D7A}\u{11D7B}\u{11D7C}\u{11D7D}\u{11D7E}\u{11D7F}\u{11D80}\u{11D81}\u{11D82}\u{11D83}\u{11D84}\u{11D85}\u{11D86}\u{11D87}\u{11D88}\u{11D89}\u{11D98}\u{11EE0}\u{11EE1}\u{11EE2}\u{11EE3}\u{11EE4}\u{11EE5}\u{11EE6}\u{11EE7}\u{11EE8}\u{11EE9}\u{11EEA}\u{11EEB}\u{11EEC}\u{11EED}\u{11EEE}\u{11EEF}\u{11EF0}\u{11EF1}\u{11EF2}\u{16E40}\u{16E41}\u{16E42}\u{16E43}\u{16E44}\u{16E45}\u{16E46}\u{16E47}\u{16E48}\u{16E49}\u{16E4A}\u{16E4B}\u{16E4C}\u{16E4D}\u{16E4E}\u{16E4F}\u{16E50}\u{16E51}\u{16E52}\u{16E53}\u{16E54}\u{16E55}\u{16E56}\u{16E57}\u{16E58}\u{16E59}\u{16E5A}\u{16E5B}\u{16E5C}\u{16E5D}\u{16E5E}\u{16E5F}\u{16E60}\u{16E61}\u{16E62}\u{16E63}\u{16E64}\u{16E65}\u{16E66}\u{16E67}\u{16E68}\u{16E69}\u{16E6A}\u{16E6B}\u{16E6C}\u{16E6D}\u{16E6E}\u{16E6F}\u{16E70}\u{16E71}\u{16E72}\u{16E73}\u{16E74}\u{16E75}\u{16E76}\u{16E77}\u{16E78}\u{16E79}\u{16E7A}\u{16E7B}\u{16E7C}\u{16E7D}\u{16E7E}\u{16E7F}\u{187ED}\u{187EE}\u{187EF}\u{187F0}\u{187F1}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-class.js new file mode 100644 index 000000000000..16d114032d6f --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v11.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ՠֈׯᡸᲐᲑᲒᲓᲔᲕᲖᲗᲘᲙᲚᲛᲜᲝᲞᲟᲠᲡᲢᲣᲤᲥᲦᲧᲨᲩᲪᲫᲬᲭᲮᲯᲰᲱᲲᲳᲴᲵᲶᲷᲸᲹᲺᲽᲾᲿㄯ鿫鿬鿭鿮鿯ꞯꞸꞹꣾ𐨴𐨵𐴀𐴁𐴂𐴃𐴄𐴅𐴆𐴇𐴈𐴉𐴊𐴋𐴌𐴍𐴎𐴏𐴐𐴑𐴒𐴓𐴔𐴕𐴖𐴗𐴘𐴙𐴚𐴛𐴜𐴝𐴞𐴟𐴠𐴡𐴢𐴣𐼀𐼁𐼂𐼃𐼄𐼅𐼆𐼇𐼈𐼉𐼊𐼋𐼌𐼍𐼎𐼏𐼐𐼑𐼒𐼓𐼔𐼕𐼖𐼗𐼘𐼙𐼚𐼛𐼜𐼧𐼰𐼱𐼲𐼳𐼴𐼵𐼶𐼷𐼸𐼹𐼺𐼻𐼼𐼽𐼾𐼿𐽀𐽁𐽂𐽃𐽄𐽅𑅄𑜚𑠀𑠁𑠂𑠃𑠄𑠅𑠆𑠇𑠈𑠉𑠊𑠋𑠌𑠍𑠎𑠏𑠐𑠑𑠒𑠓𑠔𑠕𑠖𑠗𑠘𑠙𑠚𑠛𑠜𑠝𑠞𑠟𑠠𑠡𑠢𑠣𑠤𑠥𑠦𑠧𑠨𑠩𑠪𑠫𑪝𑵠𑵡𑵢𑵣𑵤𑵥𑵧𑵨𑵪𑵫𑵬𑵭𑵮𑵯𑵰𑵱𑵲𑵳𑵴𑵵𑵶𑵷𑵸𑵹𑵺𑵻𑵼𑵽𑵾𑵿𑶀𑶁𑶂𑶃𑶄𑶅𑶆𑶇𑶈𑶉𑶘𑻠𑻡𑻢𑻣𑻤𑻥𑻦𑻧𑻨𑻩𑻪𑻫𑻬𑻭𑻮𑻯𑻰𑻱𑻲𖹀𖹁𖹂𖹃𖹄𖹅𖹆𖹇𖹈𖹉𖹊𖹋𖹌𖹍𖹎𖹏𖹐𖹑𖹒𖹓𖹔𖹕𖹖𖹗𖹘𖹙𖹚𖹛𖹜𖹝𖹞𖹟𖹠𖹡𖹢𖹣𖹤𖹥𖹦𖹧𖹨𖹩𖹪𖹫𖹬𖹭𖹮𖹯𖹰𖹱𖹲𖹳𖹴𖹵𖹶𖹷𖹸𖹹𖹺𖹻𖹼𖹽𖹾𖹿𘟭𘟮𘟯𘟰𘟱; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-escaped.js index bf781b429275..738a58982b0d 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-11.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-11.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-11.0.0.js index 89d312f75f12..f386d376b3c8 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-11.0.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-11.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-class-escaped.js new file mode 100644 index 000000000000..6bf9bf136d33 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v12.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u0E86\u0E89\u0E8C\u0E8E\u0E8F\u0E90\u0E91\u0E92\u0E93\u0E98\u0EA0\u0EA8\u0EA9\u0EAC\u1CF2\u1CF3\u1CFA\uA7BA\uA7BB\uA7BC\uA7BD\uA7BE\uA7BF\uA7C2\uA7C3\uA7C4\uA7C5\uA7C6\uAB66\uAB67\u{10FE0}\u{10FE1}\u{10FE2}\u{10FE3}\u{10FE4}\u{10FE5}\u{10FE6}\u{10FE7}\u{10FE8}\u{10FE9}\u{10FEA}\u{10FEB}\u{10FEC}\u{10FED}\u{10FEE}\u{10FEF}\u{10FF0}\u{10FF1}\u{10FF2}\u{10FF3}\u{10FF4}\u{10FF5}\u{10FF6}\u{1145F}\u{116B8}\u{119A0}\u{119A1}\u{119A2}\u{119A3}\u{119A4}\u{119A5}\u{119A6}\u{119A7}\u{119AA}\u{119AB}\u{119AC}\u{119AD}\u{119AE}\u{119AF}\u{119B0}\u{119B1}\u{119B2}\u{119B3}\u{119B4}\u{119B5}\u{119B6}\u{119B7}\u{119B8}\u{119B9}\u{119BA}\u{119BB}\u{119BC}\u{119BD}\u{119BE}\u{119BF}\u{119C0}\u{119C1}\u{119C2}\u{119C3}\u{119C4}\u{119C5}\u{119C6}\u{119C7}\u{119C8}\u{119C9}\u{119CA}\u{119CB}\u{119CC}\u{119CD}\u{119CE}\u{119CF}\u{119D0}\u{119E1}\u{119E3}\u{11A84}\u{11A85}\u{16F45}\u{16F46}\u{16F47}\u{16F48}\u{16F49}\u{16F4A}\u{16FE3}\u{187F2}\u{187F3}\u{187F4}\u{187F5}\u{187F6}\u{187F7}\u{1B150}\u{1B151}\u{1B152}\u{1B164}\u{1B165}\u{1B166}\u{1B167}\u{1E100}\u{1E101}\u{1E102}\u{1E103}\u{1E104}\u{1E105}\u{1E106}\u{1E107}\u{1E108}\u{1E109}\u{1E10A}\u{1E10B}\u{1E10C}\u{1E10D}\u{1E10E}\u{1E10F}\u{1E110}\u{1E111}\u{1E112}\u{1E113}\u{1E114}\u{1E115}\u{1E116}\u{1E117}\u{1E118}\u{1E119}\u{1E11A}\u{1E11B}\u{1E11C}\u{1E11D}\u{1E11E}\u{1E11F}\u{1E120}\u{1E121}\u{1E122}\u{1E123}\u{1E124}\u{1E125}\u{1E126}\u{1E127}\u{1E128}\u{1E129}\u{1E12A}\u{1E12B}\u{1E12C}\u{1E137}\u{1E138}\u{1E139}\u{1E13A}\u{1E13B}\u{1E13C}\u{1E13D}\u{1E14E}\u{1E2C0}\u{1E2C1}\u{1E2C2}\u{1E2C3}\u{1E2C4}\u{1E2C5}\u{1E2C6}\u{1E2C7}\u{1E2C8}\u{1E2C9}\u{1E2CA}\u{1E2CB}\u{1E2CC}\u{1E2CD}\u{1E2CE}\u{1E2CF}\u{1E2D0}\u{1E2D1}\u{1E2D2}\u{1E2D3}\u{1E2D4}\u{1E2D5}\u{1E2D6}\u{1E2D7}\u{1E2D8}\u{1E2D9}\u{1E2DA}\u{1E2DB}\u{1E2DC}\u{1E2DD}\u{1E2DE}\u{1E2DF}\u{1E2E0}\u{1E2E1}\u{1E2E2}\u{1E2E3}\u{1E2E4}\u{1E2E5}\u{1E2E6}\u{1E2E7}\u{1E2E8}\u{1E2E9}\u{1E2EA}\u{1E2EB}\u{1E94B}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-class.js new file mode 100644 index 000000000000..76cc962523c3 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v12.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ຆຉຌຎຏຐຑຒຓຘຠຨຩຬᳲᳳᳺꞺꞻꞼꞽꞾꞿꟂꟃꟄꟅꟆꭦꭧ𐿠𐿡𐿢𐿣𐿤𐿥𐿦𐿧𐿨𐿩𐿪𐿫𐿬𐿭𐿮𐿯𐿰𐿱𐿲𐿳𐿴𐿵𐿶𑑟𑚸𑦠𑦡𑦢𑦣𑦤𑦥𑦦𑦧𑦪𑦫𑦬𑦭𑦮𑦯𑦰𑦱𑦲𑦳𑦴𑦵𑦶𑦷𑦸𑦹𑦺𑦻𑦼𑦽𑦾𑦿𑧀𑧁𑧂𑧃𑧄𑧅𑧆𑧇𑧈𑧉𑧊𑧋𑧌𑧍𑧎𑧏𑧐𑧡𑧣𑪄𑪅𖽅𖽆𖽇𖽈𖽉𖽊𖿣𘟲𘟳𘟴𘟵𘟶𘟷𛅐𛅑𛅒𛅤𛅥𛅦𛅧𞄀𞄁𞄂𞄃𞄄𞄅𞄆𞄇𞄈𞄉𞄊𞄋𞄌𞄍𞄎𞄏𞄐𞄑𞄒𞄓𞄔𞄕𞄖𞄗𞄘𞄙𞄚𞄛𞄜𞄝𞄞𞄟𞄠𞄡𞄢𞄣𞄤𞄥𞄦𞄧𞄨𞄩𞄪𞄫𞄬𞄷𞄸𞄹𞄺𞄻𞄼𞄽𞅎𞋀𞋁𞋂𞋃𞋄𞋅𞋆𞋇𞋈𞋉𞋊𞋋𞋌𞋍𞋎𞋏𞋐𞋑𞋒𞋓𞋔𞋕𞋖𞋗𞋘𞋙𞋚𞋛𞋜𞋝𞋞𞋟𞋠𞋡𞋢𞋣𞋤𞋥𞋦𞋧𞋨𞋩𞋪𞋫𞥋; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-escaped.js index f0dd87ef5d63..0a5fb9aa5ca7 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-12.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-12.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-12.0.0.js index c013dc850ee3..14a325796f10 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-12.0.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-12.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-class-escaped.js new file mode 100644 index 000000000000..7d85b8257d92 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v13.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u08BE\u08BF\u08C0\u08C1\u08C2\u08C3\u08C4\u08C5\u08C6\u08C7\u0D04\u31BB\u31BC\u31BD\u31BE\u31BF\u4DB6\u4DB7\u4DB8\u4DB9\u4DBA\u4DBB\u4DBC\u4DBD\u4DBE\u4DBF\u9FF0\u9FF1\u9FF2\u9FF3\u9FF4\u9FF5\u9FF6\u9FF7\u9FF8\u9FF9\u9FFA\u9FFB\u9FFC\uA7C7\uA7C8\uA7C9\uA7CA\uA7F5\uA7F6\uAB68\uAB69\u{10E80}\u{10E81}\u{10E82}\u{10E83}\u{10E84}\u{10E85}\u{10E86}\u{10E87}\u{10E88}\u{10E89}\u{10E8A}\u{10E8B}\u{10E8C}\u{10E8D}\u{10E8E}\u{10E8F}\u{10E90}\u{10E91}\u{10E92}\u{10E93}\u{10E94}\u{10E95}\u{10E96}\u{10E97}\u{10E98}\u{10E99}\u{10E9A}\u{10E9B}\u{10E9C}\u{10E9D}\u{10E9E}\u{10E9F}\u{10EA0}\u{10EA1}\u{10EA2}\u{10EA3}\u{10EA4}\u{10EA5}\u{10EA6}\u{10EA7}\u{10EA8}\u{10EA9}\u{10EB0}\u{10EB1}\u{10FB0}\u{10FB1}\u{10FB2}\u{10FB3}\u{10FB4}\u{10FB5}\u{10FB6}\u{10FB7}\u{10FB8}\u{10FB9}\u{10FBA}\u{10FBB}\u{10FBC}\u{10FBD}\u{10FBE}\u{10FBF}\u{10FC0}\u{10FC1}\u{10FC2}\u{10FC3}\u{10FC4}\u{11147}\u{11460}\u{11461}\u{11900}\u{11901}\u{11902}\u{11903}\u{11904}\u{11905}\u{11906}\u{11909}\u{1190C}\u{1190D}\u{1190E}\u{1190F}\u{11910}\u{11911}\u{11912}\u{11913}\u{11915}\u{11916}\u{11918}\u{11919}\u{1191A}\u{1191B}\u{1191C}\u{1191D}\u{1191E}\u{1191F}\u{11920}\u{11921}\u{11922}\u{11923}\u{11924}\u{11925}\u{11926}\u{11927}\u{11928}\u{11929}\u{1192A}\u{1192B}\u{1192C}\u{1192D}\u{1192E}\u{1192F}\u{1193F}\u{11941}\u{11FB0}\u{18AF3}\u{18AF4}\u{18AF5}\u{18AF6}\u{18AF7}\u{18AF8}\u{18AF9}\u{18AFA}\u{18AFB}\u{18AFC}\u{18AFD}\u{18AFE}\u{18AFF}\u{18B00}\u{18B01}\u{18B02}\u{18B03}\u{18B04}\u{18B05}\u{18B06}\u{18B07}\u{18B08}\u{18B09}\u{18B0A}\u{18B0B}\u{18B0C}\u{18B0D}\u{18B0E}\u{18B0F}\u{18B10}\u{18B11}\u{18B12}\u{18B13}\u{18B14}\u{18B15}\u{18B16}\u{18B17}\u{18B18}\u{18B19}\u{18B1A}\u{18B1B}\u{18B1C}\u{18B1D}\u{18B1E}\u{18B1F}\u{18B20}\u{18B21}\u{18B22}\u{18B23}\u{18B24}\u{18B25}\u{18B26}\u{18B27}\u{18B28}\u{18B29}\u{18B2A}\u{18B2B}\u{18B2C}\u{18B2D}\u{18B2E}\u{18B2F}\u{18B30}\u{18B31}\u{18B32}\u{18B33}\u{18B34}\u{18B35}\u{18B36}\u{18B37}\u{18B38}\u{18B39}\u{18B3A}\u{18B3B}\u{18B3C}\u{18B3D}\u{18B3E}\u{18B3F}\u{18B40}\u{18B41}\u{18B42}\u{18B43}\u{18B44}\u{18B45}\u{18B46}\u{18B47}\u{18B48}\u{18B49}\u{18B4A}\u{18B4B}\u{18B4C}\u{18B4D}\u{18B4E}\u{18B4F}\u{18B50}\u{18B51}\u{18B52}\u{18B53}\u{18B54}\u{18B55}\u{18B56}\u{18B57}\u{18B58}\u{18B59}\u{18B5A}\u{18B5B}\u{18B5C}\u{18B5D}\u{18B5E}\u{18B5F}\u{18B60}\u{18B61}\u{18B62}\u{18B63}\u{18B64}\u{18B65}\u{18B66}\u{18B67}\u{18B68}\u{18B69}\u{18B6A}\u{18B6B}\u{18B6C}\u{18B6D}\u{18B6E}\u{18B6F}\u{18B70}\u{18B71}\u{18B72}\u{18B73}\u{18B74}\u{18B75}\u{18B76}\u{18B77}\u{18B78}\u{18B79}\u{18B7A}\u{18B7B}\u{18B7C}\u{18B7D}\u{18B7E}\u{18B7F}\u{18B80}\u{18B81}\u{18B82}\u{18B83}\u{18B84}\u{18B85}\u{18B86}\u{18B87}\u{18B88}\u{18B89}\u{18B8A}\u{18B8B}\u{18B8C}\u{18B8D}\u{18B8E}\u{18B8F}\u{18B90}\u{18B91}\u{18B92}\u{18B93}\u{18B94}\u{18B95}\u{18B96}\u{18B97}\u{18B98}\u{18B99}\u{18B9A}\u{18B9B}\u{18B9C}\u{18B9D}\u{18B9E}\u{18B9F}\u{18BA0}\u{18BA1}\u{18BA2}\u{18BA3}\u{18BA4}\u{18BA5}\u{18BA6}\u{18BA7}\u{18BA8}\u{18BA9}\u{18BAA}\u{18BAB}\u{18BAC}\u{18BAD}\u{18BAE}\u{18BAF}\u{18BB0}\u{18BB1}\u{18BB2}\u{18BB3}\u{18BB4}\u{18BB5}\u{18BB6}\u{18BB7}\u{18BB8}\u{18BB9}\u{18BBA}\u{18BBB}\u{18BBC}\u{18BBD}\u{18BBE}\u{18BBF}\u{18BC0}\u{18BC1}\u{18BC2}\u{18BC3}\u{18BC4}\u{18BC5}\u{18BC6}\u{18BC7}\u{18BC8}\u{18BC9}\u{18BCA}\u{18BCB}\u{18BCC}\u{18BCD}\u{18BCE}\u{18BCF}\u{18BD0}\u{18BD1}\u{18BD2}\u{18BD3}\u{18BD4}\u{18BD5}\u{18BD6}\u{18BD7}\u{18BD8}\u{18BD9}\u{18BDA}\u{18BDB}\u{18BDC}\u{18BDD}\u{18BDE}\u{18BDF}\u{18BE0}\u{18BE1}\u{18BE2}\u{18BE3}\u{18BE4}\u{18BE5}\u{18BE6}\u{18BE7}\u{18BE8}\u{18BE9}\u{18BEA}\u{18BEB}\u{18BEC}\u{18BED}\u{18BEE}\u{18BEF}\u{18BF0}\u{18BF1}\u{18BF2}\u{18BF3}\u{18BF4}\u{18BF5}\u{18BF6}\u{18BF7}\u{18BF8}\u{18BF9}\u{18BFA}\u{18BFB}\u{18BFC}\u{18BFD}\u{18BFE}\u{18BFF}\u{18C00}\u{18C01}\u{18C02}\u{18C03}\u{18C04}\u{18C05}\u{18C06}\u{18C07}\u{18C08}\u{18C09}\u{18C0A}\u{18C0B}\u{18C0C}\u{18C0D}\u{18C0E}\u{18C0F}\u{18C10}\u{18C11}\u{18C12}\u{18C13}\u{18C14}\u{18C15}\u{18C16}\u{18C17}\u{18C18}\u{18C19}\u{18C1A}\u{18C1B}\u{18C1C}\u{18C1D}\u{18C1E}\u{18C1F}\u{18C20}\u{18C21}\u{18C22}\u{18C23}\u{18C24}\u{18C25}\u{18C26}\u{18C27}\u{18C28}\u{18C29}\u{18C2A}\u{18C2B}\u{18C2C}\u{18C2D}\u{18C2E}\u{18C2F}\u{18C30}\u{18C31}\u{18C32}\u{18C33}\u{18C34}\u{18C35}\u{18C36}\u{18C37}\u{18C38}\u{18C39}\u{18C3A}\u{18C3B}\u{18C3C}\u{18C3D}\u{18C3E}\u{18C3F}\u{18C40}\u{18C41}\u{18C42}\u{18C43}\u{18C44}\u{18C45}\u{18C46}\u{18C47}\u{18C48}\u{18C49}\u{18C4A}\u{18C4B}\u{18C4C}\u{18C4D}\u{18C4E}\u{18C4F}\u{18C50}\u{18C51}\u{18C52}\u{18C53}\u{18C54}\u{18C55}\u{18C56}\u{18C57}\u{18C58}\u{18C59}\u{18C5A}\u{18C5B}\u{18C5C}\u{18C5D}\u{18C5E}\u{18C5F}\u{18C60}\u{18C61}\u{18C62}\u{18C63}\u{18C64}\u{18C65}\u{18C66}\u{18C67}\u{18C68}\u{18C69}\u{18C6A}\u{18C6B}\u{18C6C}\u{18C6D}\u{18C6E}\u{18C6F}\u{18C70}\u{18C71}\u{18C72}\u{18C73}\u{18C74}\u{18C75}\u{18C76}\u{18C77}\u{18C78}\u{18C79}\u{18C7A}\u{18C7B}\u{18C7C}\u{18C7D}\u{18C7E}\u{18C7F}\u{18C80}\u{18C81}\u{18C82}\u{18C83}\u{18C84}\u{18C85}\u{18C86}\u{18C87}\u{18C88}\u{18C89}\u{18C8A}\u{18C8B}\u{18C8C}\u{18C8D}\u{18C8E}\u{18C8F}\u{18C90}\u{18C91}\u{18C92}\u{18C93}\u{18C94}\u{18C95}\u{18C96}\u{18C97}\u{18C98}\u{18C99}\u{18C9A}\u{18C9B}\u{18C9C}\u{18C9D}\u{18C9E}\u{18C9F}\u{18CA0}\u{18CA1}\u{18CA2}\u{18CA3}\u{18CA4}\u{18CA5}\u{18CA6}\u{18CA7}\u{18CA8}\u{18CA9}\u{18CAA}\u{18CAB}\u{18CAC}\u{18CAD}\u{18CAE}\u{18CAF}\u{18CB0}\u{18CB1}\u{18CB2}\u{18CB3}\u{18CB4}\u{18CB5}\u{18CB6}\u{18CB7}\u{18CB8}\u{18CB9}\u{18CBA}\u{18CBB}\u{18CBC}\u{18CBD}\u{18CBE}\u{18CBF}\u{18CC0}\u{18CC1}\u{18CC2}\u{18CC3}\u{18CC4}\u{18CC5}\u{18CC6}\u{18CC7}\u{18CC8}\u{18CC9}\u{18CCA}\u{18CCB}\u{18CCC}\u{18CCD}\u{18CCE}\u{18CCF}\u{18CD0}\u{18CD1}\u{18CD2}\u{18CD3}\u{18CD4}\u{18CD5}\u{18D00}\u{18D01}\u{18D02}\u{18D03}\u{18D04}\u{18D05}\u{18D06}\u{18D07}\u{18D08}\u{2A6D7}\u{2A6D8}\u{2A6D9}\u{2A6DA}\u{2A6DB}\u{2A6DC}\u{2A6DD}\u{30000}\u{30001}\u{30002}\u{30003}\u{30004}\u{30005}\u{30006}\u{30007}\u{30008}\u{30009}\u{3000A}\u{3000B}\u{3000C}\u{3000D}\u{3000E}\u{3000F}\u{30010}\u{30011}\u{30012}\u{30013}\u{30014}\u{30015}\u{30016}\u{30017}\u{30018}\u{30019}\u{3001A}\u{3001B}\u{3001C}\u{3001D}\u{3001E}\u{3001F}\u{30020}\u{30021}\u{30022}\u{30023}\u{30024}\u{30025}\u{30026}\u{30027}\u{30028}\u{30029}\u{3002A}\u{3002B}\u{3002C}\u{3002D}\u{3002E}\u{3002F}\u{30030}\u{30031}\u{30032}\u{30033}\u{30034}\u{30035}\u{30036}\u{30037}\u{30038}\u{30039}\u{3003A}\u{3003B}\u{3003C}\u{3003D}\u{3003E}\u{3003F}\u{30040}\u{30041}\u{30042}\u{30043}\u{30044}\u{30045}\u{30046}\u{30047}\u{30048}\u{30049}\u{3004A}\u{3004B}\u{3004C}\u{3004D}\u{3004E}\u{3004F}\u{30050}\u{30051}\u{30052}\u{30053}\u{30054}\u{30055}\u{30056}\u{30057}\u{30058}\u{30059}\u{3005A}\u{3005B}\u{3005C}\u{3005D}\u{3005E}\u{3005F}\u{30060}\u{30061}\u{30062}\u{30063}\u{30064}\u{30065}\u{30066}\u{30067}\u{30068}\u{30069}\u{3006A}\u{3006B}\u{3006C}\u{3006D}\u{3006E}\u{3006F}\u{30070}\u{30071}\u{30072}\u{30073}\u{30074}\u{30075}\u{30076}\u{30077}\u{30078}\u{30079}\u{3007A}\u{3007B}\u{3007C}\u{3007D}\u{3007E}\u{3007F}\u{30080}\u{30081}\u{30082}\u{30083}\u{30084}\u{30085}\u{30086}\u{30087}\u{30088}\u{30089}\u{3008A}\u{3008B}\u{3008C}\u{3008D}\u{3008E}\u{3008F}\u{30090}\u{30091}\u{30092}\u{30093}\u{30094}\u{30095}\u{30096}\u{30097}\u{30098}\u{30099}\u{3009A}\u{3009B}\u{3009C}\u{3009D}\u{3009E}\u{3009F}\u{300A0}\u{300A1}\u{300A2}\u{300A3}\u{300A4}\u{300A5}\u{300A6}\u{300A7}\u{300A8}\u{300A9}\u{300AA}\u{300AB}\u{300AC}\u{300AD}\u{300AE}\u{300AF}\u{300B0}\u{300B1}\u{300B2}\u{300B3}\u{300B4}\u{300B5}\u{300B6}\u{300B7}\u{300B8}\u{300B9}\u{300BA}\u{300BB}\u{300BC}\u{300BD}\u{300BE}\u{300BF}\u{300C0}\u{300C1}\u{300C2}\u{300C3}\u{300C4}\u{300C5}\u{300C6}\u{300C7}\u{300C8}\u{300C9}\u{300CA}\u{300CB}\u{300CC}\u{300CD}\u{300CE}\u{300CF}\u{300D0}\u{300D1}\u{300D2}\u{300D3}\u{300D4}\u{300D5}\u{300D6}\u{300D7}\u{300D8}\u{300D9}\u{300DA}\u{300DB}\u{300DC}\u{300DD}\u{300DE}\u{300DF}\u{300E0}\u{300E1}\u{300E2}\u{300E3}\u{300E4}\u{300E5}\u{300E6}\u{300E7}\u{300E8}\u{300E9}\u{300EA}\u{300EB}\u{300EC}\u{300ED}\u{300EE}\u{300EF}\u{300F0}\u{300F1}\u{300F2}\u{300F3}\u{300F4}\u{300F5}\u{300F6}\u{300F7}\u{300F8}\u{300F9}\u{300FA}\u{300FB}\u{300FC}\u{300FD}\u{300FE}\u{300FF}\u{30100}\u{30101}\u{30102}\u{30103}\u{30104}\u{30105}\u{30106}\u{30107}\u{30108}\u{30109}\u{3010A}\u{3010B}\u{3010C}\u{3010D}\u{3010E}\u{3010F}\u{30110}\u{30111}\u{30112}\u{30113}\u{30114}\u{30115}\u{30116}\u{30117}\u{30118}\u{30119}\u{3011A}\u{3011B}\u{3011C}\u{3011D}\u{3011E}\u{3011F}\u{30120}\u{30121}\u{30122}\u{30123}\u{30124}\u{30125}\u{30126}\u{30127}\u{30128}\u{30129}\u{3012A}\u{3012B}\u{3012C}\u{3012D}\u{3012E}\u{3012F}\u{30130}\u{30131}\u{30132}\u{30133}\u{30134}\u{30135}\u{30136}\u{30137}\u{30138}\u{30139}\u{3013A}\u{3013B}\u{3013C}\u{3013D}\u{3013E}\u{3013F}\u{30140}\u{30141}\u{30142}\u{30143}\u{30144}\u{30145}\u{30146}\u{30147}\u{30148}\u{30149}\u{3014A}\u{3014B}\u{3014C}\u{3014D}\u{3014E}\u{3014F}\u{30150}\u{30151}\u{30152}\u{30153}\u{30154}\u{30155}\u{30156}\u{30157}\u{30158}\u{30159}\u{3015A}\u{3015B}\u{3015C}\u{3015D}\u{3015E}\u{3015F}\u{30160}\u{30161}\u{30162}\u{30163}\u{30164}\u{30165}\u{30166}\u{30167}\u{30168}\u{30169}\u{3016A}\u{3016B}\u{3016C}\u{3016D}\u{3016E}\u{3016F}\u{30170}\u{30171}\u{30172}\u{30173}\u{30174}\u{30175}\u{30176}\u{30177}\u{30178}\u{30179}\u{3017A}\u{3017B}\u{3017C}\u{3017D}\u{3017E}\u{3017F}\u{30180}\u{30181}\u{30182}\u{30183}\u{30184}\u{30185}\u{30186}\u{30187}\u{30188}\u{30189}\u{3018A}\u{3018B}\u{3018C}\u{3018D}\u{3018E}\u{3018F}\u{30190}\u{30191}\u{30192}\u{30193}\u{30194}\u{30195}\u{30196}\u{30197}\u{30198}\u{30199}\u{3019A}\u{3019B}\u{3019C}\u{3019D}\u{3019E}\u{3019F}\u{301A0}\u{301A1}\u{301A2}\u{301A3}\u{301A4}\u{301A5}\u{301A6}\u{301A7}\u{301A8}\u{301A9}\u{301AA}\u{301AB}\u{301AC}\u{301AD}\u{301AE}\u{301AF}\u{301B0}\u{301B1}\u{301B2}\u{301B3}\u{301B4}\u{301B5}\u{301B6}\u{301B7}\u{301B8}\u{301B9}\u{301BA}\u{301BB}\u{301BC}\u{301BD}\u{301BE}\u{301BF}\u{301C0}\u{301C1}\u{301C2}\u{301C3}\u{301C4}\u{301C5}\u{301C6}\u{301C7}\u{301C8}\u{301C9}\u{301CA}\u{301CB}\u{301CC}\u{301CD}\u{301CE}\u{301CF}\u{301D0}\u{301D1}\u{301D2}\u{301D3}\u{301D4}\u{301D5}\u{301D6}\u{301D7}\u{301D8}\u{301D9}\u{301DA}\u{301DB}\u{301DC}\u{301DD}\u{301DE}\u{301DF}\u{301E0}\u{301E1}\u{301E2}\u{301E3}\u{301E4}\u{301E5}\u{301E6}\u{301E7}\u{301E8}\u{301E9}\u{301EA}\u{301EB}\u{301EC}\u{301ED}\u{301EE}\u{301EF}\u{301F0}\u{301F1}\u{301F2}\u{301F3}\u{301F4}\u{301F5}\u{301F6}\u{301F7}\u{301F8}\u{301F9}\u{301FA}\u{301FB}\u{301FC}\u{301FD}\u{301FE}\u{301FF}\u{30200}\u{30201}\u{30202}\u{30203}\u{30204}\u{30205}\u{30206}\u{30207}\u{30208}\u{30209}\u{3020A}\u{3020B}\u{3020C}\u{3020D}\u{3020E}\u{3020F}\u{30210}\u{30211}\u{30212}\u{30213}\u{30214}\u{30215}\u{30216}\u{30217}\u{30218}\u{30219}\u{3021A}\u{3021B}\u{3021C}\u{3021D}\u{3021E}\u{3021F}\u{30220}\u{30221}\u{30222}\u{30223}\u{30224}\u{30225}\u{30226}\u{30227}\u{30228}\u{30229}\u{3022A}\u{3022B}\u{3022C}\u{3022D}\u{3022E}\u{3022F}\u{30230}\u{30231}\u{30232}\u{30233}\u{30234}\u{30235}\u{30236}\u{30237}\u{30238}\u{30239}\u{3023A}\u{3023B}\u{3023C}\u{3023D}\u{3023E}\u{3023F}\u{30240}\u{30241}\u{30242}\u{30243}\u{30244}\u{30245}\u{30246}\u{30247}\u{30248}\u{30249}\u{3024A}\u{3024B}\u{3024C}\u{3024D}\u{3024E}\u{3024F}\u{30250}\u{30251}\u{30252}\u{30253}\u{30254}\u{30255}\u{30256}\u{30257}\u{30258}\u{30259}\u{3025A}\u{3025B}\u{3025C}\u{3025D}\u{3025E}\u{3025F}\u{30260}\u{30261}\u{30262}\u{30263}\u{30264}\u{30265}\u{30266}\u{30267}\u{30268}\u{30269}\u{3026A}\u{3026B}\u{3026C}\u{3026D}\u{3026E}\u{3026F}\u{30270}\u{30271}\u{30272}\u{30273}\u{30274}\u{30275}\u{30276}\u{30277}\u{30278}\u{30279}\u{3027A}\u{3027B}\u{3027C}\u{3027D}\u{3027E}\u{3027F}\u{30280}\u{30281}\u{30282}\u{30283}\u{30284}\u{30285}\u{30286}\u{30287}\u{30288}\u{30289}\u{3028A}\u{3028B}\u{3028C}\u{3028D}\u{3028E}\u{3028F}\u{30290}\u{30291}\u{30292}\u{30293}\u{30294}\u{30295}\u{30296}\u{30297}\u{30298}\u{30299}\u{3029A}\u{3029B}\u{3029C}\u{3029D}\u{3029E}\u{3029F}\u{302A0}\u{302A1}\u{302A2}\u{302A3}\u{302A4}\u{302A5}\u{302A6}\u{302A7}\u{302A8}\u{302A9}\u{302AA}\u{302AB}\u{302AC}\u{302AD}\u{302AE}\u{302AF}\u{302B0}\u{302B1}\u{302B2}\u{302B3}\u{302B4}\u{302B5}\u{302B6}\u{302B7}\u{302B8}\u{302B9}\u{302BA}\u{302BB}\u{302BC}\u{302BD}\u{302BE}\u{302BF}\u{302C0}\u{302C1}\u{302C2}\u{302C3}\u{302C4}\u{302C5}\u{302C6}\u{302C7}\u{302C8}\u{302C9}\u{302CA}\u{302CB}\u{302CC}\u{302CD}\u{302CE}\u{302CF}\u{302D0}\u{302D1}\u{302D2}\u{302D3}\u{302D4}\u{302D5}\u{302D6}\u{302D7}\u{302D8}\u{302D9}\u{302DA}\u{302DB}\u{302DC}\u{302DD}\u{302DE}\u{302DF}\u{302E0}\u{302E1}\u{302E2}\u{302E3}\u{302E4}\u{302E5}\u{302E6}\u{302E7}\u{302E8}\u{302E9}\u{302EA}\u{302EB}\u{302EC}\u{302ED}\u{302EE}\u{302EF}\u{302F0}\u{302F1}\u{302F2}\u{302F3}\u{302F4}\u{302F5}\u{302F6}\u{302F7}\u{302F8}\u{302F9}\u{302FA}\u{302FB}\u{302FC}\u{302FD}\u{302FE}\u{302FF}\u{30300}\u{30301}\u{30302}\u{30303}\u{30304}\u{30305}\u{30306}\u{30307}\u{30308}\u{30309}\u{3030A}\u{3030B}\u{3030C}\u{3030D}\u{3030E}\u{3030F}\u{30310}\u{30311}\u{30312}\u{30313}\u{30314}\u{30315}\u{30316}\u{30317}\u{30318}\u{30319}\u{3031A}\u{3031B}\u{3031C}\u{3031D}\u{3031E}\u{3031F}\u{30320}\u{30321}\u{30322}\u{30323}\u{30324}\u{30325}\u{30326}\u{30327}\u{30328}\u{30329}\u{3032A}\u{3032B}\u{3032C}\u{3032D}\u{3032E}\u{3032F}\u{30330}\u{30331}\u{30332}\u{30333}\u{30334}\u{30335}\u{30336}\u{30337}\u{30338}\u{30339}\u{3033A}\u{3033B}\u{3033C}\u{3033D}\u{3033E}\u{3033F}\u{30340}\u{30341}\u{30342}\u{30343}\u{30344}\u{30345}\u{30346}\u{30347}\u{30348}\u{30349}\u{3034A}\u{3034B}\u{3034C}\u{3034D}\u{3034E}\u{3034F}\u{30350}\u{30351}\u{30352}\u{30353}\u{30354}\u{30355}\u{30356}\u{30357}\u{30358}\u{30359}\u{3035A}\u{3035B}\u{3035C}\u{3035D}\u{3035E}\u{3035F}\u{30360}\u{30361}\u{30362}\u{30363}\u{30364}\u{30365}\u{30366}\u{30367}\u{30368}\u{30369}\u{3036A}\u{3036B}\u{3036C}\u{3036D}\u{3036E}\u{3036F}\u{30370}\u{30371}\u{30372}\u{30373}\u{30374}\u{30375}\u{30376}\u{30377}\u{30378}\u{30379}\u{3037A}\u{3037B}\u{3037C}\u{3037D}\u{3037E}\u{3037F}\u{30380}\u{30381}\u{30382}\u{30383}\u{30384}\u{30385}\u{30386}\u{30387}\u{30388}\u{30389}\u{3038A}\u{3038B}\u{3038C}\u{3038D}\u{3038E}\u{3038F}\u{30390}\u{30391}\u{30392}\u{30393}\u{30394}\u{30395}\u{30396}\u{30397}\u{30398}\u{30399}\u{3039A}\u{3039B}\u{3039C}\u{3039D}\u{3039E}\u{3039F}\u{303A0}\u{303A1}\u{303A2}\u{303A3}\u{303A4}\u{303A5}\u{303A6}\u{303A7}\u{303A8}\u{303A9}\u{303AA}\u{303AB}\u{303AC}\u{303AD}\u{303AE}\u{303AF}\u{303B0}\u{303B1}\u{303B2}\u{303B3}\u{303B4}\u{303B5}\u{303B6}\u{303B7}\u{303B8}\u{303B9}\u{303BA}\u{303BB}\u{303BC}\u{303BD}\u{303BE}\u{303BF}\u{303C0}\u{303C1}\u{303C2}\u{303C3}\u{303C4}\u{303C5}\u{303C6}\u{303C7}\u{303C8}\u{303C9}\u{303CA}\u{303CB}\u{303CC}\u{303CD}\u{303CE}\u{303CF}\u{303D0}\u{303D1}\u{303D2}\u{303D3}\u{303D4}\u{303D5}\u{303D6}\u{303D7}\u{303D8}\u{303D9}\u{303DA}\u{303DB}\u{303DC}\u{303DD}\u{303DE}\u{303DF}\u{303E0}\u{303E1}\u{303E2}\u{303E3}\u{303E4}\u{303E5}\u{303E6}\u{303E7}\u{303E8}\u{303E9}\u{303EA}\u{303EB}\u{303EC}\u{303ED}\u{303EE}\u{303EF}\u{303F0}\u{303F1}\u{303F2}\u{303F3}\u{303F4}\u{303F5}\u{303F6}\u{303F7}\u{303F8}\u{303F9}\u{303FA}\u{303FB}\u{303FC}\u{303FD}\u{303FE}\u{303FF}\u{30400}\u{30401}\u{30402}\u{30403}\u{30404}\u{30405}\u{30406}\u{30407}\u{30408}\u{30409}\u{3040A}\u{3040B}\u{3040C}\u{3040D}\u{3040E}\u{3040F}\u{30410}\u{30411}\u{30412}\u{30413}\u{30414}\u{30415}\u{30416}\u{30417}\u{30418}\u{30419}\u{3041A}\u{3041B}\u{3041C}\u{3041D}\u{3041E}\u{3041F}\u{30420}\u{30421}\u{30422}\u{30423}\u{30424}\u{30425}\u{30426}\u{30427}\u{30428}\u{30429}\u{3042A}\u{3042B}\u{3042C}\u{3042D}\u{3042E}\u{3042F}\u{30430}\u{30431}\u{30432}\u{30433}\u{30434}\u{30435}\u{30436}\u{30437}\u{30438}\u{30439}\u{3043A}\u{3043B}\u{3043C}\u{3043D}\u{3043E}\u{3043F}\u{30440}\u{30441}\u{30442}\u{30443}\u{30444}\u{30445}\u{30446}\u{30447}\u{30448}\u{30449}\u{3044A}\u{3044B}\u{3044C}\u{3044D}\u{3044E}\u{3044F}\u{30450}\u{30451}\u{30452}\u{30453}\u{30454}\u{30455}\u{30456}\u{30457}\u{30458}\u{30459}\u{3045A}\u{3045B}\u{3045C}\u{3045D}\u{3045E}\u{3045F}\u{30460}\u{30461}\u{30462}\u{30463}\u{30464}\u{30465}\u{30466}\u{30467}\u{30468}\u{30469}\u{3046A}\u{3046B}\u{3046C}\u{3046D}\u{3046E}\u{3046F}\u{30470}\u{30471}\u{30472}\u{30473}\u{30474}\u{30475}\u{30476}\u{30477}\u{30478}\u{30479}\u{3047A}\u{3047B}\u{3047C}\u{3047D}\u{3047E}\u{3047F}\u{30480}\u{30481}\u{30482}\u{30483}\u{30484}\u{30485}\u{30486}\u{30487}\u{30488}\u{30489}\u{3048A}\u{3048B}\u{3048C}\u{3048D}\u{3048E}\u{3048F}\u{30490}\u{30491}\u{30492}\u{30493}\u{30494}\u{30495}\u{30496}\u{30497}\u{30498}\u{30499}\u{3049A}\u{3049B}\u{3049C}\u{3049D}\u{3049E}\u{3049F}\u{304A0}\u{304A1}\u{304A2}\u{304A3}\u{304A4}\u{304A5}\u{304A6}\u{304A7}\u{304A8}\u{304A9}\u{304AA}\u{304AB}\u{304AC}\u{304AD}\u{304AE}\u{304AF}\u{304B0}\u{304B1}\u{304B2}\u{304B3}\u{304B4}\u{304B5}\u{304B6}\u{304B7}\u{304B8}\u{304B9}\u{304BA}\u{304BB}\u{304BC}\u{304BD}\u{304BE}\u{304BF}\u{304C0}\u{304C1}\u{304C2}\u{304C3}\u{304C4}\u{304C5}\u{304C6}\u{304C7}\u{304C8}\u{304C9}\u{304CA}\u{304CB}\u{304CC}\u{304CD}\u{304CE}\u{304CF}\u{304D0}\u{304D1}\u{304D2}\u{304D3}\u{304D4}\u{304D5}\u{304D6}\u{304D7}\u{304D8}\u{304D9}\u{304DA}\u{304DB}\u{304DC}\u{304DD}\u{304DE}\u{304DF}\u{304E0}\u{304E1}\u{304E2}\u{304E3}\u{304E4}\u{304E5}\u{304E6}\u{304E7}\u{304E8}\u{304E9}\u{304EA}\u{304EB}\u{304EC}\u{304ED}\u{304EE}\u{304EF}\u{304F0}\u{304F1}\u{304F2}\u{304F3}\u{304F4}\u{304F5}\u{304F6}\u{304F7}\u{304F8}\u{304F9}\u{304FA}\u{304FB}\u{304FC}\u{304FD}\u{304FE}\u{304FF}\u{30500}\u{30501}\u{30502}\u{30503}\u{30504}\u{30505}\u{30506}\u{30507}\u{30508}\u{30509}\u{3050A}\u{3050B}\u{3050C}\u{3050D}\u{3050E}\u{3050F}\u{30510}\u{30511}\u{30512}\u{30513}\u{30514}\u{30515}\u{30516}\u{30517}\u{30518}\u{30519}\u{3051A}\u{3051B}\u{3051C}\u{3051D}\u{3051E}\u{3051F}\u{30520}\u{30521}\u{30522}\u{30523}\u{30524}\u{30525}\u{30526}\u{30527}\u{30528}\u{30529}\u{3052A}\u{3052B}\u{3052C}\u{3052D}\u{3052E}\u{3052F}\u{30530}\u{30531}\u{30532}\u{30533}\u{30534}\u{30535}\u{30536}\u{30537}\u{30538}\u{30539}\u{3053A}\u{3053B}\u{3053C}\u{3053D}\u{3053E}\u{3053F}\u{30540}\u{30541}\u{30542}\u{30543}\u{30544}\u{30545}\u{30546}\u{30547}\u{30548}\u{30549}\u{3054A}\u{3054B}\u{3054C}\u{3054D}\u{3054E}\u{3054F}\u{30550}\u{30551}\u{30552}\u{30553}\u{30554}\u{30555}\u{30556}\u{30557}\u{30558}\u{30559}\u{3055A}\u{3055B}\u{3055C}\u{3055D}\u{3055E}\u{3055F}\u{30560}\u{30561}\u{30562}\u{30563}\u{30564}\u{30565}\u{30566}\u{30567}\u{30568}\u{30569}\u{3056A}\u{3056B}\u{3056C}\u{3056D}\u{3056E}\u{3056F}\u{30570}\u{30571}\u{30572}\u{30573}\u{30574}\u{30575}\u{30576}\u{30577}\u{30578}\u{30579}\u{3057A}\u{3057B}\u{3057C}\u{3057D}\u{3057E}\u{3057F}\u{30580}\u{30581}\u{30582}\u{30583}\u{30584}\u{30585}\u{30586}\u{30587}\u{30588}\u{30589}\u{3058A}\u{3058B}\u{3058C}\u{3058D}\u{3058E}\u{3058F}\u{30590}\u{30591}\u{30592}\u{30593}\u{30594}\u{30595}\u{30596}\u{30597}\u{30598}\u{30599}\u{3059A}\u{3059B}\u{3059C}\u{3059D}\u{3059E}\u{3059F}\u{305A0}\u{305A1}\u{305A2}\u{305A3}\u{305A4}\u{305A5}\u{305A6}\u{305A7}\u{305A8}\u{305A9}\u{305AA}\u{305AB}\u{305AC}\u{305AD}\u{305AE}\u{305AF}\u{305B0}\u{305B1}\u{305B2}\u{305B3}\u{305B4}\u{305B5}\u{305B6}\u{305B7}\u{305B8}\u{305B9}\u{305BA}\u{305BB}\u{305BC}\u{305BD}\u{305BE}\u{305BF}\u{305C0}\u{305C1}\u{305C2}\u{305C3}\u{305C4}\u{305C5}\u{305C6}\u{305C7}\u{305C8}\u{305C9}\u{305CA}\u{305CB}\u{305CC}\u{305CD}\u{305CE}\u{305CF}\u{305D0}\u{305D1}\u{305D2}\u{305D3}\u{305D4}\u{305D5}\u{305D6}\u{305D7}\u{305D8}\u{305D9}\u{305DA}\u{305DB}\u{305DC}\u{305DD}\u{305DE}\u{305DF}\u{305E0}\u{305E1}\u{305E2}\u{305E3}\u{305E4}\u{305E5}\u{305E6}\u{305E7}\u{305E8}\u{305E9}\u{305EA}\u{305EB}\u{305EC}\u{305ED}\u{305EE}\u{305EF}\u{305F0}\u{305F1}\u{305F2}\u{305F3}\u{305F4}\u{305F5}\u{305F6}\u{305F7}\u{305F8}\u{305F9}\u{305FA}\u{305FB}\u{305FC}\u{305FD}\u{305FE}\u{305FF}\u{30600}\u{30601}\u{30602}\u{30603}\u{30604}\u{30605}\u{30606}\u{30607}\u{30608}\u{30609}\u{3060A}\u{3060B}\u{3060C}\u{3060D}\u{3060E}\u{3060F}\u{30610}\u{30611}\u{30612}\u{30613}\u{30614}\u{30615}\u{30616}\u{30617}\u{30618}\u{30619}\u{3061A}\u{3061B}\u{3061C}\u{3061D}\u{3061E}\u{3061F}\u{30620}\u{30621}\u{30622}\u{30623}\u{30624}\u{30625}\u{30626}\u{30627}\u{30628}\u{30629}\u{3062A}\u{3062B}\u{3062C}\u{3062D}\u{3062E}\u{3062F}\u{30630}\u{30631}\u{30632}\u{30633}\u{30634}\u{30635}\u{30636}\u{30637}\u{30638}\u{30639}\u{3063A}\u{3063B}\u{3063C}\u{3063D}\u{3063E}\u{3063F}\u{30640}\u{30641}\u{30642}\u{30643}\u{30644}\u{30645}\u{30646}\u{30647}\u{30648}\u{30649}\u{3064A}\u{3064B}\u{3064C}\u{3064D}\u{3064E}\u{3064F}\u{30650}\u{30651}\u{30652}\u{30653}\u{30654}\u{30655}\u{30656}\u{30657}\u{30658}\u{30659}\u{3065A}\u{3065B}\u{3065C}\u{3065D}\u{3065E}\u{3065F}\u{30660}\u{30661}\u{30662}\u{30663}\u{30664}\u{30665}\u{30666}\u{30667}\u{30668}\u{30669}\u{3066A}\u{3066B}\u{3066C}\u{3066D}\u{3066E}\u{3066F}\u{30670}\u{30671}\u{30672}\u{30673}\u{30674}\u{30675}\u{30676}\u{30677}\u{30678}\u{30679}\u{3067A}\u{3067B}\u{3067C}\u{3067D}\u{3067E}\u{3067F}\u{30680}\u{30681}\u{30682}\u{30683}\u{30684}\u{30685}\u{30686}\u{30687}\u{30688}\u{30689}\u{3068A}\u{3068B}\u{3068C}\u{3068D}\u{3068E}\u{3068F}\u{30690}\u{30691}\u{30692}\u{30693}\u{30694}\u{30695}\u{30696}\u{30697}\u{30698}\u{30699}\u{3069A}\u{3069B}\u{3069C}\u{3069D}\u{3069E}\u{3069F}\u{306A0}\u{306A1}\u{306A2}\u{306A3}\u{306A4}\u{306A5}\u{306A6}\u{306A7}\u{306A8}\u{306A9}\u{306AA}\u{306AB}\u{306AC}\u{306AD}\u{306AE}\u{306AF}\u{306B0}\u{306B1}\u{306B2}\u{306B3}\u{306B4}\u{306B5}\u{306B6}\u{306B7}\u{306B8}\u{306B9}\u{306BA}\u{306BB}\u{306BC}\u{306BD}\u{306BE}\u{306BF}\u{306C0}\u{306C1}\u{306C2}\u{306C3}\u{306C4}\u{306C5}\u{306C6}\u{306C7}\u{306C8}\u{306C9}\u{306CA}\u{306CB}\u{306CC}\u{306CD}\u{306CE}\u{306CF}\u{306D0}\u{306D1}\u{306D2}\u{306D3}\u{306D4}\u{306D5}\u{306D6}\u{306D7}\u{306D8}\u{306D9}\u{306DA}\u{306DB}\u{306DC}\u{306DD}\u{306DE}\u{306DF}\u{306E0}\u{306E1}\u{306E2}\u{306E3}\u{306E4}\u{306E5}\u{306E6}\u{306E7}\u{306E8}\u{306E9}\u{306EA}\u{306EB}\u{306EC}\u{306ED}\u{306EE}\u{306EF}\u{306F0}\u{306F1}\u{306F2}\u{306F3}\u{306F4}\u{306F5}\u{306F6}\u{306F7}\u{306F8}\u{306F9}\u{306FA}\u{306FB}\u{306FC}\u{306FD}\u{306FE}\u{306FF}\u{30700}\u{30701}\u{30702}\u{30703}\u{30704}\u{30705}\u{30706}\u{30707}\u{30708}\u{30709}\u{3070A}\u{3070B}\u{3070C}\u{3070D}\u{3070E}\u{3070F}\u{30710}\u{30711}\u{30712}\u{30713}\u{30714}\u{30715}\u{30716}\u{30717}\u{30718}\u{30719}\u{3071A}\u{3071B}\u{3071C}\u{3071D}\u{3071E}\u{3071F}\u{30720}\u{30721}\u{30722}\u{30723}\u{30724}\u{30725}\u{30726}\u{30727}\u{30728}\u{30729}\u{3072A}\u{3072B}\u{3072C}\u{3072D}\u{3072E}\u{3072F}\u{30730}\u{30731}\u{30732}\u{30733}\u{30734}\u{30735}\u{30736}\u{30737}\u{30738}\u{30739}\u{3073A}\u{3073B}\u{3073C}\u{3073D}\u{3073E}\u{3073F}\u{30740}\u{30741}\u{30742}\u{30743}\u{30744}\u{30745}\u{30746}\u{30747}\u{30748}\u{30749}\u{3074A}\u{3074B}\u{3074C}\u{3074D}\u{3074E}\u{3074F}\u{30750}\u{30751}\u{30752}\u{30753}\u{30754}\u{30755}\u{30756}\u{30757}\u{30758}\u{30759}\u{3075A}\u{3075B}\u{3075C}\u{3075D}\u{3075E}\u{3075F}\u{30760}\u{30761}\u{30762}\u{30763}\u{30764}\u{30765}\u{30766}\u{30767}\u{30768}\u{30769}\u{3076A}\u{3076B}\u{3076C}\u{3076D}\u{3076E}\u{3076F}\u{30770}\u{30771}\u{30772}\u{30773}\u{30774}\u{30775}\u{30776}\u{30777}\u{30778}\u{30779}\u{3077A}\u{3077B}\u{3077C}\u{3077D}\u{3077E}\u{3077F}\u{30780}\u{30781}\u{30782}\u{30783}\u{30784}\u{30785}\u{30786}\u{30787}\u{30788}\u{30789}\u{3078A}\u{3078B}\u{3078C}\u{3078D}\u{3078E}\u{3078F}\u{30790}\u{30791}\u{30792}\u{30793}\u{30794}\u{30795}\u{30796}\u{30797}\u{30798}\u{30799}\u{3079A}\u{3079B}\u{3079C}\u{3079D}\u{3079E}\u{3079F}\u{307A0}\u{307A1}\u{307A2}\u{307A3}\u{307A4}\u{307A5}\u{307A6}\u{307A7}\u{307A8}\u{307A9}\u{307AA}\u{307AB}\u{307AC}\u{307AD}\u{307AE}\u{307AF}\u{307B0}\u{307B1}\u{307B2}\u{307B3}\u{307B4}\u{307B5}\u{307B6}\u{307B7}\u{307B8}\u{307B9}\u{307BA}\u{307BB}\u{307BC}\u{307BD}\u{307BE}\u{307BF}\u{307C0}\u{307C1}\u{307C2}\u{307C3}\u{307C4}\u{307C5}\u{307C6}\u{307C7}\u{307C8}\u{307C9}\u{307CA}\u{307CB}\u{307CC}\u{307CD}\u{307CE}\u{307CF}\u{307D0}\u{307D1}\u{307D2}\u{307D3}\u{307D4}\u{307D5}\u{307D6}\u{307D7}\u{307D8}\u{307D9}\u{307DA}\u{307DB}\u{307DC}\u{307DD}\u{307DE}\u{307DF}\u{307E0}\u{307E1}\u{307E2}\u{307E3}\u{307E4}\u{307E5}\u{307E6}\u{307E7}\u{307E8}\u{307E9}\u{307EA}\u{307EB}\u{307EC}\u{307ED}\u{307EE}\u{307EF}\u{307F0}\u{307F1}\u{307F2}\u{307F3}\u{307F4}\u{307F5}\u{307F6}\u{307F7}\u{307F8}\u{307F9}\u{307FA}\u{307FB}\u{307FC}\u{307FD}\u{307FE}\u{307FF}\u{30800}\u{30801}\u{30802}\u{30803}\u{30804}\u{30805}\u{30806}\u{30807}\u{30808}\u{30809}\u{3080A}\u{3080B}\u{3080C}\u{3080D}\u{3080E}\u{3080F}\u{30810}\u{30811}\u{30812}\u{30813}\u{30814}\u{30815}\u{30816}\u{30817}\u{30818}\u{30819}\u{3081A}\u{3081B}\u{3081C}\u{3081D}\u{3081E}\u{3081F}\u{30820}\u{30821}\u{30822}\u{30823}\u{30824}\u{30825}\u{30826}\u{30827}\u{30828}\u{30829}\u{3082A}\u{3082B}\u{3082C}\u{3082D}\u{3082E}\u{3082F}\u{30830}\u{30831}\u{30832}\u{30833}\u{30834}\u{30835}\u{30836}\u{30837}\u{30838}\u{30839}\u{3083A}\u{3083B}\u{3083C}\u{3083D}\u{3083E}\u{3083F}\u{30840}\u{30841}\u{30842}\u{30843}\u{30844}\u{30845}\u{30846}\u{30847}\u{30848}\u{30849}\u{3084A}\u{3084B}\u{3084C}\u{3084D}\u{3084E}\u{3084F}\u{30850}\u{30851}\u{30852}\u{30853}\u{30854}\u{30855}\u{30856}\u{30857}\u{30858}\u{30859}\u{3085A}\u{3085B}\u{3085C}\u{3085D}\u{3085E}\u{3085F}\u{30860}\u{30861}\u{30862}\u{30863}\u{30864}\u{30865}\u{30866}\u{30867}\u{30868}\u{30869}\u{3086A}\u{3086B}\u{3086C}\u{3086D}\u{3086E}\u{3086F}\u{30870}\u{30871}\u{30872}\u{30873}\u{30874}\u{30875}\u{30876}\u{30877}\u{30878}\u{30879}\u{3087A}\u{3087B}\u{3087C}\u{3087D}\u{3087E}\u{3087F}\u{30880}\u{30881}\u{30882}\u{30883}\u{30884}\u{30885}\u{30886}\u{30887}\u{30888}\u{30889}\u{3088A}\u{3088B}\u{3088C}\u{3088D}\u{3088E}\u{3088F}\u{30890}\u{30891}\u{30892}\u{30893}\u{30894}\u{30895}\u{30896}\u{30897}\u{30898}\u{30899}\u{3089A}\u{3089B}\u{3089C}\u{3089D}\u{3089E}\u{3089F}\u{308A0}\u{308A1}\u{308A2}\u{308A3}\u{308A4}\u{308A5}\u{308A6}\u{308A7}\u{308A8}\u{308A9}\u{308AA}\u{308AB}\u{308AC}\u{308AD}\u{308AE}\u{308AF}\u{308B0}\u{308B1}\u{308B2}\u{308B3}\u{308B4}\u{308B5}\u{308B6}\u{308B7}\u{308B8}\u{308B9}\u{308BA}\u{308BB}\u{308BC}\u{308BD}\u{308BE}\u{308BF}\u{308C0}\u{308C1}\u{308C2}\u{308C3}\u{308C4}\u{308C5}\u{308C6}\u{308C7}\u{308C8}\u{308C9}\u{308CA}\u{308CB}\u{308CC}\u{308CD}\u{308CE}\u{308CF}\u{308D0}\u{308D1}\u{308D2}\u{308D3}\u{308D4}\u{308D5}\u{308D6}\u{308D7}\u{308D8}\u{308D9}\u{308DA}\u{308DB}\u{308DC}\u{308DD}\u{308DE}\u{308DF}\u{308E0}\u{308E1}\u{308E2}\u{308E3}\u{308E4}\u{308E5}\u{308E6}\u{308E7}\u{308E8}\u{308E9}\u{308EA}\u{308EB}\u{308EC}\u{308ED}\u{308EE}\u{308EF}\u{308F0}\u{308F1}\u{308F2}\u{308F3}\u{308F4}\u{308F5}\u{308F6}\u{308F7}\u{308F8}\u{308F9}\u{308FA}\u{308FB}\u{308FC}\u{308FD}\u{308FE}\u{308FF}\u{30900}\u{30901}\u{30902}\u{30903}\u{30904}\u{30905}\u{30906}\u{30907}\u{30908}\u{30909}\u{3090A}\u{3090B}\u{3090C}\u{3090D}\u{3090E}\u{3090F}\u{30910}\u{30911}\u{30912}\u{30913}\u{30914}\u{30915}\u{30916}\u{30917}\u{30918}\u{30919}\u{3091A}\u{3091B}\u{3091C}\u{3091D}\u{3091E}\u{3091F}\u{30920}\u{30921}\u{30922}\u{30923}\u{30924}\u{30925}\u{30926}\u{30927}\u{30928}\u{30929}\u{3092A}\u{3092B}\u{3092C}\u{3092D}\u{3092E}\u{3092F}\u{30930}\u{30931}\u{30932}\u{30933}\u{30934}\u{30935}\u{30936}\u{30937}\u{30938}\u{30939}\u{3093A}\u{3093B}\u{3093C}\u{3093D}\u{3093E}\u{3093F}\u{30940}\u{30941}\u{30942}\u{30943}\u{30944}\u{30945}\u{30946}\u{30947}\u{30948}\u{30949}\u{3094A}\u{3094B}\u{3094C}\u{3094D}\u{3094E}\u{3094F}\u{30950}\u{30951}\u{30952}\u{30953}\u{30954}\u{30955}\u{30956}\u{30957}\u{30958}\u{30959}\u{3095A}\u{3095B}\u{3095C}\u{3095D}\u{3095E}\u{3095F}\u{30960}\u{30961}\u{30962}\u{30963}\u{30964}\u{30965}\u{30966}\u{30967}\u{30968}\u{30969}\u{3096A}\u{3096B}\u{3096C}\u{3096D}\u{3096E}\u{3096F}\u{30970}\u{30971}\u{30972}\u{30973}\u{30974}\u{30975}\u{30976}\u{30977}\u{30978}\u{30979}\u{3097A}\u{3097B}\u{3097C}\u{3097D}\u{3097E}\u{3097F}\u{30980}\u{30981}\u{30982}\u{30983}\u{30984}\u{30985}\u{30986}\u{30987}\u{30988}\u{30989}\u{3098A}\u{3098B}\u{3098C}\u{3098D}\u{3098E}\u{3098F}\u{30990}\u{30991}\u{30992}\u{30993}\u{30994}\u{30995}\u{30996}\u{30997}\u{30998}\u{30999}\u{3099A}\u{3099B}\u{3099C}\u{3099D}\u{3099E}\u{3099F}\u{309A0}\u{309A1}\u{309A2}\u{309A3}\u{309A4}\u{309A5}\u{309A6}\u{309A7}\u{309A8}\u{309A9}\u{309AA}\u{309AB}\u{309AC}\u{309AD}\u{309AE}\u{309AF}\u{309B0}\u{309B1}\u{309B2}\u{309B3}\u{309B4}\u{309B5}\u{309B6}\u{309B7}\u{309B8}\u{309B9}\u{309BA}\u{309BB}\u{309BC}\u{309BD}\u{309BE}\u{309BF}\u{309C0}\u{309C1}\u{309C2}\u{309C3}\u{309C4}\u{309C5}\u{309C6}\u{309C7}\u{309C8}\u{309C9}\u{309CA}\u{309CB}\u{309CC}\u{309CD}\u{309CE}\u{309CF}\u{309D0}\u{309D1}\u{309D2}\u{309D3}\u{309D4}\u{309D5}\u{309D6}\u{309D7}\u{309D8}\u{309D9}\u{309DA}\u{309DB}\u{309DC}\u{309DD}\u{309DE}\u{309DF}\u{309E0}\u{309E1}\u{309E2}\u{309E3}\u{309E4}\u{309E5}\u{309E6}\u{309E7}\u{309E8}\u{309E9}\u{309EA}\u{309EB}\u{309EC}\u{309ED}\u{309EE}\u{309EF}\u{309F0}\u{309F1}\u{309F2}\u{309F3}\u{309F4}\u{309F5}\u{309F6}\u{309F7}\u{309F8}\u{309F9}\u{309FA}\u{309FB}\u{309FC}\u{309FD}\u{309FE}\u{309FF}\u{30A00}\u{30A01}\u{30A02}\u{30A03}\u{30A04}\u{30A05}\u{30A06}\u{30A07}\u{30A08}\u{30A09}\u{30A0A}\u{30A0B}\u{30A0C}\u{30A0D}\u{30A0E}\u{30A0F}\u{30A10}\u{30A11}\u{30A12}\u{30A13}\u{30A14}\u{30A15}\u{30A16}\u{30A17}\u{30A18}\u{30A19}\u{30A1A}\u{30A1B}\u{30A1C}\u{30A1D}\u{30A1E}\u{30A1F}\u{30A20}\u{30A21}\u{30A22}\u{30A23}\u{30A24}\u{30A25}\u{30A26}\u{30A27}\u{30A28}\u{30A29}\u{30A2A}\u{30A2B}\u{30A2C}\u{30A2D}\u{30A2E}\u{30A2F}\u{30A30}\u{30A31}\u{30A32}\u{30A33}\u{30A34}\u{30A35}\u{30A36}\u{30A37}\u{30A38}\u{30A39}\u{30A3A}\u{30A3B}\u{30A3C}\u{30A3D}\u{30A3E}\u{30A3F}\u{30A40}\u{30A41}\u{30A42}\u{30A43}\u{30A44}\u{30A45}\u{30A46}\u{30A47}\u{30A48}\u{30A49}\u{30A4A}\u{30A4B}\u{30A4C}\u{30A4D}\u{30A4E}\u{30A4F}\u{30A50}\u{30A51}\u{30A52}\u{30A53}\u{30A54}\u{30A55}\u{30A56}\u{30A57}\u{30A58}\u{30A59}\u{30A5A}\u{30A5B}\u{30A5C}\u{30A5D}\u{30A5E}\u{30A5F}\u{30A60}\u{30A61}\u{30A62}\u{30A63}\u{30A64}\u{30A65}\u{30A66}\u{30A67}\u{30A68}\u{30A69}\u{30A6A}\u{30A6B}\u{30A6C}\u{30A6D}\u{30A6E}\u{30A6F}\u{30A70}\u{30A71}\u{30A72}\u{30A73}\u{30A74}\u{30A75}\u{30A76}\u{30A77}\u{30A78}\u{30A79}\u{30A7A}\u{30A7B}\u{30A7C}\u{30A7D}\u{30A7E}\u{30A7F}\u{30A80}\u{30A81}\u{30A82}\u{30A83}\u{30A84}\u{30A85}\u{30A86}\u{30A87}\u{30A88}\u{30A89}\u{30A8A}\u{30A8B}\u{30A8C}\u{30A8D}\u{30A8E}\u{30A8F}\u{30A90}\u{30A91}\u{30A92}\u{30A93}\u{30A94}\u{30A95}\u{30A96}\u{30A97}\u{30A98}\u{30A99}\u{30A9A}\u{30A9B}\u{30A9C}\u{30A9D}\u{30A9E}\u{30A9F}\u{30AA0}\u{30AA1}\u{30AA2}\u{30AA3}\u{30AA4}\u{30AA5}\u{30AA6}\u{30AA7}\u{30AA8}\u{30AA9}\u{30AAA}\u{30AAB}\u{30AAC}\u{30AAD}\u{30AAE}\u{30AAF}\u{30AB0}\u{30AB1}\u{30AB2}\u{30AB3}\u{30AB4}\u{30AB5}\u{30AB6}\u{30AB7}\u{30AB8}\u{30AB9}\u{30ABA}\u{30ABB}\u{30ABC}\u{30ABD}\u{30ABE}\u{30ABF}\u{30AC0}\u{30AC1}\u{30AC2}\u{30AC3}\u{30AC4}\u{30AC5}\u{30AC6}\u{30AC7}\u{30AC8}\u{30AC9}\u{30ACA}\u{30ACB}\u{30ACC}\u{30ACD}\u{30ACE}\u{30ACF}\u{30AD0}\u{30AD1}\u{30AD2}\u{30AD3}\u{30AD4}\u{30AD5}\u{30AD6}\u{30AD7}\u{30AD8}\u{30AD9}\u{30ADA}\u{30ADB}\u{30ADC}\u{30ADD}\u{30ADE}\u{30ADF}\u{30AE0}\u{30AE1}\u{30AE2}\u{30AE3}\u{30AE4}\u{30AE5}\u{30AE6}\u{30AE7}\u{30AE8}\u{30AE9}\u{30AEA}\u{30AEB}\u{30AEC}\u{30AED}\u{30AEE}\u{30AEF}\u{30AF0}\u{30AF1}\u{30AF2}\u{30AF3}\u{30AF4}\u{30AF5}\u{30AF6}\u{30AF7}\u{30AF8}\u{30AF9}\u{30AFA}\u{30AFB}\u{30AFC}\u{30AFD}\u{30AFE}\u{30AFF}\u{30B00}\u{30B01}\u{30B02}\u{30B03}\u{30B04}\u{30B05}\u{30B06}\u{30B07}\u{30B08}\u{30B09}\u{30B0A}\u{30B0B}\u{30B0C}\u{30B0D}\u{30B0E}\u{30B0F}\u{30B10}\u{30B11}\u{30B12}\u{30B13}\u{30B14}\u{30B15}\u{30B16}\u{30B17}\u{30B18}\u{30B19}\u{30B1A}\u{30B1B}\u{30B1C}\u{30B1D}\u{30B1E}\u{30B1F}\u{30B20}\u{30B21}\u{30B22}\u{30B23}\u{30B24}\u{30B25}\u{30B26}\u{30B27}\u{30B28}\u{30B29}\u{30B2A}\u{30B2B}\u{30B2C}\u{30B2D}\u{30B2E}\u{30B2F}\u{30B30}\u{30B31}\u{30B32}\u{30B33}\u{30B34}\u{30B35}\u{30B36}\u{30B37}\u{30B38}\u{30B39}\u{30B3A}\u{30B3B}\u{30B3C}\u{30B3D}\u{30B3E}\u{30B3F}\u{30B40}\u{30B41}\u{30B42}\u{30B43}\u{30B44}\u{30B45}\u{30B46}\u{30B47}\u{30B48}\u{30B49}\u{30B4A}\u{30B4B}\u{30B4C}\u{30B4D}\u{30B4E}\u{30B4F}\u{30B50}\u{30B51}\u{30B52}\u{30B53}\u{30B54}\u{30B55}\u{30B56}\u{30B57}\u{30B58}\u{30B59}\u{30B5A}\u{30B5B}\u{30B5C}\u{30B5D}\u{30B5E}\u{30B5F}\u{30B60}\u{30B61}\u{30B62}\u{30B63}\u{30B64}\u{30B65}\u{30B66}\u{30B67}\u{30B68}\u{30B69}\u{30B6A}\u{30B6B}\u{30B6C}\u{30B6D}\u{30B6E}\u{30B6F}\u{30B70}\u{30B71}\u{30B72}\u{30B73}\u{30B74}\u{30B75}\u{30B76}\u{30B77}\u{30B78}\u{30B79}\u{30B7A}\u{30B7B}\u{30B7C}\u{30B7D}\u{30B7E}\u{30B7F}\u{30B80}\u{30B81}\u{30B82}\u{30B83}\u{30B84}\u{30B85}\u{30B86}\u{30B87}\u{30B88}\u{30B89}\u{30B8A}\u{30B8B}\u{30B8C}\u{30B8D}\u{30B8E}\u{30B8F}\u{30B90}\u{30B91}\u{30B92}\u{30B93}\u{30B94}\u{30B95}\u{30B96}\u{30B97}\u{30B98}\u{30B99}\u{30B9A}\u{30B9B}\u{30B9C}\u{30B9D}\u{30B9E}\u{30B9F}\u{30BA0}\u{30BA1}\u{30BA2}\u{30BA3}\u{30BA4}\u{30BA5}\u{30BA6}\u{30BA7}\u{30BA8}\u{30BA9}\u{30BAA}\u{30BAB}\u{30BAC}\u{30BAD}\u{30BAE}\u{30BAF}\u{30BB0}\u{30BB1}\u{30BB2}\u{30BB3}\u{30BB4}\u{30BB5}\u{30BB6}\u{30BB7}\u{30BB8}\u{30BB9}\u{30BBA}\u{30BBB}\u{30BBC}\u{30BBD}\u{30BBE}\u{30BBF}\u{30BC0}\u{30BC1}\u{30BC2}\u{30BC3}\u{30BC4}\u{30BC5}\u{30BC6}\u{30BC7}\u{30BC8}\u{30BC9}\u{30BCA}\u{30BCB}\u{30BCC}\u{30BCD}\u{30BCE}\u{30BCF}\u{30BD0}\u{30BD1}\u{30BD2}\u{30BD3}\u{30BD4}\u{30BD5}\u{30BD6}\u{30BD7}\u{30BD8}\u{30BD9}\u{30BDA}\u{30BDB}\u{30BDC}\u{30BDD}\u{30BDE}\u{30BDF}\u{30BE0}\u{30BE1}\u{30BE2}\u{30BE3}\u{30BE4}\u{30BE5}\u{30BE6}\u{30BE7}\u{30BE8}\u{30BE9}\u{30BEA}\u{30BEB}\u{30BEC}\u{30BED}\u{30BEE}\u{30BEF}\u{30BF0}\u{30BF1}\u{30BF2}\u{30BF3}\u{30BF4}\u{30BF5}\u{30BF6}\u{30BF7}\u{30BF8}\u{30BF9}\u{30BFA}\u{30BFB}\u{30BFC}\u{30BFD}\u{30BFE}\u{30BFF}\u{30C00}\u{30C01}\u{30C02}\u{30C03}\u{30C04}\u{30C05}\u{30C06}\u{30C07}\u{30C08}\u{30C09}\u{30C0A}\u{30C0B}\u{30C0C}\u{30C0D}\u{30C0E}\u{30C0F}\u{30C10}\u{30C11}\u{30C12}\u{30C13}\u{30C14}\u{30C15}\u{30C16}\u{30C17}\u{30C18}\u{30C19}\u{30C1A}\u{30C1B}\u{30C1C}\u{30C1D}\u{30C1E}\u{30C1F}\u{30C20}\u{30C21}\u{30C22}\u{30C23}\u{30C24}\u{30C25}\u{30C26}\u{30C27}\u{30C28}\u{30C29}\u{30C2A}\u{30C2B}\u{30C2C}\u{30C2D}\u{30C2E}\u{30C2F}\u{30C30}\u{30C31}\u{30C32}\u{30C33}\u{30C34}\u{30C35}\u{30C36}\u{30C37}\u{30C38}\u{30C39}\u{30C3A}\u{30C3B}\u{30C3C}\u{30C3D}\u{30C3E}\u{30C3F}\u{30C40}\u{30C41}\u{30C42}\u{30C43}\u{30C44}\u{30C45}\u{30C46}\u{30C47}\u{30C48}\u{30C49}\u{30C4A}\u{30C4B}\u{30C4C}\u{30C4D}\u{30C4E}\u{30C4F}\u{30C50}\u{30C51}\u{30C52}\u{30C53}\u{30C54}\u{30C55}\u{30C56}\u{30C57}\u{30C58}\u{30C59}\u{30C5A}\u{30C5B}\u{30C5C}\u{30C5D}\u{30C5E}\u{30C5F}\u{30C60}\u{30C61}\u{30C62}\u{30C63}\u{30C64}\u{30C65}\u{30C66}\u{30C67}\u{30C68}\u{30C69}\u{30C6A}\u{30C6B}\u{30C6C}\u{30C6D}\u{30C6E}\u{30C6F}\u{30C70}\u{30C71}\u{30C72}\u{30C73}\u{30C74}\u{30C75}\u{30C76}\u{30C77}\u{30C78}\u{30C79}\u{30C7A}\u{30C7B}\u{30C7C}\u{30C7D}\u{30C7E}\u{30C7F}\u{30C80}\u{30C81}\u{30C82}\u{30C83}\u{30C84}\u{30C85}\u{30C86}\u{30C87}\u{30C88}\u{30C89}\u{30C8A}\u{30C8B}\u{30C8C}\u{30C8D}\u{30C8E}\u{30C8F}\u{30C90}\u{30C91}\u{30C92}\u{30C93}\u{30C94}\u{30C95}\u{30C96}\u{30C97}\u{30C98}\u{30C99}\u{30C9A}\u{30C9B}\u{30C9C}\u{30C9D}\u{30C9E}\u{30C9F}\u{30CA0}\u{30CA1}\u{30CA2}\u{30CA3}\u{30CA4}\u{30CA5}\u{30CA6}\u{30CA7}\u{30CA8}\u{30CA9}\u{30CAA}\u{30CAB}\u{30CAC}\u{30CAD}\u{30CAE}\u{30CAF}\u{30CB0}\u{30CB1}\u{30CB2}\u{30CB3}\u{30CB4}\u{30CB5}\u{30CB6}\u{30CB7}\u{30CB8}\u{30CB9}\u{30CBA}\u{30CBB}\u{30CBC}\u{30CBD}\u{30CBE}\u{30CBF}\u{30CC0}\u{30CC1}\u{30CC2}\u{30CC3}\u{30CC4}\u{30CC5}\u{30CC6}\u{30CC7}\u{30CC8}\u{30CC9}\u{30CCA}\u{30CCB}\u{30CCC}\u{30CCD}\u{30CCE}\u{30CCF}\u{30CD0}\u{30CD1}\u{30CD2}\u{30CD3}\u{30CD4}\u{30CD5}\u{30CD6}\u{30CD7}\u{30CD8}\u{30CD9}\u{30CDA}\u{30CDB}\u{30CDC}\u{30CDD}\u{30CDE}\u{30CDF}\u{30CE0}\u{30CE1}\u{30CE2}\u{30CE3}\u{30CE4}\u{30CE5}\u{30CE6}\u{30CE7}\u{30CE8}\u{30CE9}\u{30CEA}\u{30CEB}\u{30CEC}\u{30CED}\u{30CEE}\u{30CEF}\u{30CF0}\u{30CF1}\u{30CF2}\u{30CF3}\u{30CF4}\u{30CF5}\u{30CF6}\u{30CF7}\u{30CF8}\u{30CF9}\u{30CFA}\u{30CFB}\u{30CFC}\u{30CFD}\u{30CFE}\u{30CFF}\u{30D00}\u{30D01}\u{30D02}\u{30D03}\u{30D04}\u{30D05}\u{30D06}\u{30D07}\u{30D08}\u{30D09}\u{30D0A}\u{30D0B}\u{30D0C}\u{30D0D}\u{30D0E}\u{30D0F}\u{30D10}\u{30D11}\u{30D12}\u{30D13}\u{30D14}\u{30D15}\u{30D16}\u{30D17}\u{30D18}\u{30D19}\u{30D1A}\u{30D1B}\u{30D1C}\u{30D1D}\u{30D1E}\u{30D1F}\u{30D20}\u{30D21}\u{30D22}\u{30D23}\u{30D24}\u{30D25}\u{30D26}\u{30D27}\u{30D28}\u{30D29}\u{30D2A}\u{30D2B}\u{30D2C}\u{30D2D}\u{30D2E}\u{30D2F}\u{30D30}\u{30D31}\u{30D32}\u{30D33}\u{30D34}\u{30D35}\u{30D36}\u{30D37}\u{30D38}\u{30D39}\u{30D3A}\u{30D3B}\u{30D3C}\u{30D3D}\u{30D3E}\u{30D3F}\u{30D40}\u{30D41}\u{30D42}\u{30D43}\u{30D44}\u{30D45}\u{30D46}\u{30D47}\u{30D48}\u{30D49}\u{30D4A}\u{30D4B}\u{30D4C}\u{30D4D}\u{30D4E}\u{30D4F}\u{30D50}\u{30D51}\u{30D52}\u{30D53}\u{30D54}\u{30D55}\u{30D56}\u{30D57}\u{30D58}\u{30D59}\u{30D5A}\u{30D5B}\u{30D5C}\u{30D5D}\u{30D5E}\u{30D5F}\u{30D60}\u{30D61}\u{30D62}\u{30D63}\u{30D64}\u{30D65}\u{30D66}\u{30D67}\u{30D68}\u{30D69}\u{30D6A}\u{30D6B}\u{30D6C}\u{30D6D}\u{30D6E}\u{30D6F}\u{30D70}\u{30D71}\u{30D72}\u{30D73}\u{30D74}\u{30D75}\u{30D76}\u{30D77}\u{30D78}\u{30D79}\u{30D7A}\u{30D7B}\u{30D7C}\u{30D7D}\u{30D7E}\u{30D7F}\u{30D80}\u{30D81}\u{30D82}\u{30D83}\u{30D84}\u{30D85}\u{30D86}\u{30D87}\u{30D88}\u{30D89}\u{30D8A}\u{30D8B}\u{30D8C}\u{30D8D}\u{30D8E}\u{30D8F}\u{30D90}\u{30D91}\u{30D92}\u{30D93}\u{30D94}\u{30D95}\u{30D96}\u{30D97}\u{30D98}\u{30D99}\u{30D9A}\u{30D9B}\u{30D9C}\u{30D9D}\u{30D9E}\u{30D9F}\u{30DA0}\u{30DA1}\u{30DA2}\u{30DA3}\u{30DA4}\u{30DA5}\u{30DA6}\u{30DA7}\u{30DA8}\u{30DA9}\u{30DAA}\u{30DAB}\u{30DAC}\u{30DAD}\u{30DAE}\u{30DAF}\u{30DB0}\u{30DB1}\u{30DB2}\u{30DB3}\u{30DB4}\u{30DB5}\u{30DB6}\u{30DB7}\u{30DB8}\u{30DB9}\u{30DBA}\u{30DBB}\u{30DBC}\u{30DBD}\u{30DBE}\u{30DBF}\u{30DC0}\u{30DC1}\u{30DC2}\u{30DC3}\u{30DC4}\u{30DC5}\u{30DC6}\u{30DC7}\u{30DC8}\u{30DC9}\u{30DCA}\u{30DCB}\u{30DCC}\u{30DCD}\u{30DCE}\u{30DCF}\u{30DD0}\u{30DD1}\u{30DD2}\u{30DD3}\u{30DD4}\u{30DD5}\u{30DD6}\u{30DD7}\u{30DD8}\u{30DD9}\u{30DDA}\u{30DDB}\u{30DDC}\u{30DDD}\u{30DDE}\u{30DDF}\u{30DE0}\u{30DE1}\u{30DE2}\u{30DE3}\u{30DE4}\u{30DE5}\u{30DE6}\u{30DE7}\u{30DE8}\u{30DE9}\u{30DEA}\u{30DEB}\u{30DEC}\u{30DED}\u{30DEE}\u{30DEF}\u{30DF0}\u{30DF1}\u{30DF2}\u{30DF3}\u{30DF4}\u{30DF5}\u{30DF6}\u{30DF7}\u{30DF8}\u{30DF9}\u{30DFA}\u{30DFB}\u{30DFC}\u{30DFD}\u{30DFE}\u{30DFF}\u{30E00}\u{30E01}\u{30E02}\u{30E03}\u{30E04}\u{30E05}\u{30E06}\u{30E07}\u{30E08}\u{30E09}\u{30E0A}\u{30E0B}\u{30E0C}\u{30E0D}\u{30E0E}\u{30E0F}\u{30E10}\u{30E11}\u{30E12}\u{30E13}\u{30E14}\u{30E15}\u{30E16}\u{30E17}\u{30E18}\u{30E19}\u{30E1A}\u{30E1B}\u{30E1C}\u{30E1D}\u{30E1E}\u{30E1F}\u{30E20}\u{30E21}\u{30E22}\u{30E23}\u{30E24}\u{30E25}\u{30E26}\u{30E27}\u{30E28}\u{30E29}\u{30E2A}\u{30E2B}\u{30E2C}\u{30E2D}\u{30E2E}\u{30E2F}\u{30E30}\u{30E31}\u{30E32}\u{30E33}\u{30E34}\u{30E35}\u{30E36}\u{30E37}\u{30E38}\u{30E39}\u{30E3A}\u{30E3B}\u{30E3C}\u{30E3D}\u{30E3E}\u{30E3F}\u{30E40}\u{30E41}\u{30E42}\u{30E43}\u{30E44}\u{30E45}\u{30E46}\u{30E47}\u{30E48}\u{30E49}\u{30E4A}\u{30E4B}\u{30E4C}\u{30E4D}\u{30E4E}\u{30E4F}\u{30E50}\u{30E51}\u{30E52}\u{30E53}\u{30E54}\u{30E55}\u{30E56}\u{30E57}\u{30E58}\u{30E59}\u{30E5A}\u{30E5B}\u{30E5C}\u{30E5D}\u{30E5E}\u{30E5F}\u{30E60}\u{30E61}\u{30E62}\u{30E63}\u{30E64}\u{30E65}\u{30E66}\u{30E67}\u{30E68}\u{30E69}\u{30E6A}\u{30E6B}\u{30E6C}\u{30E6D}\u{30E6E}\u{30E6F}\u{30E70}\u{30E71}\u{30E72}\u{30E73}\u{30E74}\u{30E75}\u{30E76}\u{30E77}\u{30E78}\u{30E79}\u{30E7A}\u{30E7B}\u{30E7C}\u{30E7D}\u{30E7E}\u{30E7F}\u{30E80}\u{30E81}\u{30E82}\u{30E83}\u{30E84}\u{30E85}\u{30E86}\u{30E87}\u{30E88}\u{30E89}\u{30E8A}\u{30E8B}\u{30E8C}\u{30E8D}\u{30E8E}\u{30E8F}\u{30E90}\u{30E91}\u{30E92}\u{30E93}\u{30E94}\u{30E95}\u{30E96}\u{30E97}\u{30E98}\u{30E99}\u{30E9A}\u{30E9B}\u{30E9C}\u{30E9D}\u{30E9E}\u{30E9F}\u{30EA0}\u{30EA1}\u{30EA2}\u{30EA3}\u{30EA4}\u{30EA5}\u{30EA6}\u{30EA7}\u{30EA8}\u{30EA9}\u{30EAA}\u{30EAB}\u{30EAC}\u{30EAD}\u{30EAE}\u{30EAF}\u{30EB0}\u{30EB1}\u{30EB2}\u{30EB3}\u{30EB4}\u{30EB5}\u{30EB6}\u{30EB7}\u{30EB8}\u{30EB9}\u{30EBA}\u{30EBB}\u{30EBC}\u{30EBD}\u{30EBE}\u{30EBF}\u{30EC0}\u{30EC1}\u{30EC2}\u{30EC3}\u{30EC4}\u{30EC5}\u{30EC6}\u{30EC7}\u{30EC8}\u{30EC9}\u{30ECA}\u{30ECB}\u{30ECC}\u{30ECD}\u{30ECE}\u{30ECF}\u{30ED0}\u{30ED1}\u{30ED2}\u{30ED3}\u{30ED4}\u{30ED5}\u{30ED6}\u{30ED7}\u{30ED8}\u{30ED9}\u{30EDA}\u{30EDB}\u{30EDC}\u{30EDD}\u{30EDE}\u{30EDF}\u{30EE0}\u{30EE1}\u{30EE2}\u{30EE3}\u{30EE4}\u{30EE5}\u{30EE6}\u{30EE7}\u{30EE8}\u{30EE9}\u{30EEA}\u{30EEB}\u{30EEC}\u{30EED}\u{30EEE}\u{30EEF}\u{30EF0}\u{30EF1}\u{30EF2}\u{30EF3}\u{30EF4}\u{30EF5}\u{30EF6}\u{30EF7}\u{30EF8}\u{30EF9}\u{30EFA}\u{30EFB}\u{30EFC}\u{30EFD}\u{30EFE}\u{30EFF}\u{30F00}\u{30F01}\u{30F02}\u{30F03}\u{30F04}\u{30F05}\u{30F06}\u{30F07}\u{30F08}\u{30F09}\u{30F0A}\u{30F0B}\u{30F0C}\u{30F0D}\u{30F0E}\u{30F0F}\u{30F10}\u{30F11}\u{30F12}\u{30F13}\u{30F14}\u{30F15}\u{30F16}\u{30F17}\u{30F18}\u{30F19}\u{30F1A}\u{30F1B}\u{30F1C}\u{30F1D}\u{30F1E}\u{30F1F}\u{30F20}\u{30F21}\u{30F22}\u{30F23}\u{30F24}\u{30F25}\u{30F26}\u{30F27}\u{30F28}\u{30F29}\u{30F2A}\u{30F2B}\u{30F2C}\u{30F2D}\u{30F2E}\u{30F2F}\u{30F30}\u{30F31}\u{30F32}\u{30F33}\u{30F34}\u{30F35}\u{30F36}\u{30F37}\u{30F38}\u{30F39}\u{30F3A}\u{30F3B}\u{30F3C}\u{30F3D}\u{30F3E}\u{30F3F}\u{30F40}\u{30F41}\u{30F42}\u{30F43}\u{30F44}\u{30F45}\u{30F46}\u{30F47}\u{30F48}\u{30F49}\u{30F4A}\u{30F4B}\u{30F4C}\u{30F4D}\u{30F4E}\u{30F4F}\u{30F50}\u{30F51}\u{30F52}\u{30F53}\u{30F54}\u{30F55}\u{30F56}\u{30F57}\u{30F58}\u{30F59}\u{30F5A}\u{30F5B}\u{30F5C}\u{30F5D}\u{30F5E}\u{30F5F}\u{30F60}\u{30F61}\u{30F62}\u{30F63}\u{30F64}\u{30F65}\u{30F66}\u{30F67}\u{30F68}\u{30F69}\u{30F6A}\u{30F6B}\u{30F6C}\u{30F6D}\u{30F6E}\u{30F6F}\u{30F70}\u{30F71}\u{30F72}\u{30F73}\u{30F74}\u{30F75}\u{30F76}\u{30F77}\u{30F78}\u{30F79}\u{30F7A}\u{30F7B}\u{30F7C}\u{30F7D}\u{30F7E}\u{30F7F}\u{30F80}\u{30F81}\u{30F82}\u{30F83}\u{30F84}\u{30F85}\u{30F86}\u{30F87}\u{30F88}\u{30F89}\u{30F8A}\u{30F8B}\u{30F8C}\u{30F8D}\u{30F8E}\u{30F8F}\u{30F90}\u{30F91}\u{30F92}\u{30F93}\u{30F94}\u{30F95}\u{30F96}\u{30F97}\u{30F98}\u{30F99}\u{30F9A}\u{30F9B}\u{30F9C}\u{30F9D}\u{30F9E}\u{30F9F}\u{30FA0}\u{30FA1}\u{30FA2}\u{30FA3}\u{30FA4}\u{30FA5}\u{30FA6}\u{30FA7}\u{30FA8}\u{30FA9}\u{30FAA}\u{30FAB}\u{30FAC}\u{30FAD}\u{30FAE}\u{30FAF}\u{30FB0}\u{30FB1}\u{30FB2}\u{30FB3}\u{30FB4}\u{30FB5}\u{30FB6}\u{30FB7}\u{30FB8}\u{30FB9}\u{30FBA}\u{30FBB}\u{30FBC}\u{30FBD}\u{30FBE}\u{30FBF}\u{30FC0}\u{30FC1}\u{30FC2}\u{30FC3}\u{30FC4}\u{30FC5}\u{30FC6}\u{30FC7}\u{30FC8}\u{30FC9}\u{30FCA}\u{30FCB}\u{30FCC}\u{30FCD}\u{30FCE}\u{30FCF}\u{30FD0}\u{30FD1}\u{30FD2}\u{30FD3}\u{30FD4}\u{30FD5}\u{30FD6}\u{30FD7}\u{30FD8}\u{30FD9}\u{30FDA}\u{30FDB}\u{30FDC}\u{30FDD}\u{30FDE}\u{30FDF}\u{30FE0}\u{30FE1}\u{30FE2}\u{30FE3}\u{30FE4}\u{30FE5}\u{30FE6}\u{30FE7}\u{30FE8}\u{30FE9}\u{30FEA}\u{30FEB}\u{30FEC}\u{30FED}\u{30FEE}\u{30FEF}\u{30FF0}\u{30FF1}\u{30FF2}\u{30FF3}\u{30FF4}\u{30FF5}\u{30FF6}\u{30FF7}\u{30FF8}\u{30FF9}\u{30FFA}\u{30FFB}\u{30FFC}\u{30FFD}\u{30FFE}\u{30FFF}\u{31000}\u{31001}\u{31002}\u{31003}\u{31004}\u{31005}\u{31006}\u{31007}\u{31008}\u{31009}\u{3100A}\u{3100B}\u{3100C}\u{3100D}\u{3100E}\u{3100F}\u{31010}\u{31011}\u{31012}\u{31013}\u{31014}\u{31015}\u{31016}\u{31017}\u{31018}\u{31019}\u{3101A}\u{3101B}\u{3101C}\u{3101D}\u{3101E}\u{3101F}\u{31020}\u{31021}\u{31022}\u{31023}\u{31024}\u{31025}\u{31026}\u{31027}\u{31028}\u{31029}\u{3102A}\u{3102B}\u{3102C}\u{3102D}\u{3102E}\u{3102F}\u{31030}\u{31031}\u{31032}\u{31033}\u{31034}\u{31035}\u{31036}\u{31037}\u{31038}\u{31039}\u{3103A}\u{3103B}\u{3103C}\u{3103D}\u{3103E}\u{3103F}\u{31040}\u{31041}\u{31042}\u{31043}\u{31044}\u{31045}\u{31046}\u{31047}\u{31048}\u{31049}\u{3104A}\u{3104B}\u{3104C}\u{3104D}\u{3104E}\u{3104F}\u{31050}\u{31051}\u{31052}\u{31053}\u{31054}\u{31055}\u{31056}\u{31057}\u{31058}\u{31059}\u{3105A}\u{3105B}\u{3105C}\u{3105D}\u{3105E}\u{3105F}\u{31060}\u{31061}\u{31062}\u{31063}\u{31064}\u{31065}\u{31066}\u{31067}\u{31068}\u{31069}\u{3106A}\u{3106B}\u{3106C}\u{3106D}\u{3106E}\u{3106F}\u{31070}\u{31071}\u{31072}\u{31073}\u{31074}\u{31075}\u{31076}\u{31077}\u{31078}\u{31079}\u{3107A}\u{3107B}\u{3107C}\u{3107D}\u{3107E}\u{3107F}\u{31080}\u{31081}\u{31082}\u{31083}\u{31084}\u{31085}\u{31086}\u{31087}\u{31088}\u{31089}\u{3108A}\u{3108B}\u{3108C}\u{3108D}\u{3108E}\u{3108F}\u{31090}\u{31091}\u{31092}\u{31093}\u{31094}\u{31095}\u{31096}\u{31097}\u{31098}\u{31099}\u{3109A}\u{3109B}\u{3109C}\u{3109D}\u{3109E}\u{3109F}\u{310A0}\u{310A1}\u{310A2}\u{310A3}\u{310A4}\u{310A5}\u{310A6}\u{310A7}\u{310A8}\u{310A9}\u{310AA}\u{310AB}\u{310AC}\u{310AD}\u{310AE}\u{310AF}\u{310B0}\u{310B1}\u{310B2}\u{310B3}\u{310B4}\u{310B5}\u{310B6}\u{310B7}\u{310B8}\u{310B9}\u{310BA}\u{310BB}\u{310BC}\u{310BD}\u{310BE}\u{310BF}\u{310C0}\u{310C1}\u{310C2}\u{310C3}\u{310C4}\u{310C5}\u{310C6}\u{310C7}\u{310C8}\u{310C9}\u{310CA}\u{310CB}\u{310CC}\u{310CD}\u{310CE}\u{310CF}\u{310D0}\u{310D1}\u{310D2}\u{310D3}\u{310D4}\u{310D5}\u{310D6}\u{310D7}\u{310D8}\u{310D9}\u{310DA}\u{310DB}\u{310DC}\u{310DD}\u{310DE}\u{310DF}\u{310E0}\u{310E1}\u{310E2}\u{310E3}\u{310E4}\u{310E5}\u{310E6}\u{310E7}\u{310E8}\u{310E9}\u{310EA}\u{310EB}\u{310EC}\u{310ED}\u{310EE}\u{310EF}\u{310F0}\u{310F1}\u{310F2}\u{310F3}\u{310F4}\u{310F5}\u{310F6}\u{310F7}\u{310F8}\u{310F9}\u{310FA}\u{310FB}\u{310FC}\u{310FD}\u{310FE}\u{310FF}\u{31100}\u{31101}\u{31102}\u{31103}\u{31104}\u{31105}\u{31106}\u{31107}\u{31108}\u{31109}\u{3110A}\u{3110B}\u{3110C}\u{3110D}\u{3110E}\u{3110F}\u{31110}\u{31111}\u{31112}\u{31113}\u{31114}\u{31115}\u{31116}\u{31117}\u{31118}\u{31119}\u{3111A}\u{3111B}\u{3111C}\u{3111D}\u{3111E}\u{3111F}\u{31120}\u{31121}\u{31122}\u{31123}\u{31124}\u{31125}\u{31126}\u{31127}\u{31128}\u{31129}\u{3112A}\u{3112B}\u{3112C}\u{3112D}\u{3112E}\u{3112F}\u{31130}\u{31131}\u{31132}\u{31133}\u{31134}\u{31135}\u{31136}\u{31137}\u{31138}\u{31139}\u{3113A}\u{3113B}\u{3113C}\u{3113D}\u{3113E}\u{3113F}\u{31140}\u{31141}\u{31142}\u{31143}\u{31144}\u{31145}\u{31146}\u{31147}\u{31148}\u{31149}\u{3114A}\u{3114B}\u{3114C}\u{3114D}\u{3114E}\u{3114F}\u{31150}\u{31151}\u{31152}\u{31153}\u{31154}\u{31155}\u{31156}\u{31157}\u{31158}\u{31159}\u{3115A}\u{3115B}\u{3115C}\u{3115D}\u{3115E}\u{3115F}\u{31160}\u{31161}\u{31162}\u{31163}\u{31164}\u{31165}\u{31166}\u{31167}\u{31168}\u{31169}\u{3116A}\u{3116B}\u{3116C}\u{3116D}\u{3116E}\u{3116F}\u{31170}\u{31171}\u{31172}\u{31173}\u{31174}\u{31175}\u{31176}\u{31177}\u{31178}\u{31179}\u{3117A}\u{3117B}\u{3117C}\u{3117D}\u{3117E}\u{3117F}\u{31180}\u{31181}\u{31182}\u{31183}\u{31184}\u{31185}\u{31186}\u{31187}\u{31188}\u{31189}\u{3118A}\u{3118B}\u{3118C}\u{3118D}\u{3118E}\u{3118F}\u{31190}\u{31191}\u{31192}\u{31193}\u{31194}\u{31195}\u{31196}\u{31197}\u{31198}\u{31199}\u{3119A}\u{3119B}\u{3119C}\u{3119D}\u{3119E}\u{3119F}\u{311A0}\u{311A1}\u{311A2}\u{311A3}\u{311A4}\u{311A5}\u{311A6}\u{311A7}\u{311A8}\u{311A9}\u{311AA}\u{311AB}\u{311AC}\u{311AD}\u{311AE}\u{311AF}\u{311B0}\u{311B1}\u{311B2}\u{311B3}\u{311B4}\u{311B5}\u{311B6}\u{311B7}\u{311B8}\u{311B9}\u{311BA}\u{311BB}\u{311BC}\u{311BD}\u{311BE}\u{311BF}\u{311C0}\u{311C1}\u{311C2}\u{311C3}\u{311C4}\u{311C5}\u{311C6}\u{311C7}\u{311C8}\u{311C9}\u{311CA}\u{311CB}\u{311CC}\u{311CD}\u{311CE}\u{311CF}\u{311D0}\u{311D1}\u{311D2}\u{311D3}\u{311D4}\u{311D5}\u{311D6}\u{311D7}\u{311D8}\u{311D9}\u{311DA}\u{311DB}\u{311DC}\u{311DD}\u{311DE}\u{311DF}\u{311E0}\u{311E1}\u{311E2}\u{311E3}\u{311E4}\u{311E5}\u{311E6}\u{311E7}\u{311E8}\u{311E9}\u{311EA}\u{311EB}\u{311EC}\u{311ED}\u{311EE}\u{311EF}\u{311F0}\u{311F1}\u{311F2}\u{311F3}\u{311F4}\u{311F5}\u{311F6}\u{311F7}\u{311F8}\u{311F9}\u{311FA}\u{311FB}\u{311FC}\u{311FD}\u{311FE}\u{311FF}\u{31200}\u{31201}\u{31202}\u{31203}\u{31204}\u{31205}\u{31206}\u{31207}\u{31208}\u{31209}\u{3120A}\u{3120B}\u{3120C}\u{3120D}\u{3120E}\u{3120F}\u{31210}\u{31211}\u{31212}\u{31213}\u{31214}\u{31215}\u{31216}\u{31217}\u{31218}\u{31219}\u{3121A}\u{3121B}\u{3121C}\u{3121D}\u{3121E}\u{3121F}\u{31220}\u{31221}\u{31222}\u{31223}\u{31224}\u{31225}\u{31226}\u{31227}\u{31228}\u{31229}\u{3122A}\u{3122B}\u{3122C}\u{3122D}\u{3122E}\u{3122F}\u{31230}\u{31231}\u{31232}\u{31233}\u{31234}\u{31235}\u{31236}\u{31237}\u{31238}\u{31239}\u{3123A}\u{3123B}\u{3123C}\u{3123D}\u{3123E}\u{3123F}\u{31240}\u{31241}\u{31242}\u{31243}\u{31244}\u{31245}\u{31246}\u{31247}\u{31248}\u{31249}\u{3124A}\u{3124B}\u{3124C}\u{3124D}\u{3124E}\u{3124F}\u{31250}\u{31251}\u{31252}\u{31253}\u{31254}\u{31255}\u{31256}\u{31257}\u{31258}\u{31259}\u{3125A}\u{3125B}\u{3125C}\u{3125D}\u{3125E}\u{3125F}\u{31260}\u{31261}\u{31262}\u{31263}\u{31264}\u{31265}\u{31266}\u{31267}\u{31268}\u{31269}\u{3126A}\u{3126B}\u{3126C}\u{3126D}\u{3126E}\u{3126F}\u{31270}\u{31271}\u{31272}\u{31273}\u{31274}\u{31275}\u{31276}\u{31277}\u{31278}\u{31279}\u{3127A}\u{3127B}\u{3127C}\u{3127D}\u{3127E}\u{3127F}\u{31280}\u{31281}\u{31282}\u{31283}\u{31284}\u{31285}\u{31286}\u{31287}\u{31288}\u{31289}\u{3128A}\u{3128B}\u{3128C}\u{3128D}\u{3128E}\u{3128F}\u{31290}\u{31291}\u{31292}\u{31293}\u{31294}\u{31295}\u{31296}\u{31297}\u{31298}\u{31299}\u{3129A}\u{3129B}\u{3129C}\u{3129D}\u{3129E}\u{3129F}\u{312A0}\u{312A1}\u{312A2}\u{312A3}\u{312A4}\u{312A5}\u{312A6}\u{312A7}\u{312A8}\u{312A9}\u{312AA}\u{312AB}\u{312AC}\u{312AD}\u{312AE}\u{312AF}\u{312B0}\u{312B1}\u{312B2}\u{312B3}\u{312B4}\u{312B5}\u{312B6}\u{312B7}\u{312B8}\u{312B9}\u{312BA}\u{312BB}\u{312BC}\u{312BD}\u{312BE}\u{312BF}\u{312C0}\u{312C1}\u{312C2}\u{312C3}\u{312C4}\u{312C5}\u{312C6}\u{312C7}\u{312C8}\u{312C9}\u{312CA}\u{312CB}\u{312CC}\u{312CD}\u{312CE}\u{312CF}\u{312D0}\u{312D1}\u{312D2}\u{312D3}\u{312D4}\u{312D5}\u{312D6}\u{312D7}\u{312D8}\u{312D9}\u{312DA}\u{312DB}\u{312DC}\u{312DD}\u{312DE}\u{312DF}\u{312E0}\u{312E1}\u{312E2}\u{312E3}\u{312E4}\u{312E5}\u{312E6}\u{312E7}\u{312E8}\u{312E9}\u{312EA}\u{312EB}\u{312EC}\u{312ED}\u{312EE}\u{312EF}\u{312F0}\u{312F1}\u{312F2}\u{312F3}\u{312F4}\u{312F5}\u{312F6}\u{312F7}\u{312F8}\u{312F9}\u{312FA}\u{312FB}\u{312FC}\u{312FD}\u{312FE}\u{312FF}\u{31300}\u{31301}\u{31302}\u{31303}\u{31304}\u{31305}\u{31306}\u{31307}\u{31308}\u{31309}\u{3130A}\u{3130B}\u{3130C}\u{3130D}\u{3130E}\u{3130F}\u{31310}\u{31311}\u{31312}\u{31313}\u{31314}\u{31315}\u{31316}\u{31317}\u{31318}\u{31319}\u{3131A}\u{3131B}\u{3131C}\u{3131D}\u{3131E}\u{3131F}\u{31320}\u{31321}\u{31322}\u{31323}\u{31324}\u{31325}\u{31326}\u{31327}\u{31328}\u{31329}\u{3132A}\u{3132B}\u{3132C}\u{3132D}\u{3132E}\u{3132F}\u{31330}\u{31331}\u{31332}\u{31333}\u{31334}\u{31335}\u{31336}\u{31337}\u{31338}\u{31339}\u{3133A}\u{3133B}\u{3133C}\u{3133D}\u{3133E}\u{3133F}\u{31340}\u{31341}\u{31342}\u{31343}\u{31344}\u{31345}\u{31346}\u{31347}\u{31348}\u{31349}\u{3134A}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-class.js new file mode 100644 index 000000000000..fd243161452a --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v13.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ࢾࢿࣀࣁࣂࣃࣄࣅࣆࣇഄㆻㆼㆽㆾㆿ䶶䶷䶸䶹䶺䶻䶼䶽䶾䶿鿰鿱鿲鿳鿴鿵鿶鿷鿸鿹鿺鿻鿼ꟇꟈꟉꟊꟵꟶꭨꭩ𐺀𐺁𐺂𐺃𐺄𐺅𐺆𐺇𐺈𐺉𐺊𐺋𐺌𐺍𐺎𐺏𐺐𐺑𐺒𐺓𐺔𐺕𐺖𐺗𐺘𐺙𐺚𐺛𐺜𐺝𐺞𐺟𐺠𐺡𐺢𐺣𐺤𐺥𐺦𐺧𐺨𐺩𐺰𐺱𐾰𐾱𐾲𐾳𐾴𐾵𐾶𐾷𐾸𐾹𐾺𐾻𐾼𐾽𐾾𐾿𐿀𐿁𐿂𐿃𐿄𑅇𑑠𑑡𑤀𑤁𑤂𑤃𑤄𑤅𑤆𑤉𑤌𑤍𑤎𑤏𑤐𑤑𑤒𑤓𑤕𑤖𑤘𑤙𑤚𑤛𑤜𑤝𑤞𑤟𑤠𑤡𑤢𑤣𑤤𑤥𑤦𑤧𑤨𑤩𑤪𑤫𑤬𑤭𑤮𑤯𑤿𑥁𑾰𘫳𘫴𘫵𘫶𘫷𘫸𘫹𘫺𘫻𘫼𘫽𘫾𘫿𘬀𘬁𘬂𘬃𘬄𘬅𘬆𘬇𘬈𘬉𘬊𘬋𘬌𘬍𘬎𘬏𘬐𘬑𘬒𘬓𘬔𘬕𘬖𘬗𘬘𘬙𘬚𘬛𘬜𘬝𘬞𘬟𘬠𘬡𘬢𘬣𘬤𘬥𘬦𘬧𘬨𘬩𘬪𘬫𘬬𘬭𘬮𘬯𘬰𘬱𘬲𘬳𘬴𘬵𘬶𘬷𘬸𘬹𘬺𘬻𘬼𘬽𘬾𘬿𘭀𘭁𘭂𘭃𘭄𘭅𘭆𘭇𘭈𘭉𘭊𘭋𘭌𘭍𘭎𘭏𘭐𘭑𘭒𘭓𘭔𘭕𘭖𘭗𘭘𘭙𘭚𘭛𘭜𘭝𘭞𘭟𘭠𘭡𘭢𘭣𘭤𘭥𘭦𘭧𘭨𘭩𘭪𘭫𘭬𘭭𘭮𘭯𘭰𘭱𘭲𘭳𘭴𘭵𘭶𘭷𘭸𘭹𘭺𘭻𘭼𘭽𘭾𘭿𘮀𘮁𘮂𘮃𘮄𘮅𘮆𘮇𘮈𘮉𘮊𘮋𘮌𘮍𘮎𘮏𘮐𘮑𘮒𘮓𘮔𘮕𘮖𘮗𘮘𘮙𘮚𘮛𘮜𘮝𘮞𘮟𘮠𘮡𘮢𘮣𘮤𘮥𘮦𘮧𘮨𘮩𘮪𘮫𘮬𘮭𘮮𘮯𘮰𘮱𘮲𘮳𘮴𘮵𘮶𘮷𘮸𘮹𘮺𘮻𘮼𘮽𘮾𘮿𘯀𘯁𘯂𘯃𘯄𘯅𘯆𘯇𘯈𘯉𘯊𘯋𘯌𘯍𘯎𘯏𘯐𘯑𘯒𘯓𘯔𘯕𘯖𘯗𘯘𘯙𘯚𘯛𘯜𘯝𘯞𘯟𘯠𘯡𘯢𘯣𘯤𘯥𘯦𘯧𘯨𘯩𘯪𘯫𘯬𘯭𘯮𘯯𘯰𘯱𘯲𘯳𘯴𘯵𘯶𘯷𘯸𘯹𘯺𘯻𘯼𘯽𘯾𘯿𘰀𘰁𘰂𘰃𘰄𘰅𘰆𘰇𘰈𘰉𘰊𘰋𘰌𘰍𘰎𘰏𘰐𘰑𘰒𘰓𘰔𘰕𘰖𘰗𘰘𘰙𘰚𘰛𘰜𘰝𘰞𘰟𘰠𘰡𘰢𘰣𘰤𘰥𘰦𘰧𘰨𘰩𘰪𘰫𘰬𘰭𘰮𘰯𘰰𘰱𘰲𘰳𘰴𘰵𘰶𘰷𘰸𘰹𘰺𘰻𘰼𘰽𘰾𘰿𘱀𘱁𘱂𘱃𘱄𘱅𘱆𘱇𘱈𘱉𘱊𘱋𘱌𘱍𘱎𘱏𘱐𘱑𘱒𘱓𘱔𘱕𘱖𘱗𘱘𘱙𘱚𘱛𘱜𘱝𘱞𘱟𘱠𘱡𘱢𘱣𘱤𘱥𘱦𘱧𘱨𘱩𘱪𘱫𘱬𘱭𘱮𘱯𘱰𘱱𘱲𘱳𘱴𘱵𘱶𘱷𘱸𘱹𘱺𘱻𘱼𘱽𘱾𘱿𘲀𘲁𘲂𘲃𘲄𘲅𘲆𘲇𘲈𘲉𘲊𘲋𘲌𘲍𘲎𘲏𘲐𘲑𘲒𘲓𘲔𘲕𘲖𘲗𘲘𘲙𘲚𘲛𘲜𘲝𘲞𘲟𘲠𘲡𘲢𘲣𘲤𘲥𘲦𘲧𘲨𘲩𘲪𘲫𘲬𘲭𘲮𘲯𘲰𘲱𘲲𘲳𘲴𘲵𘲶𘲷𘲸𘲹𘲺𘲻𘲼𘲽𘲾𘲿𘳀𘳁𘳂𘳃𘳄𘳅𘳆𘳇𘳈𘳉𘳊𘳋𘳌𘳍𘳎𘳏𘳐𘳑𘳒𘳓𘳔𘳕𘴀𘴁𘴂𘴃𘴄𘴅𘴆𘴇𘴈𪛗𪛘𪛙𪛚𪛛𪛜𪛝𰀀𰀁𰀂𰀃𰀄𰀅𰀆𰀇𰀈𰀉𰀊𰀋𰀌𰀍𰀎𰀏𰀐𰀑𰀒𰀓𰀔𰀕𰀖𰀗𰀘𰀙𰀚𰀛𰀜𰀝𰀞𰀟𰀠𰀡𰀢𰀣𰀤𰀥𰀦𰀧𰀨𰀩𰀪𰀫𰀬𰀭𰀮𰀯𰀰𰀱𰀲𰀳𰀴𰀵𰀶𰀷𰀸𰀹𰀺𰀻𰀼𰀽𰀾𰀿𰁀𰁁𰁂𰁃𰁄𰁅𰁆𰁇𰁈𰁉𰁊𰁋𰁌𰁍𰁎𰁏𰁐𰁑𰁒𰁓𰁔𰁕𰁖𰁗𰁘𰁙𰁚𰁛𰁜𰁝𰁞𰁟𰁠𰁡𰁢𰁣𰁤𰁥𰁦𰁧𰁨𰁩𰁪𰁫𰁬𰁭𰁮𰁯𰁰𰁱𰁲𰁳𰁴𰁵𰁶𰁷𰁸𰁹𰁺𰁻𰁼𰁽𰁾𰁿𰂀𰂁𰂂𰂃𰂄𰂅𰂆𰂇𰂈𰂉𰂊𰂋𰂌𰂍𰂎𰂏𰂐𰂑𰂒𰂓𰂔𰂕𰂖𰂗𰂘𰂙𰂚𰂛𰂜𰂝𰂞𰂟𰂠𰂡𰂢𰂣𰂤𰂥𰂦𰂧𰂨𰂩𰂪𰂫𰂬𰂭𰂮𰂯𰂰𰂱𰂲𰂳𰂴𰂵𰂶𰂷𰂸𰂹𰂺𰂻𰂼𰂽𰂾𰂿𰃀𰃁𰃂𰃃𰃄𰃅𰃆𰃇𰃈𰃉𰃊𰃋𰃌𰃍𰃎𰃏𰃐𰃑𰃒𰃓𰃔𰃕𰃖𰃗𰃘𰃙𰃚𰃛𰃜𰃝𰃞𰃟𰃠𰃡𰃢𰃣𰃤𰃥𰃦𰃧𰃨𰃩𰃪𰃫𰃬𰃭𰃮𰃯𰃰𰃱𰃲𰃳𰃴𰃵𰃶𰃷𰃸𰃹𰃺𰃻𰃼𰃽𰃾𰃿𰄀𰄁𰄂𰄃𰄄𰄅𰄆𰄇𰄈𰄉𰄊𰄋𰄌𰄍𰄎𰄏𰄐𰄑𰄒𰄓𰄔𰄕𰄖𰄗𰄘𰄙𰄚𰄛𰄜𰄝𰄞𰄟𰄠𰄡𰄢𰄣𰄤𰄥𰄦𰄧𰄨𰄩𰄪𰄫𰄬𰄭𰄮𰄯𰄰𰄱𰄲𰄳𰄴𰄵𰄶𰄷𰄸𰄹𰄺𰄻𰄼𰄽𰄾𰄿𰅀𰅁𰅂𰅃𰅄𰅅𰅆𰅇𰅈𰅉𰅊𰅋𰅌𰅍𰅎𰅏𰅐𰅑𰅒𰅓𰅔𰅕𰅖𰅗𰅘𰅙𰅚𰅛𰅜𰅝𰅞𰅟𰅠𰅡𰅢𰅣𰅤𰅥𰅦𰅧𰅨𰅩𰅪𰅫𰅬𰅭𰅮𰅯𰅰𰅱𰅲𰅳𰅴𰅵𰅶𰅷𰅸𰅹𰅺𰅻𰅼𰅽𰅾𰅿𰆀𰆁𰆂𰆃𰆄𰆅𰆆𰆇𰆈𰆉𰆊𰆋𰆌𰆍𰆎𰆏𰆐𰆑𰆒𰆓𰆔𰆕𰆖𰆗𰆘𰆙𰆚𰆛𰆜𰆝𰆞𰆟𰆠𰆡𰆢𰆣𰆤𰆥𰆦𰆧𰆨𰆩𰆪𰆫𰆬𰆭𰆮𰆯𰆰𰆱𰆲𰆳𰆴𰆵𰆶𰆷𰆸𰆹𰆺𰆻𰆼𰆽𰆾𰆿𰇀𰇁𰇂𰇃𰇄𰇅𰇆𰇇𰇈𰇉𰇊𰇋𰇌𰇍𰇎𰇏𰇐𰇑𰇒𰇓𰇔𰇕𰇖𰇗𰇘𰇙𰇚𰇛𰇜𰇝𰇞𰇟𰇠𰇡𰇢𰇣𰇤𰇥𰇦𰇧𰇨𰇩𰇪𰇫𰇬𰇭𰇮𰇯𰇰𰇱𰇲𰇳𰇴𰇵𰇶𰇷𰇸𰇹𰇺𰇻𰇼𰇽𰇾𰇿𰈀𰈁𰈂𰈃𰈄𰈅𰈆𰈇𰈈𰈉𰈊𰈋𰈌𰈍𰈎𰈏𰈐𰈑𰈒𰈓𰈔𰈕𰈖𰈗𰈘𰈙𰈚𰈛𰈜𰈝𰈞𰈟𰈠𰈡𰈢𰈣𰈤𰈥𰈦𰈧𰈨𰈩𰈪𰈫𰈬𰈭𰈮𰈯𰈰𰈱𰈲𰈳𰈴𰈵𰈶𰈷𰈸𰈹𰈺𰈻𰈼𰈽𰈾𰈿𰉀𰉁𰉂𰉃𰉄𰉅𰉆𰉇𰉈𰉉𰉊𰉋𰉌𰉍𰉎𰉏𰉐𰉑𰉒𰉓𰉔𰉕𰉖𰉗𰉘𰉙𰉚𰉛𰉜𰉝𰉞𰉟𰉠𰉡𰉢𰉣𰉤𰉥𰉦𰉧𰉨𰉩𰉪𰉫𰉬𰉭𰉮𰉯𰉰𰉱𰉲𰉳𰉴𰉵𰉶𰉷𰉸𰉹𰉺𰉻𰉼𰉽𰉾𰉿𰊀𰊁𰊂𰊃𰊄𰊅𰊆𰊇𰊈𰊉𰊊𰊋𰊌𰊍𰊎𰊏𰊐𰊑𰊒𰊓𰊔𰊕𰊖𰊗𰊘𰊙𰊚𰊛𰊜𰊝𰊞𰊟𰊠𰊡𰊢𰊣𰊤𰊥𰊦𰊧𰊨𰊩𰊪𰊫𰊬𰊭𰊮𰊯𰊰𰊱𰊲𰊳𰊴𰊵𰊶𰊷𰊸𰊹𰊺𰊻𰊼𰊽𰊾𰊿𰋀𰋁𰋂𰋃𰋄𰋅𰋆𰋇𰋈𰋉𰋊𰋋𰋌𰋍𰋎𰋏𰋐𰋑𰋒𰋓𰋔𰋕𰋖𰋗𰋘𰋙𰋚𰋛𰋜𰋝𰋞𰋟𰋠𰋡𰋢𰋣𰋤𰋥𰋦𰋧𰋨𰋩𰋪𰋫𰋬𰋭𰋮𰋯𰋰𰋱𰋲𰋳𰋴𰋵𰋶𰋷𰋸𰋹𰋺𰋻𰋼𰋽𰋾𰋿𰌀𰌁𰌂𰌃𰌄𰌅𰌆𰌇𰌈𰌉𰌊𰌋𰌌𰌍𰌎𰌏𰌐𰌑𰌒𰌓𰌔𰌕𰌖𰌗𰌘𰌙𰌚𰌛𰌜𰌝𰌞𰌟𰌠𰌡𰌢𰌣𰌤𰌥𰌦𰌧𰌨𰌩𰌪𰌫𰌬𰌭𰌮𰌯𰌰𰌱𰌲𰌳𰌴𰌵𰌶𰌷𰌸𰌹𰌺𰌻𰌼𰌽𰌾𰌿𰍀𰍁𰍂𰍃𰍄𰍅𰍆𰍇𰍈𰍉𰍊𰍋𰍌𰍍𰍎𰍏𰍐𰍑𰍒𰍓𰍔𰍕𰍖𰍗𰍘𰍙𰍚𰍛𰍜𰍝𰍞𰍟𰍠𰍡𰍢𰍣𰍤𰍥𰍦𰍧𰍨𰍩𰍪𰍫𰍬𰍭𰍮𰍯𰍰𰍱𰍲𰍳𰍴𰍵𰍶𰍷𰍸𰍹𰍺𰍻𰍼𰍽𰍾𰍿𰎀𰎁𰎂𰎃𰎄𰎅𰎆𰎇𰎈𰎉𰎊𰎋𰎌𰎍𰎎𰎏𰎐𰎑𰎒𰎓𰎔𰎕𰎖𰎗𰎘𰎙𰎚𰎛𰎜𰎝𰎞𰎟𰎠𰎡𰎢𰎣𰎤𰎥𰎦𰎧𰎨𰎩𰎪𰎫𰎬𰎭𰎮𰎯𰎰𰎱𰎲𰎳𰎴𰎵𰎶𰎷𰎸𰎹𰎺𰎻𰎼𰎽𰎾𰎿𰏀𰏁𰏂𰏃𰏄𰏅𰏆𰏇𰏈𰏉𰏊𰏋𰏌𰏍𰏎𰏏𰏐𰏑𰏒𰏓𰏔𰏕𰏖𰏗𰏘𰏙𰏚𰏛𰏜𰏝𰏞𰏟𰏠𰏡𰏢𰏣𰏤𰏥𰏦𰏧𰏨𰏩𰏪𰏫𰏬𰏭𰏮𰏯𰏰𰏱𰏲𰏳𰏴𰏵𰏶𰏷𰏸𰏹𰏺𰏻𰏼𰏽𰏾𰏿𰐀𰐁𰐂𰐃𰐄𰐅𰐆𰐇𰐈𰐉𰐊𰐋𰐌𰐍𰐎𰐏𰐐𰐑𰐒𰐓𰐔𰐕𰐖𰐗𰐘𰐙𰐚𰐛𰐜𰐝𰐞𰐟𰐠𰐡𰐢𰐣𰐤𰐥𰐦𰐧𰐨𰐩𰐪𰐫𰐬𰐭𰐮𰐯𰐰𰐱𰐲𰐳𰐴𰐵𰐶𰐷𰐸𰐹𰐺𰐻𰐼𰐽𰐾𰐿𰑀𰑁𰑂𰑃𰑄𰑅𰑆𰑇𰑈𰑉𰑊𰑋𰑌𰑍𰑎𰑏𰑐𰑑𰑒𰑓𰑔𰑕𰑖𰑗𰑘𰑙𰑚𰑛𰑜𰑝𰑞𰑟𰑠𰑡𰑢𰑣𰑤𰑥𰑦𰑧𰑨𰑩𰑪𰑫𰑬𰑭𰑮𰑯𰑰𰑱𰑲𰑳𰑴𰑵𰑶𰑷𰑸𰑹𰑺𰑻𰑼𰑽𰑾𰑿𰒀𰒁𰒂𰒃𰒄𰒅𰒆𰒇𰒈𰒉𰒊𰒋𰒌𰒍𰒎𰒏𰒐𰒑𰒒𰒓𰒔𰒕𰒖𰒗𰒘𰒙𰒚𰒛𰒜𰒝𰒞𰒟𰒠𰒡𰒢𰒣𰒤𰒥𰒦𰒧𰒨𰒩𰒪𰒫𰒬𰒭𰒮𰒯𰒰𰒱𰒲𰒳𰒴𰒵𰒶𰒷𰒸𰒹𰒺𰒻𰒼𰒽𰒾𰒿𰓀𰓁𰓂𰓃𰓄𰓅𰓆𰓇𰓈𰓉𰓊𰓋𰓌𰓍𰓎𰓏𰓐𰓑𰓒𰓓𰓔𰓕𰓖𰓗𰓘𰓙𰓚𰓛𰓜𰓝𰓞𰓟𰓠𰓡𰓢𰓣𰓤𰓥𰓦𰓧𰓨𰓩𰓪𰓫𰓬𰓭𰓮𰓯𰓰𰓱𰓲𰓳𰓴𰓵𰓶𰓷𰓸𰓹𰓺𰓻𰓼𰓽𰓾𰓿𰔀𰔁𰔂𰔃𰔄𰔅𰔆𰔇𰔈𰔉𰔊𰔋𰔌𰔍𰔎𰔏𰔐𰔑𰔒𰔓𰔔𰔕𰔖𰔗𰔘𰔙𰔚𰔛𰔜𰔝𰔞𰔟𰔠𰔡𰔢𰔣𰔤𰔥𰔦𰔧𰔨𰔩𰔪𰔫𰔬𰔭𰔮𰔯𰔰𰔱𰔲𰔳𰔴𰔵𰔶𰔷𰔸𰔹𰔺𰔻𰔼𰔽𰔾𰔿𰕀𰕁𰕂𰕃𰕄𰕅𰕆𰕇𰕈𰕉𰕊𰕋𰕌𰕍𰕎𰕏𰕐𰕑𰕒𰕓𰕔𰕕𰕖𰕗𰕘𰕙𰕚𰕛𰕜𰕝𰕞𰕟𰕠𰕡𰕢𰕣𰕤𰕥𰕦𰕧𰕨𰕩𰕪𰕫𰕬𰕭𰕮𰕯𰕰𰕱𰕲𰕳𰕴𰕵𰕶𰕷𰕸𰕹𰕺𰕻𰕼𰕽𰕾𰕿𰖀𰖁𰖂𰖃𰖄𰖅𰖆𰖇𰖈𰖉𰖊𰖋𰖌𰖍𰖎𰖏𰖐𰖑𰖒𰖓𰖔𰖕𰖖𰖗𰖘𰖙𰖚𰖛𰖜𰖝𰖞𰖟𰖠𰖡𰖢𰖣𰖤𰖥𰖦𰖧𰖨𰖩𰖪𰖫𰖬𰖭𰖮𰖯𰖰𰖱𰖲𰖳𰖴𰖵𰖶𰖷𰖸𰖹𰖺𰖻𰖼𰖽𰖾𰖿𰗀𰗁𰗂𰗃𰗄𰗅𰗆𰗇𰗈𰗉𰗊𰗋𰗌𰗍𰗎𰗏𰗐𰗑𰗒𰗓𰗔𰗕𰗖𰗗𰗘𰗙𰗚𰗛𰗜𰗝𰗞𰗟𰗠𰗡𰗢𰗣𰗤𰗥𰗦𰗧𰗨𰗩𰗪𰗫𰗬𰗭𰗮𰗯𰗰𰗱𰗲𰗳𰗴𰗵𰗶𰗷𰗸𰗹𰗺𰗻𰗼𰗽𰗾𰗿𰘀𰘁𰘂𰘃𰘄𰘅𰘆𰘇𰘈𰘉𰘊𰘋𰘌𰘍𰘎𰘏𰘐𰘑𰘒𰘓𰘔𰘕𰘖𰘗𰘘𰘙𰘚𰘛𰘜𰘝𰘞𰘟𰘠𰘡𰘢𰘣𰘤𰘥𰘦𰘧𰘨𰘩𰘪𰘫𰘬𰘭𰘮𰘯𰘰𰘱𰘲𰘳𰘴𰘵𰘶𰘷𰘸𰘹𰘺𰘻𰘼𰘽𰘾𰘿𰙀𰙁𰙂𰙃𰙄𰙅𰙆𰙇𰙈𰙉𰙊𰙋𰙌𰙍𰙎𰙏𰙐𰙑𰙒𰙓𰙔𰙕𰙖𰙗𰙘𰙙𰙚𰙛𰙜𰙝𰙞𰙟𰙠𰙡𰙢𰙣𰙤𰙥𰙦𰙧𰙨𰙩𰙪𰙫𰙬𰙭𰙮𰙯𰙰𰙱𰙲𰙳𰙴𰙵𰙶𰙷𰙸𰙹𰙺𰙻𰙼𰙽𰙾𰙿𰚀𰚁𰚂𰚃𰚄𰚅𰚆𰚇𰚈𰚉𰚊𰚋𰚌𰚍𰚎𰚏𰚐𰚑𰚒𰚓𰚔𰚕𰚖𰚗𰚘𰚙𰚚𰚛𰚜𰚝𰚞𰚟𰚠𰚡𰚢𰚣𰚤𰚥𰚦𰚧𰚨𰚩𰚪𰚫𰚬𰚭𰚮𰚯𰚰𰚱𰚲𰚳𰚴𰚵𰚶𰚷𰚸𰚹𰚺𰚻𰚼𰚽𰚾𰚿𰛀𰛁𰛂𰛃𰛄𰛅𰛆𰛇𰛈𰛉𰛊𰛋𰛌𰛍𰛎𰛏𰛐𰛑𰛒𰛓𰛔𰛕𰛖𰛗𰛘𰛙𰛚𰛛𰛜𰛝𰛞𰛟𰛠𰛡𰛢𰛣𰛤𰛥𰛦𰛧𰛨𰛩𰛪𰛫𰛬𰛭𰛮𰛯𰛰𰛱𰛲𰛳𰛴𰛵𰛶𰛷𰛸𰛹𰛺𰛻𰛼𰛽𰛾𰛿𰜀𰜁𰜂𰜃𰜄𰜅𰜆𰜇𰜈𰜉𰜊𰜋𰜌𰜍𰜎𰜏𰜐𰜑𰜒𰜓𰜔𰜕𰜖𰜗𰜘𰜙𰜚𰜛𰜜𰜝𰜞𰜟𰜠𰜡𰜢𰜣𰜤𰜥𰜦𰜧𰜨𰜩𰜪𰜫𰜬𰜭𰜮𰜯𰜰𰜱𰜲𰜳𰜴𰜵𰜶𰜷𰜸𰜹𰜺𰜻𰜼𰜽𰜾𰜿𰝀𰝁𰝂𰝃𰝄𰝅𰝆𰝇𰝈𰝉𰝊𰝋𰝌𰝍𰝎𰝏𰝐𰝑𰝒𰝓𰝔𰝕𰝖𰝗𰝘𰝙𰝚𰝛𰝜𰝝𰝞𰝟𰝠𰝡𰝢𰝣𰝤𰝥𰝦𰝧𰝨𰝩𰝪𰝫𰝬𰝭𰝮𰝯𰝰𰝱𰝲𰝳𰝴𰝵𰝶𰝷𰝸𰝹𰝺𰝻𰝼𰝽𰝾𰝿𰞀𰞁𰞂𰞃𰞄𰞅𰞆𰞇𰞈𰞉𰞊𰞋𰞌𰞍𰞎𰞏𰞐𰞑𰞒𰞓𰞔𰞕𰞖𰞗𰞘𰞙𰞚𰞛𰞜𰞝𰞞𰞟𰞠𰞡𰞢𰞣𰞤𰞥𰞦𰞧𰞨𰞩𰞪𰞫𰞬𰞭𰞮𰞯𰞰𰞱𰞲𰞳𰞴𰞵𰞶𰞷𰞸𰞹𰞺𰞻𰞼𰞽𰞾𰞿𰟀𰟁𰟂𰟃𰟄𰟅𰟆𰟇𰟈𰟉𰟊𰟋𰟌𰟍𰟎𰟏𰟐𰟑𰟒𰟓𰟔𰟕𰟖𰟗𰟘𰟙𰟚𰟛𰟜𰟝𰟞𰟟𰟠𰟡𰟢𰟣𰟤𰟥𰟦𰟧𰟨𰟩𰟪𰟫𰟬𰟭𰟮𰟯𰟰𰟱𰟲𰟳𰟴𰟵𰟶𰟷𰟸𰟹𰟺𰟻𰟼𰟽𰟾𰟿𰠀𰠁𰠂𰠃𰠄𰠅𰠆𰠇𰠈𰠉𰠊𰠋𰠌𰠍𰠎𰠏𰠐𰠑𰠒𰠓𰠔𰠕𰠖𰠗𰠘𰠙𰠚𰠛𰠜𰠝𰠞𰠟𰠠𰠡𰠢𰠣𰠤𰠥𰠦𰠧𰠨𰠩𰠪𰠫𰠬𰠭𰠮𰠯𰠰𰠱𰠲𰠳𰠴𰠵𰠶𰠷𰠸𰠹𰠺𰠻𰠼𰠽𰠾𰠿𰡀𰡁𰡂𰡃𰡄𰡅𰡆𰡇𰡈𰡉𰡊𰡋𰡌𰡍𰡎𰡏𰡐𰡑𰡒𰡓𰡔𰡕𰡖𰡗𰡘𰡙𰡚𰡛𰡜𰡝𰡞𰡟𰡠𰡡𰡢𰡣𰡤𰡥𰡦𰡧𰡨𰡩𰡪𰡫𰡬𰡭𰡮𰡯𰡰𰡱𰡲𰡳𰡴𰡵𰡶𰡷𰡸𰡹𰡺𰡻𰡼𰡽𰡾𰡿𰢀𰢁𰢂𰢃𰢄𰢅𰢆𰢇𰢈𰢉𰢊𰢋𰢌𰢍𰢎𰢏𰢐𰢑𰢒𰢓𰢔𰢕𰢖𰢗𰢘𰢙𰢚𰢛𰢜𰢝𰢞𰢟𰢠𰢡𰢢𰢣𰢤𰢥𰢦𰢧𰢨𰢩𰢪𰢫𰢬𰢭𰢮𰢯𰢰𰢱𰢲𰢳𰢴𰢵𰢶𰢷𰢸𰢹𰢺𰢻𰢼𰢽𰢾𰢿𰣀𰣁𰣂𰣃𰣄𰣅𰣆𰣇𰣈𰣉𰣊𰣋𰣌𰣍𰣎𰣏𰣐𰣑𰣒𰣓𰣔𰣕𰣖𰣗𰣘𰣙𰣚𰣛𰣜𰣝𰣞𰣟𰣠𰣡𰣢𰣣𰣤𰣥𰣦𰣧𰣨𰣩𰣪𰣫𰣬𰣭𰣮𰣯𰣰𰣱𰣲𰣳𰣴𰣵𰣶𰣷𰣸𰣹𰣺𰣻𰣼𰣽𰣾𰣿𰤀𰤁𰤂𰤃𰤄𰤅𰤆𰤇𰤈𰤉𰤊𰤋𰤌𰤍𰤎𰤏𰤐𰤑𰤒𰤓𰤔𰤕𰤖𰤗𰤘𰤙𰤚𰤛𰤜𰤝𰤞𰤟𰤠𰤡𰤢𰤣𰤤𰤥𰤦𰤧𰤨𰤩𰤪𰤫𰤬𰤭𰤮𰤯𰤰𰤱𰤲𰤳𰤴𰤵𰤶𰤷𰤸𰤹𰤺𰤻𰤼𰤽𰤾𰤿𰥀𰥁𰥂𰥃𰥄𰥅𰥆𰥇𰥈𰥉𰥊𰥋𰥌𰥍𰥎𰥏𰥐𰥑𰥒𰥓𰥔𰥕𰥖𰥗𰥘𰥙𰥚𰥛𰥜𰥝𰥞𰥟𰥠𰥡𰥢𰥣𰥤𰥥𰥦𰥧𰥨𰥩𰥪𰥫𰥬𰥭𰥮𰥯𰥰𰥱𰥲𰥳𰥴𰥵𰥶𰥷𰥸𰥹𰥺𰥻𰥼𰥽𰥾𰥿𰦀𰦁𰦂𰦃𰦄𰦅𰦆𰦇𰦈𰦉𰦊𰦋𰦌𰦍𰦎𰦏𰦐𰦑𰦒𰦓𰦔𰦕𰦖𰦗𰦘𰦙𰦚𰦛𰦜𰦝𰦞𰦟𰦠𰦡𰦢𰦣𰦤𰦥𰦦𰦧𰦨𰦩𰦪𰦫𰦬𰦭𰦮𰦯𰦰𰦱𰦲𰦳𰦴𰦵𰦶𰦷𰦸𰦹𰦺𰦻𰦼𰦽𰦾𰦿𰧀𰧁𰧂𰧃𰧄𰧅𰧆𰧇𰧈𰧉𰧊𰧋𰧌𰧍𰧎𰧏𰧐𰧑𰧒𰧓𰧔𰧕𰧖𰧗𰧘𰧙𰧚𰧛𰧜𰧝𰧞𰧟𰧠𰧡𰧢𰧣𰧤𰧥𰧦𰧧𰧨𰧩𰧪𰧫𰧬𰧭𰧮𰧯𰧰𰧱𰧲𰧳𰧴𰧵𰧶𰧷𰧸𰧹𰧺𰧻𰧼𰧽𰧾𰧿𰨀𰨁𰨂𰨃𰨄𰨅𰨆𰨇𰨈𰨉𰨊𰨋𰨌𰨍𰨎𰨏𰨐𰨑𰨒𰨓𰨔𰨕𰨖𰨗𰨘𰨙𰨚𰨛𰨜𰨝𰨞𰨟𰨠𰨡𰨢𰨣𰨤𰨥𰨦𰨧𰨨𰨩𰨪𰨫𰨬𰨭𰨮𰨯𰨰𰨱𰨲𰨳𰨴𰨵𰨶𰨷𰨸𰨹𰨺𰨻𰨼𰨽𰨾𰨿𰩀𰩁𰩂𰩃𰩄𰩅𰩆𰩇𰩈𰩉𰩊𰩋𰩌𰩍𰩎𰩏𰩐𰩑𰩒𰩓𰩔𰩕𰩖𰩗𰩘𰩙𰩚𰩛𰩜𰩝𰩞𰩟𰩠𰩡𰩢𰩣𰩤𰩥𰩦𰩧𰩨𰩩𰩪𰩫𰩬𰩭𰩮𰩯𰩰𰩱𰩲𰩳𰩴𰩵𰩶𰩷𰩸𰩹𰩺𰩻𰩼𰩽𰩾𰩿𰪀𰪁𰪂𰪃𰪄𰪅𰪆𰪇𰪈𰪉𰪊𰪋𰪌𰪍𰪎𰪏𰪐𰪑𰪒𰪓𰪔𰪕𰪖𰪗𰪘𰪙𰪚𰪛𰪜𰪝𰪞𰪟𰪠𰪡𰪢𰪣𰪤𰪥𰪦𰪧𰪨𰪩𰪪𰪫𰪬𰪭𰪮𰪯𰪰𰪱𰪲𰪳𰪴𰪵𰪶𰪷𰪸𰪹𰪺𰪻𰪼𰪽𰪾𰪿𰫀𰫁𰫂𰫃𰫄𰫅𰫆𰫇𰫈𰫉𰫊𰫋𰫌𰫍𰫎𰫏𰫐𰫑𰫒𰫓𰫔𰫕𰫖𰫗𰫘𰫙𰫚𰫛𰫜𰫝𰫞𰫟𰫠𰫡𰫢𰫣𰫤𰫥𰫦𰫧𰫨𰫩𰫪𰫫𰫬𰫭𰫮𰫯𰫰𰫱𰫲𰫳𰫴𰫵𰫶𰫷𰫸𰫹𰫺𰫻𰫼𰫽𰫾𰫿𰬀𰬁𰬂𰬃𰬄𰬅𰬆𰬇𰬈𰬉𰬊𰬋𰬌𰬍𰬎𰬏𰬐𰬑𰬒𰬓𰬔𰬕𰬖𰬗𰬘𰬙𰬚𰬛𰬜𰬝𰬞𰬟𰬠𰬡𰬢𰬣𰬤𰬥𰬦𰬧𰬨𰬩𰬪𰬫𰬬𰬭𰬮𰬯𰬰𰬱𰬲𰬳𰬴𰬵𰬶𰬷𰬸𰬹𰬺𰬻𰬼𰬽𰬾𰬿𰭀𰭁𰭂𰭃𰭄𰭅𰭆𰭇𰭈𰭉𰭊𰭋𰭌𰭍𰭎𰭏𰭐𰭑𰭒𰭓𰭔𰭕𰭖𰭗𰭘𰭙𰭚𰭛𰭜𰭝𰭞𰭟𰭠𰭡𰭢𰭣𰭤𰭥𰭦𰭧𰭨𰭩𰭪𰭫𰭬𰭭𰭮𰭯𰭰𰭱𰭲𰭳𰭴𰭵𰭶𰭷𰭸𰭹𰭺𰭻𰭼𰭽𰭾𰭿𰮀𰮁𰮂𰮃𰮄𰮅𰮆𰮇𰮈𰮉𰮊𰮋𰮌𰮍𰮎𰮏𰮐𰮑𰮒𰮓𰮔𰮕𰮖𰮗𰮘𰮙𰮚𰮛𰮜𰮝𰮞𰮟𰮠𰮡𰮢𰮣𰮤𰮥𰮦𰮧𰮨𰮩𰮪𰮫𰮬𰮭𰮮𰮯𰮰𰮱𰮲𰮳𰮴𰮵𰮶𰮷𰮸𰮹𰮺𰮻𰮼𰮽𰮾𰮿𰯀𰯁𰯂𰯃𰯄𰯅𰯆𰯇𰯈𰯉𰯊𰯋𰯌𰯍𰯎𰯏𰯐𰯑𰯒𰯓𰯔𰯕𰯖𰯗𰯘𰯙𰯚𰯛𰯜𰯝𰯞𰯟𰯠𰯡𰯢𰯣𰯤𰯥𰯦𰯧𰯨𰯩𰯪𰯫𰯬𰯭𰯮𰯯𰯰𰯱𰯲𰯳𰯴𰯵𰯶𰯷𰯸𰯹𰯺𰯻𰯼𰯽𰯾𰯿𰰀𰰁𰰂𰰃𰰄𰰅𰰆𰰇𰰈𰰉𰰊𰰋𰰌𰰍𰰎𰰏𰰐𰰑𰰒𰰓𰰔𰰕𰰖𰰗𰰘𰰙𰰚𰰛𰰜𰰝𰰞𰰟𰰠𰰡𰰢𰰣𰰤𰰥𰰦𰰧𰰨𰰩𰰪𰰫𰰬𰰭𰰮𰰯𰰰𰰱𰰲𰰳𰰴𰰵𰰶𰰷𰰸𰰹𰰺𰰻𰰼𰰽𰰾𰰿𰱀𰱁𰱂𰱃𰱄𰱅𰱆𰱇𰱈𰱉𰱊𰱋𰱌𰱍𰱎𰱏𰱐𰱑𰱒𰱓𰱔𰱕𰱖𰱗𰱘𰱙𰱚𰱛𰱜𰱝𰱞𰱟𰱠𰱡𰱢𰱣𰱤𰱥𰱦𰱧𰱨𰱩𰱪𰱫𰱬𰱭𰱮𰱯𰱰𰱱𰱲𰱳𰱴𰱵𰱶𰱷𰱸𰱹𰱺𰱻𰱼𰱽𰱾𰱿𰲀𰲁𰲂𰲃𰲄𰲅𰲆𰲇𰲈𰲉𰲊𰲋𰲌𰲍𰲎𰲏𰲐𰲑𰲒𰲓𰲔𰲕𰲖𰲗𰲘𰲙𰲚𰲛𰲜𰲝𰲞𰲟𰲠𰲡𰲢𰲣𰲤𰲥𰲦𰲧𰲨𰲩𰲪𰲫𰲬𰲭𰲮𰲯𰲰𰲱𰲲𰲳𰲴𰲵𰲶𰲷𰲸𰲹𰲺𰲻𰲼𰲽𰲾𰲿𰳀𰳁𰳂𰳃𰳄𰳅𰳆𰳇𰳈𰳉𰳊𰳋𰳌𰳍𰳎𰳏𰳐𰳑𰳒𰳓𰳔𰳕𰳖𰳗𰳘𰳙𰳚𰳛𰳜𰳝𰳞𰳟𰳠𰳡𰳢𰳣𰳤𰳥𰳦𰳧𰳨𰳩𰳪𰳫𰳬𰳭𰳮𰳯𰳰𰳱𰳲𰳳𰳴𰳵𰳶𰳷𰳸𰳹𰳺𰳻𰳼𰳽𰳾𰳿𰴀𰴁𰴂𰴃𰴄𰴅𰴆𰴇𰴈𰴉𰴊𰴋𰴌𰴍𰴎𰴏𰴐𰴑𰴒𰴓𰴔𰴕𰴖𰴗𰴘𰴙𰴚𰴛𰴜𰴝𰴞𰴟𰴠𰴡𰴢𰴣𰴤𰴥𰴦𰴧𰴨𰴩𰴪𰴫𰴬𰴭𰴮𰴯𰴰𰴱𰴲𰴳𰴴𰴵𰴶𰴷𰴸𰴹𰴺𰴻𰴼𰴽𰴾𰴿𰵀𰵁𰵂𰵃𰵄𰵅𰵆𰵇𰵈𰵉𰵊𰵋𰵌𰵍𰵎𰵏𰵐𰵑𰵒𰵓𰵔𰵕𰵖𰵗𰵘𰵙𰵚𰵛𰵜𰵝𰵞𰵟𰵠𰵡𰵢𰵣𰵤𰵥𰵦𰵧𰵨𰵩𰵪𰵫𰵬𰵭𰵮𰵯𰵰𰵱𰵲𰵳𰵴𰵵𰵶𰵷𰵸𰵹𰵺𰵻𰵼𰵽𰵾𰵿𰶀𰶁𰶂𰶃𰶄𰶅𰶆𰶇𰶈𰶉𰶊𰶋𰶌𰶍𰶎𰶏𰶐𰶑𰶒𰶓𰶔𰶕𰶖𰶗𰶘𰶙𰶚𰶛𰶜𰶝𰶞𰶟𰶠𰶡𰶢𰶣𰶤𰶥𰶦𰶧𰶨𰶩𰶪𰶫𰶬𰶭𰶮𰶯𰶰𰶱𰶲𰶳𰶴𰶵𰶶𰶷𰶸𰶹𰶺𰶻𰶼𰶽𰶾𰶿𰷀𰷁𰷂𰷃𰷄𰷅𰷆𰷇𰷈𰷉𰷊𰷋𰷌𰷍𰷎𰷏𰷐𰷑𰷒𰷓𰷔𰷕𰷖𰷗𰷘𰷙𰷚𰷛𰷜𰷝𰷞𰷟𰷠𰷡𰷢𰷣𰷤𰷥𰷦𰷧𰷨𰷩𰷪𰷫𰷬𰷭𰷮𰷯𰷰𰷱𰷲𰷳𰷴𰷵𰷶𰷷𰷸𰷹𰷺𰷻𰷼𰷽𰷾𰷿𰸀𰸁𰸂𰸃𰸄𰸅𰸆𰸇𰸈𰸉𰸊𰸋𰸌𰸍𰸎𰸏𰸐𰸑𰸒𰸓𰸔𰸕𰸖𰸗𰸘𰸙𰸚𰸛𰸜𰸝𰸞𰸟𰸠𰸡𰸢𰸣𰸤𰸥𰸦𰸧𰸨𰸩𰸪𰸫𰸬𰸭𰸮𰸯𰸰𰸱𰸲𰸳𰸴𰸵𰸶𰸷𰸸𰸹𰸺𰸻𰸼𰸽𰸾𰸿𰹀𰹁𰹂𰹃𰹄𰹅𰹆𰹇𰹈𰹉𰹊𰹋𰹌𰹍𰹎𰹏𰹐𰹑𰹒𰹓𰹔𰹕𰹖𰹗𰹘𰹙𰹚𰹛𰹜𰹝𰹞𰹟𰹠𰹡𰹢𰹣𰹤𰹥𰹦𰹧𰹨𰹩𰹪𰹫𰹬𰹭𰹮𰹯𰹰𰹱𰹲𰹳𰹴𰹵𰹶𰹷𰹸𰹹𰹺𰹻𰹼𰹽𰹾𰹿𰺀𰺁𰺂𰺃𰺄𰺅𰺆𰺇𰺈𰺉𰺊𰺋𰺌𰺍𰺎𰺏𰺐𰺑𰺒𰺓𰺔𰺕𰺖𰺗𰺘𰺙𰺚𰺛𰺜𰺝𰺞𰺟𰺠𰺡𰺢𰺣𰺤𰺥𰺦𰺧𰺨𰺩𰺪𰺫𰺬𰺭𰺮𰺯𰺰𰺱𰺲𰺳𰺴𰺵𰺶𰺷𰺸𰺹𰺺𰺻𰺼𰺽𰺾𰺿𰻀𰻁𰻂𰻃𰻄𰻅𰻆𰻇𰻈𰻉𰻊𰻋𰻌𰻍𰻎𰻏𰻐𰻑𰻒𰻓𰻔𰻕𰻖𰻗𰻘𰻙𰻚𰻛𰻜𰻝𰻞𰻟𰻠𰻡𰻢𰻣𰻤𰻥𰻦𰻧𰻨𰻩𰻪𰻫𰻬𰻭𰻮𰻯𰻰𰻱𰻲𰻳𰻴𰻵𰻶𰻷𰻸𰻹𰻺𰻻𰻼𰻽𰻾𰻿𰼀𰼁𰼂𰼃𰼄𰼅𰼆𰼇𰼈𰼉𰼊𰼋𰼌𰼍𰼎𰼏𰼐𰼑𰼒𰼓𰼔𰼕𰼖𰼗𰼘𰼙𰼚𰼛𰼜𰼝𰼞𰼟𰼠𰼡𰼢𰼣𰼤𰼥𰼦𰼧𰼨𰼩𰼪𰼫𰼬𰼭𰼮𰼯𰼰𰼱𰼲𰼳𰼴𰼵𰼶𰼷𰼸𰼹𰼺𰼻𰼼𰼽𰼾𰼿𰽀𰽁𰽂𰽃𰽄𰽅𰽆𰽇𰽈𰽉𰽊𰽋𰽌𰽍𰽎𰽏𰽐𰽑𰽒𰽓𰽔𰽕𰽖𰽗𰽘𰽙𰽚𰽛𰽜𰽝𰽞𰽟𰽠𰽡𰽢𰽣𰽤𰽥𰽦𰽧𰽨𰽩𰽪𰽫𰽬𰽭𰽮𰽯𰽰𰽱𰽲𰽳𰽴𰽵𰽶𰽷𰽸𰽹𰽺𰽻𰽼𰽽𰽾𰽿𰾀𰾁𰾂𰾃𰾄𰾅𰾆𰾇𰾈𰾉𰾊𰾋𰾌𰾍𰾎𰾏𰾐𰾑𰾒𰾓𰾔𰾕𰾖𰾗𰾘𰾙𰾚𰾛𰾜𰾝𰾞𰾟𰾠𰾡𰾢𰾣𰾤𰾥𰾦𰾧𰾨𰾩𰾪𰾫𰾬𰾭𰾮𰾯𰾰𰾱𰾲𰾳𰾴𰾵𰾶𰾷𰾸𰾹𰾺𰾻𰾼𰾽𰾾𰾿𰿀𰿁𰿂𰿃𰿄𰿅𰿆𰿇𰿈𰿉𰿊𰿋𰿌𰿍𰿎𰿏𰿐𰿑𰿒𰿓𰿔𰿕𰿖𰿗𰿘𰿙𰿚𰿛𰿜𰿝𰿞𰿟𰿠𰿡𰿢𰿣𰿤𰿥𰿦𰿧𰿨𰿩𰿪𰿫𰿬𰿭𰿮𰿯𰿰𰿱𰿲𰿳𰿴𰿵𰿶𰿷𰿸𰿹𰿺𰿻𰿼𰿽𰿾𰿿𱀀𱀁𱀂𱀃𱀄𱀅𱀆𱀇𱀈𱀉𱀊𱀋𱀌𱀍𱀎𱀏𱀐𱀑𱀒𱀓𱀔𱀕𱀖𱀗𱀘𱀙𱀚𱀛𱀜𱀝𱀞𱀟𱀠𱀡𱀢𱀣𱀤𱀥𱀦𱀧𱀨𱀩𱀪𱀫𱀬𱀭𱀮𱀯𱀰𱀱𱀲𱀳𱀴𱀵𱀶𱀷𱀸𱀹𱀺𱀻𱀼𱀽𱀾𱀿𱁀𱁁𱁂𱁃𱁄𱁅𱁆𱁇𱁈𱁉𱁊𱁋𱁌𱁍𱁎𱁏𱁐𱁑𱁒𱁓𱁔𱁕𱁖𱁗𱁘𱁙𱁚𱁛𱁜𱁝𱁞𱁟𱁠𱁡𱁢𱁣𱁤𱁥𱁦𱁧𱁨𱁩𱁪𱁫𱁬𱁭𱁮𱁯𱁰𱁱𱁲𱁳𱁴𱁵𱁶𱁷𱁸𱁹𱁺𱁻𱁼𱁽𱁾𱁿𱂀𱂁𱂂𱂃𱂄𱂅𱂆𱂇𱂈𱂉𱂊𱂋𱂌𱂍𱂎𱂏𱂐𱂑𱂒𱂓𱂔𱂕𱂖𱂗𱂘𱂙𱂚𱂛𱂜𱂝𱂞𱂟𱂠𱂡𱂢𱂣𱂤𱂥𱂦𱂧𱂨𱂩𱂪𱂫𱂬𱂭𱂮𱂯𱂰𱂱𱂲𱂳𱂴𱂵𱂶𱂷𱂸𱂹𱂺𱂻𱂼𱂽𱂾𱂿𱃀𱃁𱃂𱃃𱃄𱃅𱃆𱃇𱃈𱃉𱃊𱃋𱃌𱃍𱃎𱃏𱃐𱃑𱃒𱃓𱃔𱃕𱃖𱃗𱃘𱃙𱃚𱃛𱃜𱃝𱃞𱃟𱃠𱃡𱃢𱃣𱃤𱃥𱃦𱃧𱃨𱃩𱃪𱃫𱃬𱃭𱃮𱃯𱃰𱃱𱃲𱃳𱃴𱃵𱃶𱃷𱃸𱃹𱃺𱃻𱃼𱃽𱃾𱃿𱄀𱄁𱄂𱄃𱄄𱄅𱄆𱄇𱄈𱄉𱄊𱄋𱄌𱄍𱄎𱄏𱄐𱄑𱄒𱄓𱄔𱄕𱄖𱄗𱄘𱄙𱄚𱄛𱄜𱄝𱄞𱄟𱄠𱄡𱄢𱄣𱄤𱄥𱄦𱄧𱄨𱄩𱄪𱄫𱄬𱄭𱄮𱄯𱄰𱄱𱄲𱄳𱄴𱄵𱄶𱄷𱄸𱄹𱄺𱄻𱄼𱄽𱄾𱄿𱅀𱅁𱅂𱅃𱅄𱅅𱅆𱅇𱅈𱅉𱅊𱅋𱅌𱅍𱅎𱅏𱅐𱅑𱅒𱅓𱅔𱅕𱅖𱅗𱅘𱅙𱅚𱅛𱅜𱅝𱅞𱅟𱅠𱅡𱅢𱅣𱅤𱅥𱅦𱅧𱅨𱅩𱅪𱅫𱅬𱅭𱅮𱅯𱅰𱅱𱅲𱅳𱅴𱅵𱅶𱅷𱅸𱅹𱅺𱅻𱅼𱅽𱅾𱅿𱆀𱆁𱆂𱆃𱆄𱆅𱆆𱆇𱆈𱆉𱆊𱆋𱆌𱆍𱆎𱆏𱆐𱆑𱆒𱆓𱆔𱆕𱆖𱆗𱆘𱆙𱆚𱆛𱆜𱆝𱆞𱆟𱆠𱆡𱆢𱆣𱆤𱆥𱆦𱆧𱆨𱆩𱆪𱆫𱆬𱆭𱆮𱆯𱆰𱆱𱆲𱆳𱆴𱆵𱆶𱆷𱆸𱆹𱆺𱆻𱆼𱆽𱆾𱆿𱇀𱇁𱇂𱇃𱇄𱇅𱇆𱇇𱇈𱇉𱇊𱇋𱇌𱇍𱇎𱇏𱇐𱇑𱇒𱇓𱇔𱇕𱇖𱇗𱇘𱇙𱇚𱇛𱇜𱇝𱇞𱇟𱇠𱇡𱇢𱇣𱇤𱇥𱇦𱇧𱇨𱇩𱇪𱇫𱇬𱇭𱇮𱇯𱇰𱇱𱇲𱇳𱇴𱇵𱇶𱇷𱇸𱇹𱇺𱇻𱇼𱇽𱇾𱇿𱈀𱈁𱈂𱈃𱈄𱈅𱈆𱈇𱈈𱈉𱈊𱈋𱈌𱈍𱈎𱈏𱈐𱈑𱈒𱈓𱈔𱈕𱈖𱈗𱈘𱈙𱈚𱈛𱈜𱈝𱈞𱈟𱈠𱈡𱈢𱈣𱈤𱈥𱈦𱈧𱈨𱈩𱈪𱈫𱈬𱈭𱈮𱈯𱈰𱈱𱈲𱈳𱈴𱈵𱈶𱈷𱈸𱈹𱈺𱈻𱈼𱈽𱈾𱈿𱉀𱉁𱉂𱉃𱉄𱉅𱉆𱉇𱉈𱉉𱉊𱉋𱉌𱉍𱉎𱉏𱉐𱉑𱉒𱉓𱉔𱉕𱉖𱉗𱉘𱉙𱉚𱉛𱉜𱉝𱉞𱉟𱉠𱉡𱉢𱉣𱉤𱉥𱉦𱉧𱉨𱉩𱉪𱉫𱉬𱉭𱉮𱉯𱉰𱉱𱉲𱉳𱉴𱉵𱉶𱉷𱉸𱉹𱉺𱉻𱉼𱉽𱉾𱉿𱊀𱊁𱊂𱊃𱊄𱊅𱊆𱊇𱊈𱊉𱊊𱊋𱊌𱊍𱊎𱊏𱊐𱊑𱊒𱊓𱊔𱊕𱊖𱊗𱊘𱊙𱊚𱊛𱊜𱊝𱊞𱊟𱊠𱊡𱊢𱊣𱊤𱊥𱊦𱊧𱊨𱊩𱊪𱊫𱊬𱊭𱊮𱊯𱊰𱊱𱊲𱊳𱊴𱊵𱊶𱊷𱊸𱊹𱊺𱊻𱊼𱊽𱊾𱊿𱋀𱋁𱋂𱋃𱋄𱋅𱋆𱋇𱋈𱋉𱋊𱋋𱋌𱋍𱋎𱋏𱋐𱋑𱋒𱋓𱋔𱋕𱋖𱋗𱋘𱋙𱋚𱋛𱋜𱋝𱋞𱋟𱋠𱋡𱋢𱋣𱋤𱋥𱋦𱋧𱋨𱋩𱋪𱋫𱋬𱋭𱋮𱋯𱋰𱋱𱋲𱋳𱋴𱋵𱋶𱋷𱋸𱋹𱋺𱋻𱋼𱋽𱋾𱋿𱌀𱌁𱌂𱌃𱌄𱌅𱌆𱌇𱌈𱌉𱌊𱌋𱌌𱌍𱌎𱌏𱌐𱌑𱌒𱌓𱌔𱌕𱌖𱌗𱌘𱌙𱌚𱌛𱌜𱌝𱌞𱌟𱌠𱌡𱌢𱌣𱌤𱌥𱌦𱌧𱌨𱌩𱌪𱌫𱌬𱌭𱌮𱌯𱌰𱌱𱌲𱌳𱌴𱌵𱌶𱌷𱌸𱌹𱌺𱌻𱌼𱌽𱌾𱌿𱍀𱍁𱍂𱍃𱍄𱍅𱍆𱍇𱍈𱍉𱍊; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-escaped.js index 6534989ec282..3bc72c7f4b5e 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-13.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-13.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-13.0.0.js index 2245b7de37f7..68224ca36273 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-13.0.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-13.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-class-escaped.js new file mode 100644 index 000000000000..96dcbd35329c --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v14.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u0870\u0871\u0872\u0873\u0874\u0875\u0876\u0877\u0878\u0879\u087A\u087B\u087C\u087D\u087E\u087F\u0880\u0881\u0882\u0883\u0884\u0885\u0886\u0887\u0889\u088A\u088B\u088C\u088D\u088E\u08B5\u08C8\u08C9\u0C5D\u0CDD\u170D\u171F\u1B4C\u2C2F\u2C5F\u9FFD\u9FFE\u9FFF\uA7C0\uA7C1\uA7D0\uA7D1\uA7D3\uA7D5\uA7D6\uA7D7\uA7D8\uA7D9\uA7F2\uA7F3\uA7F4\u{10570}\u{10571}\u{10572}\u{10573}\u{10574}\u{10575}\u{10576}\u{10577}\u{10578}\u{10579}\u{1057A}\u{1057C}\u{1057D}\u{1057E}\u{1057F}\u{10580}\u{10581}\u{10582}\u{10583}\u{10584}\u{10585}\u{10586}\u{10587}\u{10588}\u{10589}\u{1058A}\u{1058C}\u{1058D}\u{1058E}\u{1058F}\u{10590}\u{10591}\u{10592}\u{10594}\u{10595}\u{10597}\u{10598}\u{10599}\u{1059A}\u{1059B}\u{1059C}\u{1059D}\u{1059E}\u{1059F}\u{105A0}\u{105A1}\u{105A3}\u{105A4}\u{105A5}\u{105A6}\u{105A7}\u{105A8}\u{105A9}\u{105AA}\u{105AB}\u{105AC}\u{105AD}\u{105AE}\u{105AF}\u{105B0}\u{105B1}\u{105B3}\u{105B4}\u{105B5}\u{105B6}\u{105B7}\u{105B8}\u{105B9}\u{105BB}\u{105BC}\u{10780}\u{10781}\u{10782}\u{10783}\u{10784}\u{10785}\u{10787}\u{10788}\u{10789}\u{1078A}\u{1078B}\u{1078C}\u{1078D}\u{1078E}\u{1078F}\u{10790}\u{10791}\u{10792}\u{10793}\u{10794}\u{10795}\u{10796}\u{10797}\u{10798}\u{10799}\u{1079A}\u{1079B}\u{1079C}\u{1079D}\u{1079E}\u{1079F}\u{107A0}\u{107A1}\u{107A2}\u{107A3}\u{107A4}\u{107A5}\u{107A6}\u{107A7}\u{107A8}\u{107A9}\u{107AA}\u{107AB}\u{107AC}\u{107AD}\u{107AE}\u{107AF}\u{107B0}\u{107B2}\u{107B3}\u{107B4}\u{107B5}\u{107B6}\u{107B7}\u{107B8}\u{107B9}\u{107BA}\u{10F70}\u{10F71}\u{10F72}\u{10F73}\u{10F74}\u{10F75}\u{10F76}\u{10F77}\u{10F78}\u{10F79}\u{10F7A}\u{10F7B}\u{10F7C}\u{10F7D}\u{10F7E}\u{10F7F}\u{10F80}\u{10F81}\u{11071}\u{11072}\u{11075}\u{11740}\u{11741}\u{11742}\u{11743}\u{11744}\u{11745}\u{11746}\u{11AB0}\u{11AB1}\u{11AB2}\u{11AB3}\u{11AB4}\u{11AB5}\u{11AB6}\u{11AB7}\u{11AB8}\u{11AB9}\u{11ABA}\u{11ABB}\u{11ABC}\u{11ABD}\u{11ABE}\u{11ABF}\u{12F90}\u{12F91}\u{12F92}\u{12F93}\u{12F94}\u{12F95}\u{12F96}\u{12F97}\u{12F98}\u{12F99}\u{12F9A}\u{12F9B}\u{12F9C}\u{12F9D}\u{12F9E}\u{12F9F}\u{12FA0}\u{12FA1}\u{12FA2}\u{12FA3}\u{12FA4}\u{12FA5}\u{12FA6}\u{12FA7}\u{12FA8}\u{12FA9}\u{12FAA}\u{12FAB}\u{12FAC}\u{12FAD}\u{12FAE}\u{12FAF}\u{12FB0}\u{12FB1}\u{12FB2}\u{12FB3}\u{12FB4}\u{12FB5}\u{12FB6}\u{12FB7}\u{12FB8}\u{12FB9}\u{12FBA}\u{12FBB}\u{12FBC}\u{12FBD}\u{12FBE}\u{12FBF}\u{12FC0}\u{12FC1}\u{12FC2}\u{12FC3}\u{12FC4}\u{12FC5}\u{12FC6}\u{12FC7}\u{12FC8}\u{12FC9}\u{12FCA}\u{12FCB}\u{12FCC}\u{12FCD}\u{12FCE}\u{12FCF}\u{12FD0}\u{12FD1}\u{12FD2}\u{12FD3}\u{12FD4}\u{12FD5}\u{12FD6}\u{12FD7}\u{12FD8}\u{12FD9}\u{12FDA}\u{12FDB}\u{12FDC}\u{12FDD}\u{12FDE}\u{12FDF}\u{12FE0}\u{12FE1}\u{12FE2}\u{12FE3}\u{12FE4}\u{12FE5}\u{12FE6}\u{12FE7}\u{12FE8}\u{12FE9}\u{12FEA}\u{12FEB}\u{12FEC}\u{12FED}\u{12FEE}\u{12FEF}\u{12FF0}\u{16A70}\u{16A71}\u{16A72}\u{16A73}\u{16A74}\u{16A75}\u{16A76}\u{16A77}\u{16A78}\u{16A79}\u{16A7A}\u{16A7B}\u{16A7C}\u{16A7D}\u{16A7E}\u{16A7F}\u{16A80}\u{16A81}\u{16A82}\u{16A83}\u{16A84}\u{16A85}\u{16A86}\u{16A87}\u{16A88}\u{16A89}\u{16A8A}\u{16A8B}\u{16A8C}\u{16A8D}\u{16A8E}\u{16A8F}\u{16A90}\u{16A91}\u{16A92}\u{16A93}\u{16A94}\u{16A95}\u{16A96}\u{16A97}\u{16A98}\u{16A99}\u{16A9A}\u{16A9B}\u{16A9C}\u{16A9D}\u{16A9E}\u{16A9F}\u{16AA0}\u{16AA1}\u{16AA2}\u{16AA3}\u{16AA4}\u{16AA5}\u{16AA6}\u{16AA7}\u{16AA8}\u{16AA9}\u{16AAA}\u{16AAB}\u{16AAC}\u{16AAD}\u{16AAE}\u{16AAF}\u{16AB0}\u{16AB1}\u{16AB2}\u{16AB3}\u{16AB4}\u{16AB5}\u{16AB6}\u{16AB7}\u{16AB8}\u{16AB9}\u{16ABA}\u{16ABB}\u{16ABC}\u{16ABD}\u{16ABE}\u{1AFF0}\u{1AFF1}\u{1AFF2}\u{1AFF3}\u{1AFF5}\u{1AFF6}\u{1AFF7}\u{1AFF8}\u{1AFF9}\u{1AFFA}\u{1AFFB}\u{1AFFD}\u{1AFFE}\u{1B11F}\u{1B120}\u{1B121}\u{1B122}\u{1DF00}\u{1DF01}\u{1DF02}\u{1DF03}\u{1DF04}\u{1DF05}\u{1DF06}\u{1DF07}\u{1DF08}\u{1DF09}\u{1DF0A}\u{1DF0B}\u{1DF0C}\u{1DF0D}\u{1DF0E}\u{1DF0F}\u{1DF10}\u{1DF11}\u{1DF12}\u{1DF13}\u{1DF14}\u{1DF15}\u{1DF16}\u{1DF17}\u{1DF18}\u{1DF19}\u{1DF1A}\u{1DF1B}\u{1DF1C}\u{1DF1D}\u{1DF1E}\u{1E290}\u{1E291}\u{1E292}\u{1E293}\u{1E294}\u{1E295}\u{1E296}\u{1E297}\u{1E298}\u{1E299}\u{1E29A}\u{1E29B}\u{1E29C}\u{1E29D}\u{1E29E}\u{1E29F}\u{1E2A0}\u{1E2A1}\u{1E2A2}\u{1E2A3}\u{1E2A4}\u{1E2A5}\u{1E2A6}\u{1E2A7}\u{1E2A8}\u{1E2A9}\u{1E2AA}\u{1E2AB}\u{1E2AC}\u{1E2AD}\u{1E7E0}\u{1E7E1}\u{1E7E2}\u{1E7E3}\u{1E7E4}\u{1E7E5}\u{1E7E6}\u{1E7E8}\u{1E7E9}\u{1E7EA}\u{1E7EB}\u{1E7ED}\u{1E7EE}\u{1E7F0}\u{1E7F1}\u{1E7F2}\u{1E7F3}\u{1E7F4}\u{1E7F5}\u{1E7F6}\u{1E7F7}\u{1E7F8}\u{1E7F9}\u{1E7FA}\u{1E7FB}\u{1E7FC}\u{1E7FD}\u{1E7FE}\u{2A6DE}\u{2A6DF}\u{2B735}\u{2B736}\u{2B737}\u{2B738}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-class.js new file mode 100644 index 000000000000..ea0b17c792a9 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v14.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ࡰࡱࡲࡳࡴࡵࡶࡷࡸࡹࡺࡻࡼࡽࡾࡿࢀࢁࢂࢃࢄࢅࢆࢇࢉࢊࢋࢌࢍࢎࢵࣈࣉౝೝᜍᜟᭌⰯⱟ鿽鿾鿿ꟀꟁꟐꟑꟓꟕꟖꟗꟘꟙꟲꟳꟴ𐕰𐕱𐕲𐕳𐕴𐕵𐕶𐕷𐕸𐕹𐕺𐕼𐕽𐕾𐕿𐖀𐖁𐖂𐖃𐖄𐖅𐖆𐖇𐖈𐖉𐖊𐖌𐖍𐖎𐖏𐖐𐖑𐖒𐖔𐖕𐖗𐖘𐖙𐖚𐖛𐖜𐖝𐖞𐖟𐖠𐖡𐖣𐖤𐖥𐖦𐖧𐖨𐖩𐖪𐖫𐖬𐖭𐖮𐖯𐖰𐖱𐖳𐖴𐖵𐖶𐖷𐖸𐖹𐖻𐖼𐞀𐞁𐞂𐞃𐞄𐞅𐞇𐞈𐞉𐞊𐞋𐞌𐞍𐞎𐞏𐞐𐞑𐞒𐞓𐞔𐞕𐞖𐞗𐞘𐞙𐞚𐞛𐞜𐞝𐞞𐞟𐞠𐞡𐞢𐞣𐞤𐞥𐞦𐞧𐞨𐞩𐞪𐞫𐞬𐞭𐞮𐞯𐞰𐞲𐞳𐞴𐞵𐞶𐞷𐞸𐞹𐞺𐽰𐽱𐽲𐽳𐽴𐽵𐽶𐽷𐽸𐽹𐽺𐽻𐽼𐽽𐽾𐽿𐾀𐾁𑁱𑁲𑁵𑝀𑝁𑝂𑝃𑝄𑝅𑝆𑪰𑪱𑪲𑪳𑪴𑪵𑪶𑪷𑪸𑪹𑪺𑪻𑪼𑪽𑪾𑪿𒾐𒾑𒾒𒾓𒾔𒾕𒾖𒾗𒾘𒾙𒾚𒾛𒾜𒾝𒾞𒾟𒾠𒾡𒾢𒾣𒾤𒾥𒾦𒾧𒾨𒾩𒾪𒾫𒾬𒾭𒾮𒾯𒾰𒾱𒾲𒾳𒾴𒾵𒾶𒾷𒾸𒾹𒾺𒾻𒾼𒾽𒾾𒾿𒿀𒿁𒿂𒿃𒿄𒿅𒿆𒿇𒿈𒿉𒿊𒿋𒿌𒿍𒿎𒿏𒿐𒿑𒿒𒿓𒿔𒿕𒿖𒿗𒿘𒿙𒿚𒿛𒿜𒿝𒿞𒿟𒿠𒿡𒿢𒿣𒿤𒿥𒿦𒿧𒿨𒿩𒿪𒿫𒿬𒿭𒿮𒿯𒿰𖩰𖩱𖩲𖩳𖩴𖩵𖩶𖩷𖩸𖩹𖩺𖩻𖩼𖩽𖩾𖩿𖪀𖪁𖪂𖪃𖪄𖪅𖪆𖪇𖪈𖪉𖪊𖪋𖪌𖪍𖪎𖪏𖪐𖪑𖪒𖪓𖪔𖪕𖪖𖪗𖪘𖪙𖪚𖪛𖪜𖪝𖪞𖪟𖪠𖪡𖪢𖪣𖪤𖪥𖪦𖪧𖪨𖪩𖪪𖪫𖪬𖪭𖪮𖪯𖪰𖪱𖪲𖪳𖪴𖪵𖪶𖪷𖪸𖪹𖪺𖪻𖪼𖪽𖪾𚿰𚿱𚿲𚿳𚿵𚿶𚿷𚿸𚿹𚿺𚿻𚿽𚿾𛄟𛄠𛄡𛄢𝼀𝼁𝼂𝼃𝼄𝼅𝼆𝼇𝼈𝼉𝼊𝼋𝼌𝼍𝼎𝼏𝼐𝼑𝼒𝼓𝼔𝼕𝼖𝼗𝼘𝼙𝼚𝼛𝼜𝼝𝼞𞊐𞊑𞊒𞊓𞊔𞊕𞊖𞊗𞊘𞊙𞊚𞊛𞊜𞊝𞊞𞊟𞊠𞊡𞊢𞊣𞊤𞊥𞊦𞊧𞊨𞊩𞊪𞊫𞊬𞊭𞟠𞟡𞟢𞟣𞟤𞟥𞟦𞟨𞟩𞟪𞟫𞟭𞟮𞟰𞟱𞟲𞟳𞟴𞟵𞟶𞟷𞟸𞟹𞟺𞟻𞟼𞟽𞟾𪛞𪛟𫜵𫜶𫜷𫜸; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-escaped.js new file mode 100644 index 000000000000..0ccb90e019e6 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-14.0.0-escaped.js @@ -0,0 +1,18 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: sec-names-and-keywords +description: | + Test that Unicode v14.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols +info: | + Generated by https://github.com/mathiasbynens/caniunicode +---*/ + +var \u0870\u0871\u0872\u0873\u0874\u0875\u0876\u0877\u0878\u0879\u087A\u087B\u087C\u087D\u087E\u087F\u0880\u0881\u0882\u0883\u0884\u0885\u0886\u0887\u0889\u088A\u088B\u088C\u088D\u088E\u08B5\u08C8\u08C9\u0C5D\u0CDD\u170D\u171F\u1B4C\u2C2F\u2C5F\u9FFD\u9FFE\u9FFF\uA7C0\uA7C1\uA7D0\uA7D1\uA7D3\uA7D5\uA7D6\uA7D7\uA7D8\uA7D9\uA7F2\uA7F3\uA7F4\u{10570}\u{10571}\u{10572}\u{10573}\u{10574}\u{10575}\u{10576}\u{10577}\u{10578}\u{10579}\u{1057A}\u{1057C}\u{1057D}\u{1057E}\u{1057F}\u{10580}\u{10581}\u{10582}\u{10583}\u{10584}\u{10585}\u{10586}\u{10587}\u{10588}\u{10589}\u{1058A}\u{1058C}\u{1058D}\u{1058E}\u{1058F}\u{10590}\u{10591}\u{10592}\u{10594}\u{10595}\u{10597}\u{10598}\u{10599}\u{1059A}\u{1059B}\u{1059C}\u{1059D}\u{1059E}\u{1059F}\u{105A0}\u{105A1}\u{105A3}\u{105A4}\u{105A5}\u{105A6}\u{105A7}\u{105A8}\u{105A9}\u{105AA}\u{105AB}\u{105AC}\u{105AD}\u{105AE}\u{105AF}\u{105B0}\u{105B1}\u{105B3}\u{105B4}\u{105B5}\u{105B6}\u{105B7}\u{105B8}\u{105B9}\u{105BB}\u{105BC}\u{10780}\u{10781}\u{10782}\u{10783}\u{10784}\u{10785}\u{10787}\u{10788}\u{10789}\u{1078A}\u{1078B}\u{1078C}\u{1078D}\u{1078E}\u{1078F}\u{10790}\u{10791}\u{10792}\u{10793}\u{10794}\u{10795}\u{10796}\u{10797}\u{10798}\u{10799}\u{1079A}\u{1079B}\u{1079C}\u{1079D}\u{1079E}\u{1079F}\u{107A0}\u{107A1}\u{107A2}\u{107A3}\u{107A4}\u{107A5}\u{107A6}\u{107A7}\u{107A8}\u{107A9}\u{107AA}\u{107AB}\u{107AC}\u{107AD}\u{107AE}\u{107AF}\u{107B0}\u{107B2}\u{107B3}\u{107B4}\u{107B5}\u{107B6}\u{107B7}\u{107B8}\u{107B9}\u{107BA}\u{10F70}\u{10F71}\u{10F72}\u{10F73}\u{10F74}\u{10F75}\u{10F76}\u{10F77}\u{10F78}\u{10F79}\u{10F7A}\u{10F7B}\u{10F7C}\u{10F7D}\u{10F7E}\u{10F7F}\u{10F80}\u{10F81}\u{11071}\u{11072}\u{11075}\u{11740}\u{11741}\u{11742}\u{11743}\u{11744}\u{11745}\u{11746}\u{11AB0}\u{11AB1}\u{11AB2}\u{11AB3}\u{11AB4}\u{11AB5}\u{11AB6}\u{11AB7}\u{11AB8}\u{11AB9}\u{11ABA}\u{11ABB}\u{11ABC}\u{11ABD}\u{11ABE}\u{11ABF}\u{12F90}\u{12F91}\u{12F92}\u{12F93}\u{12F94}\u{12F95}\u{12F96}\u{12F97}\u{12F98}\u{12F99}\u{12F9A}\u{12F9B}\u{12F9C}\u{12F9D}\u{12F9E}\u{12F9F}\u{12FA0}\u{12FA1}\u{12FA2}\u{12FA3}\u{12FA4}\u{12FA5}\u{12FA6}\u{12FA7}\u{12FA8}\u{12FA9}\u{12FAA}\u{12FAB}\u{12FAC}\u{12FAD}\u{12FAE}\u{12FAF}\u{12FB0}\u{12FB1}\u{12FB2}\u{12FB3}\u{12FB4}\u{12FB5}\u{12FB6}\u{12FB7}\u{12FB8}\u{12FB9}\u{12FBA}\u{12FBB}\u{12FBC}\u{12FBD}\u{12FBE}\u{12FBF}\u{12FC0}\u{12FC1}\u{12FC2}\u{12FC3}\u{12FC4}\u{12FC5}\u{12FC6}\u{12FC7}\u{12FC8}\u{12FC9}\u{12FCA}\u{12FCB}\u{12FCC}\u{12FCD}\u{12FCE}\u{12FCF}\u{12FD0}\u{12FD1}\u{12FD2}\u{12FD3}\u{12FD4}\u{12FD5}\u{12FD6}\u{12FD7}\u{12FD8}\u{12FD9}\u{12FDA}\u{12FDB}\u{12FDC}\u{12FDD}\u{12FDE}\u{12FDF}\u{12FE0}\u{12FE1}\u{12FE2}\u{12FE3}\u{12FE4}\u{12FE5}\u{12FE6}\u{12FE7}\u{12FE8}\u{12FE9}\u{12FEA}\u{12FEB}\u{12FEC}\u{12FED}\u{12FEE}\u{12FEF}\u{12FF0}\u{16A70}\u{16A71}\u{16A72}\u{16A73}\u{16A74}\u{16A75}\u{16A76}\u{16A77}\u{16A78}\u{16A79}\u{16A7A}\u{16A7B}\u{16A7C}\u{16A7D}\u{16A7E}\u{16A7F}\u{16A80}\u{16A81}\u{16A82}\u{16A83}\u{16A84}\u{16A85}\u{16A86}\u{16A87}\u{16A88}\u{16A89}\u{16A8A}\u{16A8B}\u{16A8C}\u{16A8D}\u{16A8E}\u{16A8F}\u{16A90}\u{16A91}\u{16A92}\u{16A93}\u{16A94}\u{16A95}\u{16A96}\u{16A97}\u{16A98}\u{16A99}\u{16A9A}\u{16A9B}\u{16A9C}\u{16A9D}\u{16A9E}\u{16A9F}\u{16AA0}\u{16AA1}\u{16AA2}\u{16AA3}\u{16AA4}\u{16AA5}\u{16AA6}\u{16AA7}\u{16AA8}\u{16AA9}\u{16AAA}\u{16AAB}\u{16AAC}\u{16AAD}\u{16AAE}\u{16AAF}\u{16AB0}\u{16AB1}\u{16AB2}\u{16AB3}\u{16AB4}\u{16AB5}\u{16AB6}\u{16AB7}\u{16AB8}\u{16AB9}\u{16ABA}\u{16ABB}\u{16ABC}\u{16ABD}\u{16ABE}\u{1AFF0}\u{1AFF1}\u{1AFF2}\u{1AFF3}\u{1AFF5}\u{1AFF6}\u{1AFF7}\u{1AFF8}\u{1AFF9}\u{1AFFA}\u{1AFFB}\u{1AFFD}\u{1AFFE}\u{1B11F}\u{1B120}\u{1B121}\u{1B122}\u{1DF00}\u{1DF01}\u{1DF02}\u{1DF03}\u{1DF04}\u{1DF05}\u{1DF06}\u{1DF07}\u{1DF08}\u{1DF09}\u{1DF0A}\u{1DF0B}\u{1DF0C}\u{1DF0D}\u{1DF0E}\u{1DF0F}\u{1DF10}\u{1DF11}\u{1DF12}\u{1DF13}\u{1DF14}\u{1DF15}\u{1DF16}\u{1DF17}\u{1DF18}\u{1DF19}\u{1DF1A}\u{1DF1B}\u{1DF1C}\u{1DF1D}\u{1DF1E}\u{1E290}\u{1E291}\u{1E292}\u{1E293}\u{1E294}\u{1E295}\u{1E296}\u{1E297}\u{1E298}\u{1E299}\u{1E29A}\u{1E29B}\u{1E29C}\u{1E29D}\u{1E29E}\u{1E29F}\u{1E2A0}\u{1E2A1}\u{1E2A2}\u{1E2A3}\u{1E2A4}\u{1E2A5}\u{1E2A6}\u{1E2A7}\u{1E2A8}\u{1E2A9}\u{1E2AA}\u{1E2AB}\u{1E2AC}\u{1E2AD}\u{1E7E0}\u{1E7E1}\u{1E7E2}\u{1E7E3}\u{1E7E4}\u{1E7E5}\u{1E7E6}\u{1E7E8}\u{1E7E9}\u{1E7EA}\u{1E7EB}\u{1E7ED}\u{1E7EE}\u{1E7F0}\u{1E7F1}\u{1E7F2}\u{1E7F3}\u{1E7F4}\u{1E7F5}\u{1E7F6}\u{1E7F7}\u{1E7F8}\u{1E7F9}\u{1E7FA}\u{1E7FB}\u{1E7FC}\u{1E7FD}\u{1E7FE}\u{2A6DE}\u{2A6DF}\u{2B735}\u{2B736}\u{2B737}\u{2B738}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-14.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-14.0.0.js new file mode 100644 index 000000000000..e4777d52b99f --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-14.0.0.js @@ -0,0 +1,16 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: sec-names-and-keywords +description: | + Test that Unicode v14.0.0 ID_Start characters are accepted as + identifier start characters. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +---*/ + +var ࡰࡱࡲࡳࡴࡵࡶࡷࡸࡹࡺࡻࡼࡽࡾࡿࢀࢁࢂࢃࢄࢅࢆࢇࢉࢊࢋࢌࢍࢎࢵࣈࣉౝೝᜍᜟᭌⰯⱟ鿽鿾鿿ꟀꟁꟐꟑꟓꟕꟖꟗꟘꟙꟲꟳꟴ𐕰𐕱𐕲𐕳𐕴𐕵𐕶𐕷𐕸𐕹𐕺𐕼𐕽𐕾𐕿𐖀𐖁𐖂𐖃𐖄𐖅𐖆𐖇𐖈𐖉𐖊𐖌𐖍𐖎𐖏𐖐𐖑𐖒𐖔𐖕𐖗𐖘𐖙𐖚𐖛𐖜𐖝𐖞𐖟𐖠𐖡𐖣𐖤𐖥𐖦𐖧𐖨𐖩𐖪𐖫𐖬𐖭𐖮𐖯𐖰𐖱𐖳𐖴𐖵𐖶𐖷𐖸𐖹𐖻𐖼𐞀𐞁𐞂𐞃𐞄𐞅𐞇𐞈𐞉𐞊𐞋𐞌𐞍𐞎𐞏𐞐𐞑𐞒𐞓𐞔𐞕𐞖𐞗𐞘𐞙𐞚𐞛𐞜𐞝𐞞𐞟𐞠𐞡𐞢𐞣𐞤𐞥𐞦𐞧𐞨𐞩𐞪𐞫𐞬𐞭𐞮𐞯𐞰𐞲𐞳𐞴𐞵𐞶𐞷𐞸𐞹𐞺𐽰𐽱𐽲𐽳𐽴𐽵𐽶𐽷𐽸𐽹𐽺𐽻𐽼𐽽𐽾𐽿𐾀𐾁𑁱𑁲𑁵𑝀𑝁𑝂𑝃𑝄𑝅𑝆𑪰𑪱𑪲𑪳𑪴𑪵𑪶𑪷𑪸𑪹𑪺𑪻𑪼𑪽𑪾𑪿𒾐𒾑𒾒𒾓𒾔𒾕𒾖𒾗𒾘𒾙𒾚𒾛𒾜𒾝𒾞𒾟𒾠𒾡𒾢𒾣𒾤𒾥𒾦𒾧𒾨𒾩𒾪𒾫𒾬𒾭𒾮𒾯𒾰𒾱𒾲𒾳𒾴𒾵𒾶𒾷𒾸𒾹𒾺𒾻𒾼𒾽𒾾𒾿𒿀𒿁𒿂𒿃𒿄𒿅𒿆𒿇𒿈𒿉𒿊𒿋𒿌𒿍𒿎𒿏𒿐𒿑𒿒𒿓𒿔𒿕𒿖𒿗𒿘𒿙𒿚𒿛𒿜𒿝𒿞𒿟𒿠𒿡𒿢𒿣𒿤𒿥𒿦𒿧𒿨𒿩𒿪𒿫𒿬𒿭𒿮𒿯𒿰𖩰𖩱𖩲𖩳𖩴𖩵𖩶𖩷𖩸𖩹𖩺𖩻𖩼𖩽𖩾𖩿𖪀𖪁𖪂𖪃𖪄𖪅𖪆𖪇𖪈𖪉𖪊𖪋𖪌𖪍𖪎𖪏𖪐𖪑𖪒𖪓𖪔𖪕𖪖𖪗𖪘𖪙𖪚𖪛𖪜𖪝𖪞𖪟𖪠𖪡𖪢𖪣𖪤𖪥𖪦𖪧𖪨𖪩𖪪𖪫𖪬𖪭𖪮𖪯𖪰𖪱𖪲𖪳𖪴𖪵𖪶𖪷𖪸𖪹𖪺𖪻𖪼𖪽𖪾𚿰𚿱𚿲𚿳𚿵𚿶𚿷𚿸𚿹𚿺𚿻𚿽𚿾𛄟𛄠𛄡𛄢𝼀𝼁𝼂𝼃𝼄𝼅𝼆𝼇𝼈𝼉𝼊𝼋𝼌𝼍𝼎𝼏𝼐𝼑𝼒𝼓𝼔𝼕𝼖𝼗𝼘𝼙𝼚𝼛𝼜𝼝𝼞𞊐𞊑𞊒𞊓𞊔𞊕𞊖𞊗𞊘𞊙𞊚𞊛𞊜𞊝𞊞𞊟𞊠𞊡𞊢𞊣𞊤𞊥𞊦𞊧𞊨𞊩𞊪𞊫𞊬𞊭𞟠𞟡𞟢𞟣𞟤𞟥𞟦𞟨𞟩𞟪𞟫𞟭𞟮𞟰𞟱𞟲𞟳𞟴𞟵𞟶𞟷𞟸𞟹𞟺𞟻𞟼𞟽𞟾𪛞𪛟𫜵𫜶𫜷𫜸; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-class-escaped.js new file mode 100644 index 000000000000..1f184cf7e4f6 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v5.2.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u0524\u0525\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807\u0808\u0809\u080A\u080B\u080C\u080D\u080E\u080F\u0810\u0811\u0812\u0813\u0814\u0815\u081A\u0824\u0828\u0979\u097A\u115A\u115B\u115C\u115D\u115E\u11A3\u11A4\u11A5\u11A6\u11A7\u11FA\u11FB\u11FC\u11FD\u11FE\u11FF\u1677\u1678\u1679\u167A\u167B\u167C\u167D\u167E\u167F\u18B0\u18B1\u18B2\u18B3\u18B4\u18B5\u18B6\u18B7\u18B8\u18B9\u18BA\u18BB\u18BC\u18BD\u18BE\u18BF\u18C0\u18C1\u18C2\u18C3\u18C4\u18C5\u18C6\u18C7\u18C8\u18C9\u18CA\u18CB\u18CC\u18CD\u18CE\u18CF\u18D0\u18D1\u18D2\u18D3\u18D4\u18D5\u18D6\u18D7\u18D8\u18D9\u18DA\u18DB\u18DC\u18DD\u18DE\u18DF\u18E0\u18E1\u18E2\u18E3\u18E4\u18E5\u18E6\u18E7\u18E8\u18E9\u18EA\u18EB\u18EC\u18ED\u18EE\u18EF\u18F0\u18F1\u18F2\u18F3\u18F4\u18F5\u19AA\u19AB\u1A20\u1A21\u1A22\u1A23\u1A24\u1A25\u1A26\u1A27\u1A28\u1A29\u1A2A\u1A2B\u1A2C\u1A2D\u1A2E\u1A2F\u1A30\u1A31\u1A32\u1A33\u1A34\u1A35\u1A36\u1A37\u1A38\u1A39\u1A3A\u1A3B\u1A3C\u1A3D\u1A3E\u1A3F\u1A40\u1A41\u1A42\u1A43\u1A44\u1A45\u1A46\u1A47\u1A48\u1A49\u1A4A\u1A4B\u1A4C\u1A4D\u1A4E\u1A4F\u1A50\u1A51\u1A52\u1A53\u1A54\u1AA7\u1CE9\u1CEA\u1CEB\u1CEC\u1CEE\u1CEF\u1CF0\u1CF1\u2C70\u2C7E\u2C7F\u2CEB\u2CEC\u2CED\u2CEE\u9FC4\u9FC5\u9FC6\u9FC7\u9FC8\u9FC9\u9FCA\u9FCB\uA4D0\uA4D1\uA4D2\uA4D3\uA4D4\uA4D5\uA4D6\uA4D7\uA4D8\uA4D9\uA4DA\uA4DB\uA4DC\uA4DD\uA4DE\uA4DF\uA4E0\uA4E1\uA4E2\uA4E3\uA4E4\uA4E5\uA4E6\uA4E7\uA4E8\uA4E9\uA4EA\uA4EB\uA4EC\uA4ED\uA4EE\uA4EF\uA4F0\uA4F1\uA4F2\uA4F3\uA4F4\uA4F5\uA4F6\uA4F7\uA4F8\uA4F9\uA4FA\uA4FB\uA4FC\uA4FD\uA6A0\uA6A1\uA6A2\uA6A3\uA6A4\uA6A5\uA6A6\uA6A7\uA6A8\uA6A9\uA6AA\uA6AB\uA6AC\uA6AD\uA6AE\uA6AF\uA6B0\uA6B1\uA6B2\uA6B3\uA6B4\uA6B5\uA6B6\uA6B7\uA6B8\uA6B9\uA6BA\uA6BB\uA6BC\uA6BD\uA6BE\uA6BF\uA6C0\uA6C1\uA6C2\uA6C3\uA6C4\uA6C5\uA6C6\uA6C7\uA6C8\uA6C9\uA6CA\uA6CB\uA6CC\uA6CD\uA6CE\uA6CF\uA6D0\uA6D1\uA6D2\uA6D3\uA6D4\uA6D5\uA6D6\uA6D7\uA6D8\uA6D9\uA6DA\uA6DB\uA6DC\uA6DD\uA6DE\uA6DF\uA6E0\uA6E1\uA6E2\uA6E3\uA6E4\uA6E5\uA6E6\uA6E7\uA6E8\uA6E9\uA6EA\uA6EB\uA6EC\uA6ED\uA6EE\uA6EF\uA8F2\uA8F3\uA8F4\uA8F5\uA8F6\uA8F7\uA8FB\uA960\uA961\uA962\uA963\uA964\uA965\uA966\uA967\uA968\uA969\uA96A\uA96B\uA96C\uA96D\uA96E\uA96F\uA970\uA971\uA972\uA973\uA974\uA975\uA976\uA977\uA978\uA979\uA97A\uA97B\uA97C\uA984\uA985\uA986\uA987\uA988\uA989\uA98A\uA98B\uA98C\uA98D\uA98E\uA98F\uA990\uA991\uA992\uA993\uA994\uA995\uA996\uA997\uA998\uA999\uA99A\uA99B\uA99C\uA99D\uA99E\uA99F\uA9A0\uA9A1\uA9A2\uA9A3\uA9A4\uA9A5\uA9A6\uA9A7\uA9A8\uA9A9\uA9AA\uA9AB\uA9AC\uA9AD\uA9AE\uA9AF\uA9B0\uA9B1\uA9B2\uA9CF\uAA60\uAA61\uAA62\uAA63\uAA64\uAA65\uAA66\uAA67\uAA68\uAA69\uAA6A\uAA6B\uAA6C\uAA6D\uAA6E\uAA6F\uAA70\uAA71\uAA72\uAA73\uAA74\uAA75\uAA76\uAA7A\uAA80\uAA81\uAA82\uAA83\uAA84\uAA85\uAA86\uAA87\uAA88\uAA89\uAA8A\uAA8B\uAA8C\uAA8D\uAA8E\uAA8F\uAA90\uAA91\uAA92\uAA93\uAA94\uAA95\uAA96\uAA97\uAA98\uAA99\uAA9A\uAA9B\uAA9C\uAA9D\uAA9E\uAA9F\uAAA0\uAAA1\uAAA2\uAAA3\uAAA4\uAAA5\uAAA6\uAAA7\uAAA8\uAAA9\uAAAA\uAAAB\uAAAC\uAAAD\uAAAE\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9\uAABA\uAABB\uAABC\uAABD\uAAC0\uAAC2\uAADB\uAADC\uAADD\uABC0\uABC1\uABC2\uABC3\uABC4\uABC5\uABC6\uABC7\uABC8\uABC9\uABCA\uABCB\uABCC\uABCD\uABCE\uABCF\uABD0\uABD1\uABD2\uABD3\uABD4\uABD5\uABD6\uABD7\uABD8\uABD9\uABDA\uABDB\uABDC\uABDD\uABDE\uABDF\uABE0\uABE1\uABE2\uD7B0\uD7B1\uD7B2\uD7B3\uD7B4\uD7B5\uD7B6\uD7B7\uD7B8\uD7B9\uD7BA\uD7BB\uD7BC\uD7BD\uD7BE\uD7BF\uD7C0\uD7C1\uD7C2\uD7C3\uD7C4\uD7C5\uD7C6\uD7CB\uD7CC\uD7CD\uD7CE\uD7CF\uD7D0\uD7D1\uD7D2\uD7D3\uD7D4\uD7D5\uD7D6\uD7D7\uD7D8\uD7D9\uD7DA\uD7DB\uD7DC\uD7DD\uD7DE\uD7DF\uD7E0\uD7E1\uD7E2\uD7E3\uD7E4\uD7E5\uD7E6\uD7E7\uD7E8\uD7E9\uD7EA\uD7EB\uD7EC\uD7ED\uD7EE\uD7EF\uD7F0\uD7F1\uD7F2\uD7F3\uD7F4\uD7F5\uD7F6\uD7F7\uD7F8\uD7F9\uD7FA\uD7FB\uFA6B\uFA6C\uFA6D\u{10840}\u{10841}\u{10842}\u{10843}\u{10844}\u{10845}\u{10846}\u{10847}\u{10848}\u{10849}\u{1084A}\u{1084B}\u{1084C}\u{1084D}\u{1084E}\u{1084F}\u{10850}\u{10851}\u{10852}\u{10853}\u{10854}\u{10855}\u{10A60}\u{10A61}\u{10A62}\u{10A63}\u{10A64}\u{10A65}\u{10A66}\u{10A67}\u{10A68}\u{10A69}\u{10A6A}\u{10A6B}\u{10A6C}\u{10A6D}\u{10A6E}\u{10A6F}\u{10A70}\u{10A71}\u{10A72}\u{10A73}\u{10A74}\u{10A75}\u{10A76}\u{10A77}\u{10A78}\u{10A79}\u{10A7A}\u{10A7B}\u{10A7C}\u{10B00}\u{10B01}\u{10B02}\u{10B03}\u{10B04}\u{10B05}\u{10B06}\u{10B07}\u{10B08}\u{10B09}\u{10B0A}\u{10B0B}\u{10B0C}\u{10B0D}\u{10B0E}\u{10B0F}\u{10B10}\u{10B11}\u{10B12}\u{10B13}\u{10B14}\u{10B15}\u{10B16}\u{10B17}\u{10B18}\u{10B19}\u{10B1A}\u{10B1B}\u{10B1C}\u{10B1D}\u{10B1E}\u{10B1F}\u{10B20}\u{10B21}\u{10B22}\u{10B23}\u{10B24}\u{10B25}\u{10B26}\u{10B27}\u{10B28}\u{10B29}\u{10B2A}\u{10B2B}\u{10B2C}\u{10B2D}\u{10B2E}\u{10B2F}\u{10B30}\u{10B31}\u{10B32}\u{10B33}\u{10B34}\u{10B35}\u{10B40}\u{10B41}\u{10B42}\u{10B43}\u{10B44}\u{10B45}\u{10B46}\u{10B47}\u{10B48}\u{10B49}\u{10B4A}\u{10B4B}\u{10B4C}\u{10B4D}\u{10B4E}\u{10B4F}\u{10B50}\u{10B51}\u{10B52}\u{10B53}\u{10B54}\u{10B55}\u{10B60}\u{10B61}\u{10B62}\u{10B63}\u{10B64}\u{10B65}\u{10B66}\u{10B67}\u{10B68}\u{10B69}\u{10B6A}\u{10B6B}\u{10B6C}\u{10B6D}\u{10B6E}\u{10B6F}\u{10B70}\u{10B71}\u{10B72}\u{10C00}\u{10C01}\u{10C02}\u{10C03}\u{10C04}\u{10C05}\u{10C06}\u{10C07}\u{10C08}\u{10C09}\u{10C0A}\u{10C0B}\u{10C0C}\u{10C0D}\u{10C0E}\u{10C0F}\u{10C10}\u{10C11}\u{10C12}\u{10C13}\u{10C14}\u{10C15}\u{10C16}\u{10C17}\u{10C18}\u{10C19}\u{10C1A}\u{10C1B}\u{10C1C}\u{10C1D}\u{10C1E}\u{10C1F}\u{10C20}\u{10C21}\u{10C22}\u{10C23}\u{10C24}\u{10C25}\u{10C26}\u{10C27}\u{10C28}\u{10C29}\u{10C2A}\u{10C2B}\u{10C2C}\u{10C2D}\u{10C2E}\u{10C2F}\u{10C30}\u{10C31}\u{10C32}\u{10C33}\u{10C34}\u{10C35}\u{10C36}\u{10C37}\u{10C38}\u{10C39}\u{10C3A}\u{10C3B}\u{10C3C}\u{10C3D}\u{10C3E}\u{10C3F}\u{10C40}\u{10C41}\u{10C42}\u{10C43}\u{10C44}\u{10C45}\u{10C46}\u{10C47}\u{10C48}\u{11083}\u{11084}\u{11085}\u{11086}\u{11087}\u{11088}\u{11089}\u{1108A}\u{1108B}\u{1108C}\u{1108D}\u{1108E}\u{1108F}\u{11090}\u{11091}\u{11092}\u{11093}\u{11094}\u{11095}\u{11096}\u{11097}\u{11098}\u{11099}\u{1109A}\u{1109B}\u{1109C}\u{1109D}\u{1109E}\u{1109F}\u{110A0}\u{110A1}\u{110A2}\u{110A3}\u{110A4}\u{110A5}\u{110A6}\u{110A7}\u{110A8}\u{110A9}\u{110AA}\u{110AB}\u{110AC}\u{110AD}\u{110AE}\u{110AF}\u{13000}\u{13001}\u{13002}\u{13003}\u{13004}\u{13005}\u{13006}\u{13007}\u{13008}\u{13009}\u{1300A}\u{1300B}\u{1300C}\u{1300D}\u{1300E}\u{1300F}\u{13010}\u{13011}\u{13012}\u{13013}\u{13014}\u{13015}\u{13016}\u{13017}\u{13018}\u{13019}\u{1301A}\u{1301B}\u{1301C}\u{1301D}\u{1301E}\u{1301F}\u{13020}\u{13021}\u{13022}\u{13023}\u{13024}\u{13025}\u{13026}\u{13027}\u{13028}\u{13029}\u{1302A}\u{1302B}\u{1302C}\u{1302D}\u{1302E}\u{1302F}\u{13030}\u{13031}\u{13032}\u{13033}\u{13034}\u{13035}\u{13036}\u{13037}\u{13038}\u{13039}\u{1303A}\u{1303B}\u{1303C}\u{1303D}\u{1303E}\u{1303F}\u{13040}\u{13041}\u{13042}\u{13043}\u{13044}\u{13045}\u{13046}\u{13047}\u{13048}\u{13049}\u{1304A}\u{1304B}\u{1304C}\u{1304D}\u{1304E}\u{1304F}\u{13050}\u{13051}\u{13052}\u{13053}\u{13054}\u{13055}\u{13056}\u{13057}\u{13058}\u{13059}\u{1305A}\u{1305B}\u{1305C}\u{1305D}\u{1305E}\u{1305F}\u{13060}\u{13061}\u{13062}\u{13063}\u{13064}\u{13065}\u{13066}\u{13067}\u{13068}\u{13069}\u{1306A}\u{1306B}\u{1306C}\u{1306D}\u{1306E}\u{1306F}\u{13070}\u{13071}\u{13072}\u{13073}\u{13074}\u{13075}\u{13076}\u{13077}\u{13078}\u{13079}\u{1307A}\u{1307B}\u{1307C}\u{1307D}\u{1307E}\u{1307F}\u{13080}\u{13081}\u{13082}\u{13083}\u{13084}\u{13085}\u{13086}\u{13087}\u{13088}\u{13089}\u{1308A}\u{1308B}\u{1308C}\u{1308D}\u{1308E}\u{1308F}\u{13090}\u{13091}\u{13092}\u{13093}\u{13094}\u{13095}\u{13096}\u{13097}\u{13098}\u{13099}\u{1309A}\u{1309B}\u{1309C}\u{1309D}\u{1309E}\u{1309F}\u{130A0}\u{130A1}\u{130A2}\u{130A3}\u{130A4}\u{130A5}\u{130A6}\u{130A7}\u{130A8}\u{130A9}\u{130AA}\u{130AB}\u{130AC}\u{130AD}\u{130AE}\u{130AF}\u{130B0}\u{130B1}\u{130B2}\u{130B3}\u{130B4}\u{130B5}\u{130B6}\u{130B7}\u{130B8}\u{130B9}\u{130BA}\u{130BB}\u{130BC}\u{130BD}\u{130BE}\u{130BF}\u{130C0}\u{130C1}\u{130C2}\u{130C3}\u{130C4}\u{130C5}\u{130C6}\u{130C7}\u{130C8}\u{130C9}\u{130CA}\u{130CB}\u{130CC}\u{130CD}\u{130CE}\u{130CF}\u{130D0}\u{130D1}\u{130D2}\u{130D3}\u{130D4}\u{130D5}\u{130D6}\u{130D7}\u{130D8}\u{130D9}\u{130DA}\u{130DB}\u{130DC}\u{130DD}\u{130DE}\u{130DF}\u{130E0}\u{130E1}\u{130E2}\u{130E3}\u{130E4}\u{130E5}\u{130E6}\u{130E7}\u{130E8}\u{130E9}\u{130EA}\u{130EB}\u{130EC}\u{130ED}\u{130EE}\u{130EF}\u{130F0}\u{130F1}\u{130F2}\u{130F3}\u{130F4}\u{130F5}\u{130F6}\u{130F7}\u{130F8}\u{130F9}\u{130FA}\u{130FB}\u{130FC}\u{130FD}\u{130FE}\u{130FF}\u{13100}\u{13101}\u{13102}\u{13103}\u{13104}\u{13105}\u{13106}\u{13107}\u{13108}\u{13109}\u{1310A}\u{1310B}\u{1310C}\u{1310D}\u{1310E}\u{1310F}\u{13110}\u{13111}\u{13112}\u{13113}\u{13114}\u{13115}\u{13116}\u{13117}\u{13118}\u{13119}\u{1311A}\u{1311B}\u{1311C}\u{1311D}\u{1311E}\u{1311F}\u{13120}\u{13121}\u{13122}\u{13123}\u{13124}\u{13125}\u{13126}\u{13127}\u{13128}\u{13129}\u{1312A}\u{1312B}\u{1312C}\u{1312D}\u{1312E}\u{1312F}\u{13130}\u{13131}\u{13132}\u{13133}\u{13134}\u{13135}\u{13136}\u{13137}\u{13138}\u{13139}\u{1313A}\u{1313B}\u{1313C}\u{1313D}\u{1313E}\u{1313F}\u{13140}\u{13141}\u{13142}\u{13143}\u{13144}\u{13145}\u{13146}\u{13147}\u{13148}\u{13149}\u{1314A}\u{1314B}\u{1314C}\u{1314D}\u{1314E}\u{1314F}\u{13150}\u{13151}\u{13152}\u{13153}\u{13154}\u{13155}\u{13156}\u{13157}\u{13158}\u{13159}\u{1315A}\u{1315B}\u{1315C}\u{1315D}\u{1315E}\u{1315F}\u{13160}\u{13161}\u{13162}\u{13163}\u{13164}\u{13165}\u{13166}\u{13167}\u{13168}\u{13169}\u{1316A}\u{1316B}\u{1316C}\u{1316D}\u{1316E}\u{1316F}\u{13170}\u{13171}\u{13172}\u{13173}\u{13174}\u{13175}\u{13176}\u{13177}\u{13178}\u{13179}\u{1317A}\u{1317B}\u{1317C}\u{1317D}\u{1317E}\u{1317F}\u{13180}\u{13181}\u{13182}\u{13183}\u{13184}\u{13185}\u{13186}\u{13187}\u{13188}\u{13189}\u{1318A}\u{1318B}\u{1318C}\u{1318D}\u{1318E}\u{1318F}\u{13190}\u{13191}\u{13192}\u{13193}\u{13194}\u{13195}\u{13196}\u{13197}\u{13198}\u{13199}\u{1319A}\u{1319B}\u{1319C}\u{1319D}\u{1319E}\u{1319F}\u{131A0}\u{131A1}\u{131A2}\u{131A3}\u{131A4}\u{131A5}\u{131A6}\u{131A7}\u{131A8}\u{131A9}\u{131AA}\u{131AB}\u{131AC}\u{131AD}\u{131AE}\u{131AF}\u{131B0}\u{131B1}\u{131B2}\u{131B3}\u{131B4}\u{131B5}\u{131B6}\u{131B7}\u{131B8}\u{131B9}\u{131BA}\u{131BB}\u{131BC}\u{131BD}\u{131BE}\u{131BF}\u{131C0}\u{131C1}\u{131C2}\u{131C3}\u{131C4}\u{131C5}\u{131C6}\u{131C7}\u{131C8}\u{131C9}\u{131CA}\u{131CB}\u{131CC}\u{131CD}\u{131CE}\u{131CF}\u{131D0}\u{131D1}\u{131D2}\u{131D3}\u{131D4}\u{131D5}\u{131D6}\u{131D7}\u{131D8}\u{131D9}\u{131DA}\u{131DB}\u{131DC}\u{131DD}\u{131DE}\u{131DF}\u{131E0}\u{131E1}\u{131E2}\u{131E3}\u{131E4}\u{131E5}\u{131E6}\u{131E7}\u{131E8}\u{131E9}\u{131EA}\u{131EB}\u{131EC}\u{131ED}\u{131EE}\u{131EF}\u{131F0}\u{131F1}\u{131F2}\u{131F3}\u{131F4}\u{131F5}\u{131F6}\u{131F7}\u{131F8}\u{131F9}\u{131FA}\u{131FB}\u{131FC}\u{131FD}\u{131FE}\u{131FF}\u{13200}\u{13201}\u{13202}\u{13203}\u{13204}\u{13205}\u{13206}\u{13207}\u{13208}\u{13209}\u{1320A}\u{1320B}\u{1320C}\u{1320D}\u{1320E}\u{1320F}\u{13210}\u{13211}\u{13212}\u{13213}\u{13214}\u{13215}\u{13216}\u{13217}\u{13218}\u{13219}\u{1321A}\u{1321B}\u{1321C}\u{1321D}\u{1321E}\u{1321F}\u{13220}\u{13221}\u{13222}\u{13223}\u{13224}\u{13225}\u{13226}\u{13227}\u{13228}\u{13229}\u{1322A}\u{1322B}\u{1322C}\u{1322D}\u{1322E}\u{1322F}\u{13230}\u{13231}\u{13232}\u{13233}\u{13234}\u{13235}\u{13236}\u{13237}\u{13238}\u{13239}\u{1323A}\u{1323B}\u{1323C}\u{1323D}\u{1323E}\u{1323F}\u{13240}\u{13241}\u{13242}\u{13243}\u{13244}\u{13245}\u{13246}\u{13247}\u{13248}\u{13249}\u{1324A}\u{1324B}\u{1324C}\u{1324D}\u{1324E}\u{1324F}\u{13250}\u{13251}\u{13252}\u{13253}\u{13254}\u{13255}\u{13256}\u{13257}\u{13258}\u{13259}\u{1325A}\u{1325B}\u{1325C}\u{1325D}\u{1325E}\u{1325F}\u{13260}\u{13261}\u{13262}\u{13263}\u{13264}\u{13265}\u{13266}\u{13267}\u{13268}\u{13269}\u{1326A}\u{1326B}\u{1326C}\u{1326D}\u{1326E}\u{1326F}\u{13270}\u{13271}\u{13272}\u{13273}\u{13274}\u{13275}\u{13276}\u{13277}\u{13278}\u{13279}\u{1327A}\u{1327B}\u{1327C}\u{1327D}\u{1327E}\u{1327F}\u{13280}\u{13281}\u{13282}\u{13283}\u{13284}\u{13285}\u{13286}\u{13287}\u{13288}\u{13289}\u{1328A}\u{1328B}\u{1328C}\u{1328D}\u{1328E}\u{1328F}\u{13290}\u{13291}\u{13292}\u{13293}\u{13294}\u{13295}\u{13296}\u{13297}\u{13298}\u{13299}\u{1329A}\u{1329B}\u{1329C}\u{1329D}\u{1329E}\u{1329F}\u{132A0}\u{132A1}\u{132A2}\u{132A3}\u{132A4}\u{132A5}\u{132A6}\u{132A7}\u{132A8}\u{132A9}\u{132AA}\u{132AB}\u{132AC}\u{132AD}\u{132AE}\u{132AF}\u{132B0}\u{132B1}\u{132B2}\u{132B3}\u{132B4}\u{132B5}\u{132B6}\u{132B7}\u{132B8}\u{132B9}\u{132BA}\u{132BB}\u{132BC}\u{132BD}\u{132BE}\u{132BF}\u{132C0}\u{132C1}\u{132C2}\u{132C3}\u{132C4}\u{132C5}\u{132C6}\u{132C7}\u{132C8}\u{132C9}\u{132CA}\u{132CB}\u{132CC}\u{132CD}\u{132CE}\u{132CF}\u{132D0}\u{132D1}\u{132D2}\u{132D3}\u{132D4}\u{132D5}\u{132D6}\u{132D7}\u{132D8}\u{132D9}\u{132DA}\u{132DB}\u{132DC}\u{132DD}\u{132DE}\u{132DF}\u{132E0}\u{132E1}\u{132E2}\u{132E3}\u{132E4}\u{132E5}\u{132E6}\u{132E7}\u{132E8}\u{132E9}\u{132EA}\u{132EB}\u{132EC}\u{132ED}\u{132EE}\u{132EF}\u{132F0}\u{132F1}\u{132F2}\u{132F3}\u{132F4}\u{132F5}\u{132F6}\u{132F7}\u{132F8}\u{132F9}\u{132FA}\u{132FB}\u{132FC}\u{132FD}\u{132FE}\u{132FF}\u{13300}\u{13301}\u{13302}\u{13303}\u{13304}\u{13305}\u{13306}\u{13307}\u{13308}\u{13309}\u{1330A}\u{1330B}\u{1330C}\u{1330D}\u{1330E}\u{1330F}\u{13310}\u{13311}\u{13312}\u{13313}\u{13314}\u{13315}\u{13316}\u{13317}\u{13318}\u{13319}\u{1331A}\u{1331B}\u{1331C}\u{1331D}\u{1331E}\u{1331F}\u{13320}\u{13321}\u{13322}\u{13323}\u{13324}\u{13325}\u{13326}\u{13327}\u{13328}\u{13329}\u{1332A}\u{1332B}\u{1332C}\u{1332D}\u{1332E}\u{1332F}\u{13330}\u{13331}\u{13332}\u{13333}\u{13334}\u{13335}\u{13336}\u{13337}\u{13338}\u{13339}\u{1333A}\u{1333B}\u{1333C}\u{1333D}\u{1333E}\u{1333F}\u{13340}\u{13341}\u{13342}\u{13343}\u{13344}\u{13345}\u{13346}\u{13347}\u{13348}\u{13349}\u{1334A}\u{1334B}\u{1334C}\u{1334D}\u{1334E}\u{1334F}\u{13350}\u{13351}\u{13352}\u{13353}\u{13354}\u{13355}\u{13356}\u{13357}\u{13358}\u{13359}\u{1335A}\u{1335B}\u{1335C}\u{1335D}\u{1335E}\u{1335F}\u{13360}\u{13361}\u{13362}\u{13363}\u{13364}\u{13365}\u{13366}\u{13367}\u{13368}\u{13369}\u{1336A}\u{1336B}\u{1336C}\u{1336D}\u{1336E}\u{1336F}\u{13370}\u{13371}\u{13372}\u{13373}\u{13374}\u{13375}\u{13376}\u{13377}\u{13378}\u{13379}\u{1337A}\u{1337B}\u{1337C}\u{1337D}\u{1337E}\u{1337F}\u{13380}\u{13381}\u{13382}\u{13383}\u{13384}\u{13385}\u{13386}\u{13387}\u{13388}\u{13389}\u{1338A}\u{1338B}\u{1338C}\u{1338D}\u{1338E}\u{1338F}\u{13390}\u{13391}\u{13392}\u{13393}\u{13394}\u{13395}\u{13396}\u{13397}\u{13398}\u{13399}\u{1339A}\u{1339B}\u{1339C}\u{1339D}\u{1339E}\u{1339F}\u{133A0}\u{133A1}\u{133A2}\u{133A3}\u{133A4}\u{133A5}\u{133A6}\u{133A7}\u{133A8}\u{133A9}\u{133AA}\u{133AB}\u{133AC}\u{133AD}\u{133AE}\u{133AF}\u{133B0}\u{133B1}\u{133B2}\u{133B3}\u{133B4}\u{133B5}\u{133B6}\u{133B7}\u{133B8}\u{133B9}\u{133BA}\u{133BB}\u{133BC}\u{133BD}\u{133BE}\u{133BF}\u{133C0}\u{133C1}\u{133C2}\u{133C3}\u{133C4}\u{133C5}\u{133C6}\u{133C7}\u{133C8}\u{133C9}\u{133CA}\u{133CB}\u{133CC}\u{133CD}\u{133CE}\u{133CF}\u{133D0}\u{133D1}\u{133D2}\u{133D3}\u{133D4}\u{133D5}\u{133D6}\u{133D7}\u{133D8}\u{133D9}\u{133DA}\u{133DB}\u{133DC}\u{133DD}\u{133DE}\u{133DF}\u{133E0}\u{133E1}\u{133E2}\u{133E3}\u{133E4}\u{133E5}\u{133E6}\u{133E7}\u{133E8}\u{133E9}\u{133EA}\u{133EB}\u{133EC}\u{133ED}\u{133EE}\u{133EF}\u{133F0}\u{133F1}\u{133F2}\u{133F3}\u{133F4}\u{133F5}\u{133F6}\u{133F7}\u{133F8}\u{133F9}\u{133FA}\u{133FB}\u{133FC}\u{133FD}\u{133FE}\u{133FF}\u{13400}\u{13401}\u{13402}\u{13403}\u{13404}\u{13405}\u{13406}\u{13407}\u{13408}\u{13409}\u{1340A}\u{1340B}\u{1340C}\u{1340D}\u{1340E}\u{1340F}\u{13410}\u{13411}\u{13412}\u{13413}\u{13414}\u{13415}\u{13416}\u{13417}\u{13418}\u{13419}\u{1341A}\u{1341B}\u{1341C}\u{1341D}\u{1341E}\u{1341F}\u{13420}\u{13421}\u{13422}\u{13423}\u{13424}\u{13425}\u{13426}\u{13427}\u{13428}\u{13429}\u{1342A}\u{1342B}\u{1342C}\u{1342D}\u{1342E}\u{2A700}\u{2A701}\u{2A702}\u{2A703}\u{2A704}\u{2A705}\u{2A706}\u{2A707}\u{2A708}\u{2A709}\u{2A70A}\u{2A70B}\u{2A70C}\u{2A70D}\u{2A70E}\u{2A70F}\u{2A710}\u{2A711}\u{2A712}\u{2A713}\u{2A714}\u{2A715}\u{2A716}\u{2A717}\u{2A718}\u{2A719}\u{2A71A}\u{2A71B}\u{2A71C}\u{2A71D}\u{2A71E}\u{2A71F}\u{2A720}\u{2A721}\u{2A722}\u{2A723}\u{2A724}\u{2A725}\u{2A726}\u{2A727}\u{2A728}\u{2A729}\u{2A72A}\u{2A72B}\u{2A72C}\u{2A72D}\u{2A72E}\u{2A72F}\u{2A730}\u{2A731}\u{2A732}\u{2A733}\u{2A734}\u{2A735}\u{2A736}\u{2A737}\u{2A738}\u{2A739}\u{2A73A}\u{2A73B}\u{2A73C}\u{2A73D}\u{2A73E}\u{2A73F}\u{2A740}\u{2A741}\u{2A742}\u{2A743}\u{2A744}\u{2A745}\u{2A746}\u{2A747}\u{2A748}\u{2A749}\u{2A74A}\u{2A74B}\u{2A74C}\u{2A74D}\u{2A74E}\u{2A74F}\u{2A750}\u{2A751}\u{2A752}\u{2A753}\u{2A754}\u{2A755}\u{2A756}\u{2A757}\u{2A758}\u{2A759}\u{2A75A}\u{2A75B}\u{2A75C}\u{2A75D}\u{2A75E}\u{2A75F}\u{2A760}\u{2A761}\u{2A762}\u{2A763}\u{2A764}\u{2A765}\u{2A766}\u{2A767}\u{2A768}\u{2A769}\u{2A76A}\u{2A76B}\u{2A76C}\u{2A76D}\u{2A76E}\u{2A76F}\u{2A770}\u{2A771}\u{2A772}\u{2A773}\u{2A774}\u{2A775}\u{2A776}\u{2A777}\u{2A778}\u{2A779}\u{2A77A}\u{2A77B}\u{2A77C}\u{2A77D}\u{2A77E}\u{2A77F}\u{2A780}\u{2A781}\u{2A782}\u{2A783}\u{2A784}\u{2A785}\u{2A786}\u{2A787}\u{2A788}\u{2A789}\u{2A78A}\u{2A78B}\u{2A78C}\u{2A78D}\u{2A78E}\u{2A78F}\u{2A790}\u{2A791}\u{2A792}\u{2A793}\u{2A794}\u{2A795}\u{2A796}\u{2A797}\u{2A798}\u{2A799}\u{2A79A}\u{2A79B}\u{2A79C}\u{2A79D}\u{2A79E}\u{2A79F}\u{2A7A0}\u{2A7A1}\u{2A7A2}\u{2A7A3}\u{2A7A4}\u{2A7A5}\u{2A7A6}\u{2A7A7}\u{2A7A8}\u{2A7A9}\u{2A7AA}\u{2A7AB}\u{2A7AC}\u{2A7AD}\u{2A7AE}\u{2A7AF}\u{2A7B0}\u{2A7B1}\u{2A7B2}\u{2A7B3}\u{2A7B4}\u{2A7B5}\u{2A7B6}\u{2A7B7}\u{2A7B8}\u{2A7B9}\u{2A7BA}\u{2A7BB}\u{2A7BC}\u{2A7BD}\u{2A7BE}\u{2A7BF}\u{2A7C0}\u{2A7C1}\u{2A7C2}\u{2A7C3}\u{2A7C4}\u{2A7C5}\u{2A7C6}\u{2A7C7}\u{2A7C8}\u{2A7C9}\u{2A7CA}\u{2A7CB}\u{2A7CC}\u{2A7CD}\u{2A7CE}\u{2A7CF}\u{2A7D0}\u{2A7D1}\u{2A7D2}\u{2A7D3}\u{2A7D4}\u{2A7D5}\u{2A7D6}\u{2A7D7}\u{2A7D8}\u{2A7D9}\u{2A7DA}\u{2A7DB}\u{2A7DC}\u{2A7DD}\u{2A7DE}\u{2A7DF}\u{2A7E0}\u{2A7E1}\u{2A7E2}\u{2A7E3}\u{2A7E4}\u{2A7E5}\u{2A7E6}\u{2A7E7}\u{2A7E8}\u{2A7E9}\u{2A7EA}\u{2A7EB}\u{2A7EC}\u{2A7ED}\u{2A7EE}\u{2A7EF}\u{2A7F0}\u{2A7F1}\u{2A7F2}\u{2A7F3}\u{2A7F4}\u{2A7F5}\u{2A7F6}\u{2A7F7}\u{2A7F8}\u{2A7F9}\u{2A7FA}\u{2A7FB}\u{2A7FC}\u{2A7FD}\u{2A7FE}\u{2A7FF}\u{2A800}\u{2A801}\u{2A802}\u{2A803}\u{2A804}\u{2A805}\u{2A806}\u{2A807}\u{2A808}\u{2A809}\u{2A80A}\u{2A80B}\u{2A80C}\u{2A80D}\u{2A80E}\u{2A80F}\u{2A810}\u{2A811}\u{2A812}\u{2A813}\u{2A814}\u{2A815}\u{2A816}\u{2A817}\u{2A818}\u{2A819}\u{2A81A}\u{2A81B}\u{2A81C}\u{2A81D}\u{2A81E}\u{2A81F}\u{2A820}\u{2A821}\u{2A822}\u{2A823}\u{2A824}\u{2A825}\u{2A826}\u{2A827}\u{2A828}\u{2A829}\u{2A82A}\u{2A82B}\u{2A82C}\u{2A82D}\u{2A82E}\u{2A82F}\u{2A830}\u{2A831}\u{2A832}\u{2A833}\u{2A834}\u{2A835}\u{2A836}\u{2A837}\u{2A838}\u{2A839}\u{2A83A}\u{2A83B}\u{2A83C}\u{2A83D}\u{2A83E}\u{2A83F}\u{2A840}\u{2A841}\u{2A842}\u{2A843}\u{2A844}\u{2A845}\u{2A846}\u{2A847}\u{2A848}\u{2A849}\u{2A84A}\u{2A84B}\u{2A84C}\u{2A84D}\u{2A84E}\u{2A84F}\u{2A850}\u{2A851}\u{2A852}\u{2A853}\u{2A854}\u{2A855}\u{2A856}\u{2A857}\u{2A858}\u{2A859}\u{2A85A}\u{2A85B}\u{2A85C}\u{2A85D}\u{2A85E}\u{2A85F}\u{2A860}\u{2A861}\u{2A862}\u{2A863}\u{2A864}\u{2A865}\u{2A866}\u{2A867}\u{2A868}\u{2A869}\u{2A86A}\u{2A86B}\u{2A86C}\u{2A86D}\u{2A86E}\u{2A86F}\u{2A870}\u{2A871}\u{2A872}\u{2A873}\u{2A874}\u{2A875}\u{2A876}\u{2A877}\u{2A878}\u{2A879}\u{2A87A}\u{2A87B}\u{2A87C}\u{2A87D}\u{2A87E}\u{2A87F}\u{2A880}\u{2A881}\u{2A882}\u{2A883}\u{2A884}\u{2A885}\u{2A886}\u{2A887}\u{2A888}\u{2A889}\u{2A88A}\u{2A88B}\u{2A88C}\u{2A88D}\u{2A88E}\u{2A88F}\u{2A890}\u{2A891}\u{2A892}\u{2A893}\u{2A894}\u{2A895}\u{2A896}\u{2A897}\u{2A898}\u{2A899}\u{2A89A}\u{2A89B}\u{2A89C}\u{2A89D}\u{2A89E}\u{2A89F}\u{2A8A0}\u{2A8A1}\u{2A8A2}\u{2A8A3}\u{2A8A4}\u{2A8A5}\u{2A8A6}\u{2A8A7}\u{2A8A8}\u{2A8A9}\u{2A8AA}\u{2A8AB}\u{2A8AC}\u{2A8AD}\u{2A8AE}\u{2A8AF}\u{2A8B0}\u{2A8B1}\u{2A8B2}\u{2A8B3}\u{2A8B4}\u{2A8B5}\u{2A8B6}\u{2A8B7}\u{2A8B8}\u{2A8B9}\u{2A8BA}\u{2A8BB}\u{2A8BC}\u{2A8BD}\u{2A8BE}\u{2A8BF}\u{2A8C0}\u{2A8C1}\u{2A8C2}\u{2A8C3}\u{2A8C4}\u{2A8C5}\u{2A8C6}\u{2A8C7}\u{2A8C8}\u{2A8C9}\u{2A8CA}\u{2A8CB}\u{2A8CC}\u{2A8CD}\u{2A8CE}\u{2A8CF}\u{2A8D0}\u{2A8D1}\u{2A8D2}\u{2A8D3}\u{2A8D4}\u{2A8D5}\u{2A8D6}\u{2A8D7}\u{2A8D8}\u{2A8D9}\u{2A8DA}\u{2A8DB}\u{2A8DC}\u{2A8DD}\u{2A8DE}\u{2A8DF}\u{2A8E0}\u{2A8E1}\u{2A8E2}\u{2A8E3}\u{2A8E4}\u{2A8E5}\u{2A8E6}\u{2A8E7}\u{2A8E8}\u{2A8E9}\u{2A8EA}\u{2A8EB}\u{2A8EC}\u{2A8ED}\u{2A8EE}\u{2A8EF}\u{2A8F0}\u{2A8F1}\u{2A8F2}\u{2A8F3}\u{2A8F4}\u{2A8F5}\u{2A8F6}\u{2A8F7}\u{2A8F8}\u{2A8F9}\u{2A8FA}\u{2A8FB}\u{2A8FC}\u{2A8FD}\u{2A8FE}\u{2A8FF}\u{2A900}\u{2A901}\u{2A902}\u{2A903}\u{2A904}\u{2A905}\u{2A906}\u{2A907}\u{2A908}\u{2A909}\u{2A90A}\u{2A90B}\u{2A90C}\u{2A90D}\u{2A90E}\u{2A90F}\u{2A910}\u{2A911}\u{2A912}\u{2A913}\u{2A914}\u{2A915}\u{2A916}\u{2A917}\u{2A918}\u{2A919}\u{2A91A}\u{2A91B}\u{2A91C}\u{2A91D}\u{2A91E}\u{2A91F}\u{2A920}\u{2A921}\u{2A922}\u{2A923}\u{2A924}\u{2A925}\u{2A926}\u{2A927}\u{2A928}\u{2A929}\u{2A92A}\u{2A92B}\u{2A92C}\u{2A92D}\u{2A92E}\u{2A92F}\u{2A930}\u{2A931}\u{2A932}\u{2A933}\u{2A934}\u{2A935}\u{2A936}\u{2A937}\u{2A938}\u{2A939}\u{2A93A}\u{2A93B}\u{2A93C}\u{2A93D}\u{2A93E}\u{2A93F}\u{2A940}\u{2A941}\u{2A942}\u{2A943}\u{2A944}\u{2A945}\u{2A946}\u{2A947}\u{2A948}\u{2A949}\u{2A94A}\u{2A94B}\u{2A94C}\u{2A94D}\u{2A94E}\u{2A94F}\u{2A950}\u{2A951}\u{2A952}\u{2A953}\u{2A954}\u{2A955}\u{2A956}\u{2A957}\u{2A958}\u{2A959}\u{2A95A}\u{2A95B}\u{2A95C}\u{2A95D}\u{2A95E}\u{2A95F}\u{2A960}\u{2A961}\u{2A962}\u{2A963}\u{2A964}\u{2A965}\u{2A966}\u{2A967}\u{2A968}\u{2A969}\u{2A96A}\u{2A96B}\u{2A96C}\u{2A96D}\u{2A96E}\u{2A96F}\u{2A970}\u{2A971}\u{2A972}\u{2A973}\u{2A974}\u{2A975}\u{2A976}\u{2A977}\u{2A978}\u{2A979}\u{2A97A}\u{2A97B}\u{2A97C}\u{2A97D}\u{2A97E}\u{2A97F}\u{2A980}\u{2A981}\u{2A982}\u{2A983}\u{2A984}\u{2A985}\u{2A986}\u{2A987}\u{2A988}\u{2A989}\u{2A98A}\u{2A98B}\u{2A98C}\u{2A98D}\u{2A98E}\u{2A98F}\u{2A990}\u{2A991}\u{2A992}\u{2A993}\u{2A994}\u{2A995}\u{2A996}\u{2A997}\u{2A998}\u{2A999}\u{2A99A}\u{2A99B}\u{2A99C}\u{2A99D}\u{2A99E}\u{2A99F}\u{2A9A0}\u{2A9A1}\u{2A9A2}\u{2A9A3}\u{2A9A4}\u{2A9A5}\u{2A9A6}\u{2A9A7}\u{2A9A8}\u{2A9A9}\u{2A9AA}\u{2A9AB}\u{2A9AC}\u{2A9AD}\u{2A9AE}\u{2A9AF}\u{2A9B0}\u{2A9B1}\u{2A9B2}\u{2A9B3}\u{2A9B4}\u{2A9B5}\u{2A9B6}\u{2A9B7}\u{2A9B8}\u{2A9B9}\u{2A9BA}\u{2A9BB}\u{2A9BC}\u{2A9BD}\u{2A9BE}\u{2A9BF}\u{2A9C0}\u{2A9C1}\u{2A9C2}\u{2A9C3}\u{2A9C4}\u{2A9C5}\u{2A9C6}\u{2A9C7}\u{2A9C8}\u{2A9C9}\u{2A9CA}\u{2A9CB}\u{2A9CC}\u{2A9CD}\u{2A9CE}\u{2A9CF}\u{2A9D0}\u{2A9D1}\u{2A9D2}\u{2A9D3}\u{2A9D4}\u{2A9D5}\u{2A9D6}\u{2A9D7}\u{2A9D8}\u{2A9D9}\u{2A9DA}\u{2A9DB}\u{2A9DC}\u{2A9DD}\u{2A9DE}\u{2A9DF}\u{2A9E0}\u{2A9E1}\u{2A9E2}\u{2A9E3}\u{2A9E4}\u{2A9E5}\u{2A9E6}\u{2A9E7}\u{2A9E8}\u{2A9E9}\u{2A9EA}\u{2A9EB}\u{2A9EC}\u{2A9ED}\u{2A9EE}\u{2A9EF}\u{2A9F0}\u{2A9F1}\u{2A9F2}\u{2A9F3}\u{2A9F4}\u{2A9F5}\u{2A9F6}\u{2A9F7}\u{2A9F8}\u{2A9F9}\u{2A9FA}\u{2A9FB}\u{2A9FC}\u{2A9FD}\u{2A9FE}\u{2A9FF}\u{2AA00}\u{2AA01}\u{2AA02}\u{2AA03}\u{2AA04}\u{2AA05}\u{2AA06}\u{2AA07}\u{2AA08}\u{2AA09}\u{2AA0A}\u{2AA0B}\u{2AA0C}\u{2AA0D}\u{2AA0E}\u{2AA0F}\u{2AA10}\u{2AA11}\u{2AA12}\u{2AA13}\u{2AA14}\u{2AA15}\u{2AA16}\u{2AA17}\u{2AA18}\u{2AA19}\u{2AA1A}\u{2AA1B}\u{2AA1C}\u{2AA1D}\u{2AA1E}\u{2AA1F}\u{2AA20}\u{2AA21}\u{2AA22}\u{2AA23}\u{2AA24}\u{2AA25}\u{2AA26}\u{2AA27}\u{2AA28}\u{2AA29}\u{2AA2A}\u{2AA2B}\u{2AA2C}\u{2AA2D}\u{2AA2E}\u{2AA2F}\u{2AA30}\u{2AA31}\u{2AA32}\u{2AA33}\u{2AA34}\u{2AA35}\u{2AA36}\u{2AA37}\u{2AA38}\u{2AA39}\u{2AA3A}\u{2AA3B}\u{2AA3C}\u{2AA3D}\u{2AA3E}\u{2AA3F}\u{2AA40}\u{2AA41}\u{2AA42}\u{2AA43}\u{2AA44}\u{2AA45}\u{2AA46}\u{2AA47}\u{2AA48}\u{2AA49}\u{2AA4A}\u{2AA4B}\u{2AA4C}\u{2AA4D}\u{2AA4E}\u{2AA4F}\u{2AA50}\u{2AA51}\u{2AA52}\u{2AA53}\u{2AA54}\u{2AA55}\u{2AA56}\u{2AA57}\u{2AA58}\u{2AA59}\u{2AA5A}\u{2AA5B}\u{2AA5C}\u{2AA5D}\u{2AA5E}\u{2AA5F}\u{2AA60}\u{2AA61}\u{2AA62}\u{2AA63}\u{2AA64}\u{2AA65}\u{2AA66}\u{2AA67}\u{2AA68}\u{2AA69}\u{2AA6A}\u{2AA6B}\u{2AA6C}\u{2AA6D}\u{2AA6E}\u{2AA6F}\u{2AA70}\u{2AA71}\u{2AA72}\u{2AA73}\u{2AA74}\u{2AA75}\u{2AA76}\u{2AA77}\u{2AA78}\u{2AA79}\u{2AA7A}\u{2AA7B}\u{2AA7C}\u{2AA7D}\u{2AA7E}\u{2AA7F}\u{2AA80}\u{2AA81}\u{2AA82}\u{2AA83}\u{2AA84}\u{2AA85}\u{2AA86}\u{2AA87}\u{2AA88}\u{2AA89}\u{2AA8A}\u{2AA8B}\u{2AA8C}\u{2AA8D}\u{2AA8E}\u{2AA8F}\u{2AA90}\u{2AA91}\u{2AA92}\u{2AA93}\u{2AA94}\u{2AA95}\u{2AA96}\u{2AA97}\u{2AA98}\u{2AA99}\u{2AA9A}\u{2AA9B}\u{2AA9C}\u{2AA9D}\u{2AA9E}\u{2AA9F}\u{2AAA0}\u{2AAA1}\u{2AAA2}\u{2AAA3}\u{2AAA4}\u{2AAA5}\u{2AAA6}\u{2AAA7}\u{2AAA8}\u{2AAA9}\u{2AAAA}\u{2AAAB}\u{2AAAC}\u{2AAAD}\u{2AAAE}\u{2AAAF}\u{2AAB0}\u{2AAB1}\u{2AAB2}\u{2AAB3}\u{2AAB4}\u{2AAB5}\u{2AAB6}\u{2AAB7}\u{2AAB8}\u{2AAB9}\u{2AABA}\u{2AABB}\u{2AABC}\u{2AABD}\u{2AABE}\u{2AABF}\u{2AAC0}\u{2AAC1}\u{2AAC2}\u{2AAC3}\u{2AAC4}\u{2AAC5}\u{2AAC6}\u{2AAC7}\u{2AAC8}\u{2AAC9}\u{2AACA}\u{2AACB}\u{2AACC}\u{2AACD}\u{2AACE}\u{2AACF}\u{2AAD0}\u{2AAD1}\u{2AAD2}\u{2AAD3}\u{2AAD4}\u{2AAD5}\u{2AAD6}\u{2AAD7}\u{2AAD8}\u{2AAD9}\u{2AADA}\u{2AADB}\u{2AADC}\u{2AADD}\u{2AADE}\u{2AADF}\u{2AAE0}\u{2AAE1}\u{2AAE2}\u{2AAE3}\u{2AAE4}\u{2AAE5}\u{2AAE6}\u{2AAE7}\u{2AAE8}\u{2AAE9}\u{2AAEA}\u{2AAEB}\u{2AAEC}\u{2AAED}\u{2AAEE}\u{2AAEF}\u{2AAF0}\u{2AAF1}\u{2AAF2}\u{2AAF3}\u{2AAF4}\u{2AAF5}\u{2AAF6}\u{2AAF7}\u{2AAF8}\u{2AAF9}\u{2AAFA}\u{2AAFB}\u{2AAFC}\u{2AAFD}\u{2AAFE}\u{2AAFF}\u{2AB00}\u{2AB01}\u{2AB02}\u{2AB03}\u{2AB04}\u{2AB05}\u{2AB06}\u{2AB07}\u{2AB08}\u{2AB09}\u{2AB0A}\u{2AB0B}\u{2AB0C}\u{2AB0D}\u{2AB0E}\u{2AB0F}\u{2AB10}\u{2AB11}\u{2AB12}\u{2AB13}\u{2AB14}\u{2AB15}\u{2AB16}\u{2AB17}\u{2AB18}\u{2AB19}\u{2AB1A}\u{2AB1B}\u{2AB1C}\u{2AB1D}\u{2AB1E}\u{2AB1F}\u{2AB20}\u{2AB21}\u{2AB22}\u{2AB23}\u{2AB24}\u{2AB25}\u{2AB26}\u{2AB27}\u{2AB28}\u{2AB29}\u{2AB2A}\u{2AB2B}\u{2AB2C}\u{2AB2D}\u{2AB2E}\u{2AB2F}\u{2AB30}\u{2AB31}\u{2AB32}\u{2AB33}\u{2AB34}\u{2AB35}\u{2AB36}\u{2AB37}\u{2AB38}\u{2AB39}\u{2AB3A}\u{2AB3B}\u{2AB3C}\u{2AB3D}\u{2AB3E}\u{2AB3F}\u{2AB40}\u{2AB41}\u{2AB42}\u{2AB43}\u{2AB44}\u{2AB45}\u{2AB46}\u{2AB47}\u{2AB48}\u{2AB49}\u{2AB4A}\u{2AB4B}\u{2AB4C}\u{2AB4D}\u{2AB4E}\u{2AB4F}\u{2AB50}\u{2AB51}\u{2AB52}\u{2AB53}\u{2AB54}\u{2AB55}\u{2AB56}\u{2AB57}\u{2AB58}\u{2AB59}\u{2AB5A}\u{2AB5B}\u{2AB5C}\u{2AB5D}\u{2AB5E}\u{2AB5F}\u{2AB60}\u{2AB61}\u{2AB62}\u{2AB63}\u{2AB64}\u{2AB65}\u{2AB66}\u{2AB67}\u{2AB68}\u{2AB69}\u{2AB6A}\u{2AB6B}\u{2AB6C}\u{2AB6D}\u{2AB6E}\u{2AB6F}\u{2AB70}\u{2AB71}\u{2AB72}\u{2AB73}\u{2AB74}\u{2AB75}\u{2AB76}\u{2AB77}\u{2AB78}\u{2AB79}\u{2AB7A}\u{2AB7B}\u{2AB7C}\u{2AB7D}\u{2AB7E}\u{2AB7F}\u{2AB80}\u{2AB81}\u{2AB82}\u{2AB83}\u{2AB84}\u{2AB85}\u{2AB86}\u{2AB87}\u{2AB88}\u{2AB89}\u{2AB8A}\u{2AB8B}\u{2AB8C}\u{2AB8D}\u{2AB8E}\u{2AB8F}\u{2AB90}\u{2AB91}\u{2AB92}\u{2AB93}\u{2AB94}\u{2AB95}\u{2AB96}\u{2AB97}\u{2AB98}\u{2AB99}\u{2AB9A}\u{2AB9B}\u{2AB9C}\u{2AB9D}\u{2AB9E}\u{2AB9F}\u{2ABA0}\u{2ABA1}\u{2ABA2}\u{2ABA3}\u{2ABA4}\u{2ABA5}\u{2ABA6}\u{2ABA7}\u{2ABA8}\u{2ABA9}\u{2ABAA}\u{2ABAB}\u{2ABAC}\u{2ABAD}\u{2ABAE}\u{2ABAF}\u{2ABB0}\u{2ABB1}\u{2ABB2}\u{2ABB3}\u{2ABB4}\u{2ABB5}\u{2ABB6}\u{2ABB7}\u{2ABB8}\u{2ABB9}\u{2ABBA}\u{2ABBB}\u{2ABBC}\u{2ABBD}\u{2ABBE}\u{2ABBF}\u{2ABC0}\u{2ABC1}\u{2ABC2}\u{2ABC3}\u{2ABC4}\u{2ABC5}\u{2ABC6}\u{2ABC7}\u{2ABC8}\u{2ABC9}\u{2ABCA}\u{2ABCB}\u{2ABCC}\u{2ABCD}\u{2ABCE}\u{2ABCF}\u{2ABD0}\u{2ABD1}\u{2ABD2}\u{2ABD3}\u{2ABD4}\u{2ABD5}\u{2ABD6}\u{2ABD7}\u{2ABD8}\u{2ABD9}\u{2ABDA}\u{2ABDB}\u{2ABDC}\u{2ABDD}\u{2ABDE}\u{2ABDF}\u{2ABE0}\u{2ABE1}\u{2ABE2}\u{2ABE3}\u{2ABE4}\u{2ABE5}\u{2ABE6}\u{2ABE7}\u{2ABE8}\u{2ABE9}\u{2ABEA}\u{2ABEB}\u{2ABEC}\u{2ABED}\u{2ABEE}\u{2ABEF}\u{2ABF0}\u{2ABF1}\u{2ABF2}\u{2ABF3}\u{2ABF4}\u{2ABF5}\u{2ABF6}\u{2ABF7}\u{2ABF8}\u{2ABF9}\u{2ABFA}\u{2ABFB}\u{2ABFC}\u{2ABFD}\u{2ABFE}\u{2ABFF}\u{2AC00}\u{2AC01}\u{2AC02}\u{2AC03}\u{2AC04}\u{2AC05}\u{2AC06}\u{2AC07}\u{2AC08}\u{2AC09}\u{2AC0A}\u{2AC0B}\u{2AC0C}\u{2AC0D}\u{2AC0E}\u{2AC0F}\u{2AC10}\u{2AC11}\u{2AC12}\u{2AC13}\u{2AC14}\u{2AC15}\u{2AC16}\u{2AC17}\u{2AC18}\u{2AC19}\u{2AC1A}\u{2AC1B}\u{2AC1C}\u{2AC1D}\u{2AC1E}\u{2AC1F}\u{2AC20}\u{2AC21}\u{2AC22}\u{2AC23}\u{2AC24}\u{2AC25}\u{2AC26}\u{2AC27}\u{2AC28}\u{2AC29}\u{2AC2A}\u{2AC2B}\u{2AC2C}\u{2AC2D}\u{2AC2E}\u{2AC2F}\u{2AC30}\u{2AC31}\u{2AC32}\u{2AC33}\u{2AC34}\u{2AC35}\u{2AC36}\u{2AC37}\u{2AC38}\u{2AC39}\u{2AC3A}\u{2AC3B}\u{2AC3C}\u{2AC3D}\u{2AC3E}\u{2AC3F}\u{2AC40}\u{2AC41}\u{2AC42}\u{2AC43}\u{2AC44}\u{2AC45}\u{2AC46}\u{2AC47}\u{2AC48}\u{2AC49}\u{2AC4A}\u{2AC4B}\u{2AC4C}\u{2AC4D}\u{2AC4E}\u{2AC4F}\u{2AC50}\u{2AC51}\u{2AC52}\u{2AC53}\u{2AC54}\u{2AC55}\u{2AC56}\u{2AC57}\u{2AC58}\u{2AC59}\u{2AC5A}\u{2AC5B}\u{2AC5C}\u{2AC5D}\u{2AC5E}\u{2AC5F}\u{2AC60}\u{2AC61}\u{2AC62}\u{2AC63}\u{2AC64}\u{2AC65}\u{2AC66}\u{2AC67}\u{2AC68}\u{2AC69}\u{2AC6A}\u{2AC6B}\u{2AC6C}\u{2AC6D}\u{2AC6E}\u{2AC6F}\u{2AC70}\u{2AC71}\u{2AC72}\u{2AC73}\u{2AC74}\u{2AC75}\u{2AC76}\u{2AC77}\u{2AC78}\u{2AC79}\u{2AC7A}\u{2AC7B}\u{2AC7C}\u{2AC7D}\u{2AC7E}\u{2AC7F}\u{2AC80}\u{2AC81}\u{2AC82}\u{2AC83}\u{2AC84}\u{2AC85}\u{2AC86}\u{2AC87}\u{2AC88}\u{2AC89}\u{2AC8A}\u{2AC8B}\u{2AC8C}\u{2AC8D}\u{2AC8E}\u{2AC8F}\u{2AC90}\u{2AC91}\u{2AC92}\u{2AC93}\u{2AC94}\u{2AC95}\u{2AC96}\u{2AC97}\u{2AC98}\u{2AC99}\u{2AC9A}\u{2AC9B}\u{2AC9C}\u{2AC9D}\u{2AC9E}\u{2AC9F}\u{2ACA0}\u{2ACA1}\u{2ACA2}\u{2ACA3}\u{2ACA4}\u{2ACA5}\u{2ACA6}\u{2ACA7}\u{2ACA8}\u{2ACA9}\u{2ACAA}\u{2ACAB}\u{2ACAC}\u{2ACAD}\u{2ACAE}\u{2ACAF}\u{2ACB0}\u{2ACB1}\u{2ACB2}\u{2ACB3}\u{2ACB4}\u{2ACB5}\u{2ACB6}\u{2ACB7}\u{2ACB8}\u{2ACB9}\u{2ACBA}\u{2ACBB}\u{2ACBC}\u{2ACBD}\u{2ACBE}\u{2ACBF}\u{2ACC0}\u{2ACC1}\u{2ACC2}\u{2ACC3}\u{2ACC4}\u{2ACC5}\u{2ACC6}\u{2ACC7}\u{2ACC8}\u{2ACC9}\u{2ACCA}\u{2ACCB}\u{2ACCC}\u{2ACCD}\u{2ACCE}\u{2ACCF}\u{2ACD0}\u{2ACD1}\u{2ACD2}\u{2ACD3}\u{2ACD4}\u{2ACD5}\u{2ACD6}\u{2ACD7}\u{2ACD8}\u{2ACD9}\u{2ACDA}\u{2ACDB}\u{2ACDC}\u{2ACDD}\u{2ACDE}\u{2ACDF}\u{2ACE0}\u{2ACE1}\u{2ACE2}\u{2ACE3}\u{2ACE4}\u{2ACE5}\u{2ACE6}\u{2ACE7}\u{2ACE8}\u{2ACE9}\u{2ACEA}\u{2ACEB}\u{2ACEC}\u{2ACED}\u{2ACEE}\u{2ACEF}\u{2ACF0}\u{2ACF1}\u{2ACF2}\u{2ACF3}\u{2ACF4}\u{2ACF5}\u{2ACF6}\u{2ACF7}\u{2ACF8}\u{2ACF9}\u{2ACFA}\u{2ACFB}\u{2ACFC}\u{2ACFD}\u{2ACFE}\u{2ACFF}\u{2AD00}\u{2AD01}\u{2AD02}\u{2AD03}\u{2AD04}\u{2AD05}\u{2AD06}\u{2AD07}\u{2AD08}\u{2AD09}\u{2AD0A}\u{2AD0B}\u{2AD0C}\u{2AD0D}\u{2AD0E}\u{2AD0F}\u{2AD10}\u{2AD11}\u{2AD12}\u{2AD13}\u{2AD14}\u{2AD15}\u{2AD16}\u{2AD17}\u{2AD18}\u{2AD19}\u{2AD1A}\u{2AD1B}\u{2AD1C}\u{2AD1D}\u{2AD1E}\u{2AD1F}\u{2AD20}\u{2AD21}\u{2AD22}\u{2AD23}\u{2AD24}\u{2AD25}\u{2AD26}\u{2AD27}\u{2AD28}\u{2AD29}\u{2AD2A}\u{2AD2B}\u{2AD2C}\u{2AD2D}\u{2AD2E}\u{2AD2F}\u{2AD30}\u{2AD31}\u{2AD32}\u{2AD33}\u{2AD34}\u{2AD35}\u{2AD36}\u{2AD37}\u{2AD38}\u{2AD39}\u{2AD3A}\u{2AD3B}\u{2AD3C}\u{2AD3D}\u{2AD3E}\u{2AD3F}\u{2AD40}\u{2AD41}\u{2AD42}\u{2AD43}\u{2AD44}\u{2AD45}\u{2AD46}\u{2AD47}\u{2AD48}\u{2AD49}\u{2AD4A}\u{2AD4B}\u{2AD4C}\u{2AD4D}\u{2AD4E}\u{2AD4F}\u{2AD50}\u{2AD51}\u{2AD52}\u{2AD53}\u{2AD54}\u{2AD55}\u{2AD56}\u{2AD57}\u{2AD58}\u{2AD59}\u{2AD5A}\u{2AD5B}\u{2AD5C}\u{2AD5D}\u{2AD5E}\u{2AD5F}\u{2AD60}\u{2AD61}\u{2AD62}\u{2AD63}\u{2AD64}\u{2AD65}\u{2AD66}\u{2AD67}\u{2AD68}\u{2AD69}\u{2AD6A}\u{2AD6B}\u{2AD6C}\u{2AD6D}\u{2AD6E}\u{2AD6F}\u{2AD70}\u{2AD71}\u{2AD72}\u{2AD73}\u{2AD74}\u{2AD75}\u{2AD76}\u{2AD77}\u{2AD78}\u{2AD79}\u{2AD7A}\u{2AD7B}\u{2AD7C}\u{2AD7D}\u{2AD7E}\u{2AD7F}\u{2AD80}\u{2AD81}\u{2AD82}\u{2AD83}\u{2AD84}\u{2AD85}\u{2AD86}\u{2AD87}\u{2AD88}\u{2AD89}\u{2AD8A}\u{2AD8B}\u{2AD8C}\u{2AD8D}\u{2AD8E}\u{2AD8F}\u{2AD90}\u{2AD91}\u{2AD92}\u{2AD93}\u{2AD94}\u{2AD95}\u{2AD96}\u{2AD97}\u{2AD98}\u{2AD99}\u{2AD9A}\u{2AD9B}\u{2AD9C}\u{2AD9D}\u{2AD9E}\u{2AD9F}\u{2ADA0}\u{2ADA1}\u{2ADA2}\u{2ADA3}\u{2ADA4}\u{2ADA5}\u{2ADA6}\u{2ADA7}\u{2ADA8}\u{2ADA9}\u{2ADAA}\u{2ADAB}\u{2ADAC}\u{2ADAD}\u{2ADAE}\u{2ADAF}\u{2ADB0}\u{2ADB1}\u{2ADB2}\u{2ADB3}\u{2ADB4}\u{2ADB5}\u{2ADB6}\u{2ADB7}\u{2ADB8}\u{2ADB9}\u{2ADBA}\u{2ADBB}\u{2ADBC}\u{2ADBD}\u{2ADBE}\u{2ADBF}\u{2ADC0}\u{2ADC1}\u{2ADC2}\u{2ADC3}\u{2ADC4}\u{2ADC5}\u{2ADC6}\u{2ADC7}\u{2ADC8}\u{2ADC9}\u{2ADCA}\u{2ADCB}\u{2ADCC}\u{2ADCD}\u{2ADCE}\u{2ADCF}\u{2ADD0}\u{2ADD1}\u{2ADD2}\u{2ADD3}\u{2ADD4}\u{2ADD5}\u{2ADD6}\u{2ADD7}\u{2ADD8}\u{2ADD9}\u{2ADDA}\u{2ADDB}\u{2ADDC}\u{2ADDD}\u{2ADDE}\u{2ADDF}\u{2ADE0}\u{2ADE1}\u{2ADE2}\u{2ADE3}\u{2ADE4}\u{2ADE5}\u{2ADE6}\u{2ADE7}\u{2ADE8}\u{2ADE9}\u{2ADEA}\u{2ADEB}\u{2ADEC}\u{2ADED}\u{2ADEE}\u{2ADEF}\u{2ADF0}\u{2ADF1}\u{2ADF2}\u{2ADF3}\u{2ADF4}\u{2ADF5}\u{2ADF6}\u{2ADF7}\u{2ADF8}\u{2ADF9}\u{2ADFA}\u{2ADFB}\u{2ADFC}\u{2ADFD}\u{2ADFE}\u{2ADFF}\u{2AE00}\u{2AE01}\u{2AE02}\u{2AE03}\u{2AE04}\u{2AE05}\u{2AE06}\u{2AE07}\u{2AE08}\u{2AE09}\u{2AE0A}\u{2AE0B}\u{2AE0C}\u{2AE0D}\u{2AE0E}\u{2AE0F}\u{2AE10}\u{2AE11}\u{2AE12}\u{2AE13}\u{2AE14}\u{2AE15}\u{2AE16}\u{2AE17}\u{2AE18}\u{2AE19}\u{2AE1A}\u{2AE1B}\u{2AE1C}\u{2AE1D}\u{2AE1E}\u{2AE1F}\u{2AE20}\u{2AE21}\u{2AE22}\u{2AE23}\u{2AE24}\u{2AE25}\u{2AE26}\u{2AE27}\u{2AE28}\u{2AE29}\u{2AE2A}\u{2AE2B}\u{2AE2C}\u{2AE2D}\u{2AE2E}\u{2AE2F}\u{2AE30}\u{2AE31}\u{2AE32}\u{2AE33}\u{2AE34}\u{2AE35}\u{2AE36}\u{2AE37}\u{2AE38}\u{2AE39}\u{2AE3A}\u{2AE3B}\u{2AE3C}\u{2AE3D}\u{2AE3E}\u{2AE3F}\u{2AE40}\u{2AE41}\u{2AE42}\u{2AE43}\u{2AE44}\u{2AE45}\u{2AE46}\u{2AE47}\u{2AE48}\u{2AE49}\u{2AE4A}\u{2AE4B}\u{2AE4C}\u{2AE4D}\u{2AE4E}\u{2AE4F}\u{2AE50}\u{2AE51}\u{2AE52}\u{2AE53}\u{2AE54}\u{2AE55}\u{2AE56}\u{2AE57}\u{2AE58}\u{2AE59}\u{2AE5A}\u{2AE5B}\u{2AE5C}\u{2AE5D}\u{2AE5E}\u{2AE5F}\u{2AE60}\u{2AE61}\u{2AE62}\u{2AE63}\u{2AE64}\u{2AE65}\u{2AE66}\u{2AE67}\u{2AE68}\u{2AE69}\u{2AE6A}\u{2AE6B}\u{2AE6C}\u{2AE6D}\u{2AE6E}\u{2AE6F}\u{2AE70}\u{2AE71}\u{2AE72}\u{2AE73}\u{2AE74}\u{2AE75}\u{2AE76}\u{2AE77}\u{2AE78}\u{2AE79}\u{2AE7A}\u{2AE7B}\u{2AE7C}\u{2AE7D}\u{2AE7E}\u{2AE7F}\u{2AE80}\u{2AE81}\u{2AE82}\u{2AE83}\u{2AE84}\u{2AE85}\u{2AE86}\u{2AE87}\u{2AE88}\u{2AE89}\u{2AE8A}\u{2AE8B}\u{2AE8C}\u{2AE8D}\u{2AE8E}\u{2AE8F}\u{2AE90}\u{2AE91}\u{2AE92}\u{2AE93}\u{2AE94}\u{2AE95}\u{2AE96}\u{2AE97}\u{2AE98}\u{2AE99}\u{2AE9A}\u{2AE9B}\u{2AE9C}\u{2AE9D}\u{2AE9E}\u{2AE9F}\u{2AEA0}\u{2AEA1}\u{2AEA2}\u{2AEA3}\u{2AEA4}\u{2AEA5}\u{2AEA6}\u{2AEA7}\u{2AEA8}\u{2AEA9}\u{2AEAA}\u{2AEAB}\u{2AEAC}\u{2AEAD}\u{2AEAE}\u{2AEAF}\u{2AEB0}\u{2AEB1}\u{2AEB2}\u{2AEB3}\u{2AEB4}\u{2AEB5}\u{2AEB6}\u{2AEB7}\u{2AEB8}\u{2AEB9}\u{2AEBA}\u{2AEBB}\u{2AEBC}\u{2AEBD}\u{2AEBE}\u{2AEBF}\u{2AEC0}\u{2AEC1}\u{2AEC2}\u{2AEC3}\u{2AEC4}\u{2AEC5}\u{2AEC6}\u{2AEC7}\u{2AEC8}\u{2AEC9}\u{2AECA}\u{2AECB}\u{2AECC}\u{2AECD}\u{2AECE}\u{2AECF}\u{2AED0}\u{2AED1}\u{2AED2}\u{2AED3}\u{2AED4}\u{2AED5}\u{2AED6}\u{2AED7}\u{2AED8}\u{2AED9}\u{2AEDA}\u{2AEDB}\u{2AEDC}\u{2AEDD}\u{2AEDE}\u{2AEDF}\u{2AEE0}\u{2AEE1}\u{2AEE2}\u{2AEE3}\u{2AEE4}\u{2AEE5}\u{2AEE6}\u{2AEE7}\u{2AEE8}\u{2AEE9}\u{2AEEA}\u{2AEEB}\u{2AEEC}\u{2AEED}\u{2AEEE}\u{2AEEF}\u{2AEF0}\u{2AEF1}\u{2AEF2}\u{2AEF3}\u{2AEF4}\u{2AEF5}\u{2AEF6}\u{2AEF7}\u{2AEF8}\u{2AEF9}\u{2AEFA}\u{2AEFB}\u{2AEFC}\u{2AEFD}\u{2AEFE}\u{2AEFF}\u{2AF00}\u{2AF01}\u{2AF02}\u{2AF03}\u{2AF04}\u{2AF05}\u{2AF06}\u{2AF07}\u{2AF08}\u{2AF09}\u{2AF0A}\u{2AF0B}\u{2AF0C}\u{2AF0D}\u{2AF0E}\u{2AF0F}\u{2AF10}\u{2AF11}\u{2AF12}\u{2AF13}\u{2AF14}\u{2AF15}\u{2AF16}\u{2AF17}\u{2AF18}\u{2AF19}\u{2AF1A}\u{2AF1B}\u{2AF1C}\u{2AF1D}\u{2AF1E}\u{2AF1F}\u{2AF20}\u{2AF21}\u{2AF22}\u{2AF23}\u{2AF24}\u{2AF25}\u{2AF26}\u{2AF27}\u{2AF28}\u{2AF29}\u{2AF2A}\u{2AF2B}\u{2AF2C}\u{2AF2D}\u{2AF2E}\u{2AF2F}\u{2AF30}\u{2AF31}\u{2AF32}\u{2AF33}\u{2AF34}\u{2AF35}\u{2AF36}\u{2AF37}\u{2AF38}\u{2AF39}\u{2AF3A}\u{2AF3B}\u{2AF3C}\u{2AF3D}\u{2AF3E}\u{2AF3F}\u{2AF40}\u{2AF41}\u{2AF42}\u{2AF43}\u{2AF44}\u{2AF45}\u{2AF46}\u{2AF47}\u{2AF48}\u{2AF49}\u{2AF4A}\u{2AF4B}\u{2AF4C}\u{2AF4D}\u{2AF4E}\u{2AF4F}\u{2AF50}\u{2AF51}\u{2AF52}\u{2AF53}\u{2AF54}\u{2AF55}\u{2AF56}\u{2AF57}\u{2AF58}\u{2AF59}\u{2AF5A}\u{2AF5B}\u{2AF5C}\u{2AF5D}\u{2AF5E}\u{2AF5F}\u{2AF60}\u{2AF61}\u{2AF62}\u{2AF63}\u{2AF64}\u{2AF65}\u{2AF66}\u{2AF67}\u{2AF68}\u{2AF69}\u{2AF6A}\u{2AF6B}\u{2AF6C}\u{2AF6D}\u{2AF6E}\u{2AF6F}\u{2AF70}\u{2AF71}\u{2AF72}\u{2AF73}\u{2AF74}\u{2AF75}\u{2AF76}\u{2AF77}\u{2AF78}\u{2AF79}\u{2AF7A}\u{2AF7B}\u{2AF7C}\u{2AF7D}\u{2AF7E}\u{2AF7F}\u{2AF80}\u{2AF81}\u{2AF82}\u{2AF83}\u{2AF84}\u{2AF85}\u{2AF86}\u{2AF87}\u{2AF88}\u{2AF89}\u{2AF8A}\u{2AF8B}\u{2AF8C}\u{2AF8D}\u{2AF8E}\u{2AF8F}\u{2AF90}\u{2AF91}\u{2AF92}\u{2AF93}\u{2AF94}\u{2AF95}\u{2AF96}\u{2AF97}\u{2AF98}\u{2AF99}\u{2AF9A}\u{2AF9B}\u{2AF9C}\u{2AF9D}\u{2AF9E}\u{2AF9F}\u{2AFA0}\u{2AFA1}\u{2AFA2}\u{2AFA3}\u{2AFA4}\u{2AFA5}\u{2AFA6}\u{2AFA7}\u{2AFA8}\u{2AFA9}\u{2AFAA}\u{2AFAB}\u{2AFAC}\u{2AFAD}\u{2AFAE}\u{2AFAF}\u{2AFB0}\u{2AFB1}\u{2AFB2}\u{2AFB3}\u{2AFB4}\u{2AFB5}\u{2AFB6}\u{2AFB7}\u{2AFB8}\u{2AFB9}\u{2AFBA}\u{2AFBB}\u{2AFBC}\u{2AFBD}\u{2AFBE}\u{2AFBF}\u{2AFC0}\u{2AFC1}\u{2AFC2}\u{2AFC3}\u{2AFC4}\u{2AFC5}\u{2AFC6}\u{2AFC7}\u{2AFC8}\u{2AFC9}\u{2AFCA}\u{2AFCB}\u{2AFCC}\u{2AFCD}\u{2AFCE}\u{2AFCF}\u{2AFD0}\u{2AFD1}\u{2AFD2}\u{2AFD3}\u{2AFD4}\u{2AFD5}\u{2AFD6}\u{2AFD7}\u{2AFD8}\u{2AFD9}\u{2AFDA}\u{2AFDB}\u{2AFDC}\u{2AFDD}\u{2AFDE}\u{2AFDF}\u{2AFE0}\u{2AFE1}\u{2AFE2}\u{2AFE3}\u{2AFE4}\u{2AFE5}\u{2AFE6}\u{2AFE7}\u{2AFE8}\u{2AFE9}\u{2AFEA}\u{2AFEB}\u{2AFEC}\u{2AFED}\u{2AFEE}\u{2AFEF}\u{2AFF0}\u{2AFF1}\u{2AFF2}\u{2AFF3}\u{2AFF4}\u{2AFF5}\u{2AFF6}\u{2AFF7}\u{2AFF8}\u{2AFF9}\u{2AFFA}\u{2AFFB}\u{2AFFC}\u{2AFFD}\u{2AFFE}\u{2AFFF}\u{2B000}\u{2B001}\u{2B002}\u{2B003}\u{2B004}\u{2B005}\u{2B006}\u{2B007}\u{2B008}\u{2B009}\u{2B00A}\u{2B00B}\u{2B00C}\u{2B00D}\u{2B00E}\u{2B00F}\u{2B010}\u{2B011}\u{2B012}\u{2B013}\u{2B014}\u{2B015}\u{2B016}\u{2B017}\u{2B018}\u{2B019}\u{2B01A}\u{2B01B}\u{2B01C}\u{2B01D}\u{2B01E}\u{2B01F}\u{2B020}\u{2B021}\u{2B022}\u{2B023}\u{2B024}\u{2B025}\u{2B026}\u{2B027}\u{2B028}\u{2B029}\u{2B02A}\u{2B02B}\u{2B02C}\u{2B02D}\u{2B02E}\u{2B02F}\u{2B030}\u{2B031}\u{2B032}\u{2B033}\u{2B034}\u{2B035}\u{2B036}\u{2B037}\u{2B038}\u{2B039}\u{2B03A}\u{2B03B}\u{2B03C}\u{2B03D}\u{2B03E}\u{2B03F}\u{2B040}\u{2B041}\u{2B042}\u{2B043}\u{2B044}\u{2B045}\u{2B046}\u{2B047}\u{2B048}\u{2B049}\u{2B04A}\u{2B04B}\u{2B04C}\u{2B04D}\u{2B04E}\u{2B04F}\u{2B050}\u{2B051}\u{2B052}\u{2B053}\u{2B054}\u{2B055}\u{2B056}\u{2B057}\u{2B058}\u{2B059}\u{2B05A}\u{2B05B}\u{2B05C}\u{2B05D}\u{2B05E}\u{2B05F}\u{2B060}\u{2B061}\u{2B062}\u{2B063}\u{2B064}\u{2B065}\u{2B066}\u{2B067}\u{2B068}\u{2B069}\u{2B06A}\u{2B06B}\u{2B06C}\u{2B06D}\u{2B06E}\u{2B06F}\u{2B070}\u{2B071}\u{2B072}\u{2B073}\u{2B074}\u{2B075}\u{2B076}\u{2B077}\u{2B078}\u{2B079}\u{2B07A}\u{2B07B}\u{2B07C}\u{2B07D}\u{2B07E}\u{2B07F}\u{2B080}\u{2B081}\u{2B082}\u{2B083}\u{2B084}\u{2B085}\u{2B086}\u{2B087}\u{2B088}\u{2B089}\u{2B08A}\u{2B08B}\u{2B08C}\u{2B08D}\u{2B08E}\u{2B08F}\u{2B090}\u{2B091}\u{2B092}\u{2B093}\u{2B094}\u{2B095}\u{2B096}\u{2B097}\u{2B098}\u{2B099}\u{2B09A}\u{2B09B}\u{2B09C}\u{2B09D}\u{2B09E}\u{2B09F}\u{2B0A0}\u{2B0A1}\u{2B0A2}\u{2B0A3}\u{2B0A4}\u{2B0A5}\u{2B0A6}\u{2B0A7}\u{2B0A8}\u{2B0A9}\u{2B0AA}\u{2B0AB}\u{2B0AC}\u{2B0AD}\u{2B0AE}\u{2B0AF}\u{2B0B0}\u{2B0B1}\u{2B0B2}\u{2B0B3}\u{2B0B4}\u{2B0B5}\u{2B0B6}\u{2B0B7}\u{2B0B8}\u{2B0B9}\u{2B0BA}\u{2B0BB}\u{2B0BC}\u{2B0BD}\u{2B0BE}\u{2B0BF}\u{2B0C0}\u{2B0C1}\u{2B0C2}\u{2B0C3}\u{2B0C4}\u{2B0C5}\u{2B0C6}\u{2B0C7}\u{2B0C8}\u{2B0C9}\u{2B0CA}\u{2B0CB}\u{2B0CC}\u{2B0CD}\u{2B0CE}\u{2B0CF}\u{2B0D0}\u{2B0D1}\u{2B0D2}\u{2B0D3}\u{2B0D4}\u{2B0D5}\u{2B0D6}\u{2B0D7}\u{2B0D8}\u{2B0D9}\u{2B0DA}\u{2B0DB}\u{2B0DC}\u{2B0DD}\u{2B0DE}\u{2B0DF}\u{2B0E0}\u{2B0E1}\u{2B0E2}\u{2B0E3}\u{2B0E4}\u{2B0E5}\u{2B0E6}\u{2B0E7}\u{2B0E8}\u{2B0E9}\u{2B0EA}\u{2B0EB}\u{2B0EC}\u{2B0ED}\u{2B0EE}\u{2B0EF}\u{2B0F0}\u{2B0F1}\u{2B0F2}\u{2B0F3}\u{2B0F4}\u{2B0F5}\u{2B0F6}\u{2B0F7}\u{2B0F8}\u{2B0F9}\u{2B0FA}\u{2B0FB}\u{2B0FC}\u{2B0FD}\u{2B0FE}\u{2B0FF}\u{2B100}\u{2B101}\u{2B102}\u{2B103}\u{2B104}\u{2B105}\u{2B106}\u{2B107}\u{2B108}\u{2B109}\u{2B10A}\u{2B10B}\u{2B10C}\u{2B10D}\u{2B10E}\u{2B10F}\u{2B110}\u{2B111}\u{2B112}\u{2B113}\u{2B114}\u{2B115}\u{2B116}\u{2B117}\u{2B118}\u{2B119}\u{2B11A}\u{2B11B}\u{2B11C}\u{2B11D}\u{2B11E}\u{2B11F}\u{2B120}\u{2B121}\u{2B122}\u{2B123}\u{2B124}\u{2B125}\u{2B126}\u{2B127}\u{2B128}\u{2B129}\u{2B12A}\u{2B12B}\u{2B12C}\u{2B12D}\u{2B12E}\u{2B12F}\u{2B130}\u{2B131}\u{2B132}\u{2B133}\u{2B134}\u{2B135}\u{2B136}\u{2B137}\u{2B138}\u{2B139}\u{2B13A}\u{2B13B}\u{2B13C}\u{2B13D}\u{2B13E}\u{2B13F}\u{2B140}\u{2B141}\u{2B142}\u{2B143}\u{2B144}\u{2B145}\u{2B146}\u{2B147}\u{2B148}\u{2B149}\u{2B14A}\u{2B14B}\u{2B14C}\u{2B14D}\u{2B14E}\u{2B14F}\u{2B150}\u{2B151}\u{2B152}\u{2B153}\u{2B154}\u{2B155}\u{2B156}\u{2B157}\u{2B158}\u{2B159}\u{2B15A}\u{2B15B}\u{2B15C}\u{2B15D}\u{2B15E}\u{2B15F}\u{2B160}\u{2B161}\u{2B162}\u{2B163}\u{2B164}\u{2B165}\u{2B166}\u{2B167}\u{2B168}\u{2B169}\u{2B16A}\u{2B16B}\u{2B16C}\u{2B16D}\u{2B16E}\u{2B16F}\u{2B170}\u{2B171}\u{2B172}\u{2B173}\u{2B174}\u{2B175}\u{2B176}\u{2B177}\u{2B178}\u{2B179}\u{2B17A}\u{2B17B}\u{2B17C}\u{2B17D}\u{2B17E}\u{2B17F}\u{2B180}\u{2B181}\u{2B182}\u{2B183}\u{2B184}\u{2B185}\u{2B186}\u{2B187}\u{2B188}\u{2B189}\u{2B18A}\u{2B18B}\u{2B18C}\u{2B18D}\u{2B18E}\u{2B18F}\u{2B190}\u{2B191}\u{2B192}\u{2B193}\u{2B194}\u{2B195}\u{2B196}\u{2B197}\u{2B198}\u{2B199}\u{2B19A}\u{2B19B}\u{2B19C}\u{2B19D}\u{2B19E}\u{2B19F}\u{2B1A0}\u{2B1A1}\u{2B1A2}\u{2B1A3}\u{2B1A4}\u{2B1A5}\u{2B1A6}\u{2B1A7}\u{2B1A8}\u{2B1A9}\u{2B1AA}\u{2B1AB}\u{2B1AC}\u{2B1AD}\u{2B1AE}\u{2B1AF}\u{2B1B0}\u{2B1B1}\u{2B1B2}\u{2B1B3}\u{2B1B4}\u{2B1B5}\u{2B1B6}\u{2B1B7}\u{2B1B8}\u{2B1B9}\u{2B1BA}\u{2B1BB}\u{2B1BC}\u{2B1BD}\u{2B1BE}\u{2B1BF}\u{2B1C0}\u{2B1C1}\u{2B1C2}\u{2B1C3}\u{2B1C4}\u{2B1C5}\u{2B1C6}\u{2B1C7}\u{2B1C8}\u{2B1C9}\u{2B1CA}\u{2B1CB}\u{2B1CC}\u{2B1CD}\u{2B1CE}\u{2B1CF}\u{2B1D0}\u{2B1D1}\u{2B1D2}\u{2B1D3}\u{2B1D4}\u{2B1D5}\u{2B1D6}\u{2B1D7}\u{2B1D8}\u{2B1D9}\u{2B1DA}\u{2B1DB}\u{2B1DC}\u{2B1DD}\u{2B1DE}\u{2B1DF}\u{2B1E0}\u{2B1E1}\u{2B1E2}\u{2B1E3}\u{2B1E4}\u{2B1E5}\u{2B1E6}\u{2B1E7}\u{2B1E8}\u{2B1E9}\u{2B1EA}\u{2B1EB}\u{2B1EC}\u{2B1ED}\u{2B1EE}\u{2B1EF}\u{2B1F0}\u{2B1F1}\u{2B1F2}\u{2B1F3}\u{2B1F4}\u{2B1F5}\u{2B1F6}\u{2B1F7}\u{2B1F8}\u{2B1F9}\u{2B1FA}\u{2B1FB}\u{2B1FC}\u{2B1FD}\u{2B1FE}\u{2B1FF}\u{2B200}\u{2B201}\u{2B202}\u{2B203}\u{2B204}\u{2B205}\u{2B206}\u{2B207}\u{2B208}\u{2B209}\u{2B20A}\u{2B20B}\u{2B20C}\u{2B20D}\u{2B20E}\u{2B20F}\u{2B210}\u{2B211}\u{2B212}\u{2B213}\u{2B214}\u{2B215}\u{2B216}\u{2B217}\u{2B218}\u{2B219}\u{2B21A}\u{2B21B}\u{2B21C}\u{2B21D}\u{2B21E}\u{2B21F}\u{2B220}\u{2B221}\u{2B222}\u{2B223}\u{2B224}\u{2B225}\u{2B226}\u{2B227}\u{2B228}\u{2B229}\u{2B22A}\u{2B22B}\u{2B22C}\u{2B22D}\u{2B22E}\u{2B22F}\u{2B230}\u{2B231}\u{2B232}\u{2B233}\u{2B234}\u{2B235}\u{2B236}\u{2B237}\u{2B238}\u{2B239}\u{2B23A}\u{2B23B}\u{2B23C}\u{2B23D}\u{2B23E}\u{2B23F}\u{2B240}\u{2B241}\u{2B242}\u{2B243}\u{2B244}\u{2B245}\u{2B246}\u{2B247}\u{2B248}\u{2B249}\u{2B24A}\u{2B24B}\u{2B24C}\u{2B24D}\u{2B24E}\u{2B24F}\u{2B250}\u{2B251}\u{2B252}\u{2B253}\u{2B254}\u{2B255}\u{2B256}\u{2B257}\u{2B258}\u{2B259}\u{2B25A}\u{2B25B}\u{2B25C}\u{2B25D}\u{2B25E}\u{2B25F}\u{2B260}\u{2B261}\u{2B262}\u{2B263}\u{2B264}\u{2B265}\u{2B266}\u{2B267}\u{2B268}\u{2B269}\u{2B26A}\u{2B26B}\u{2B26C}\u{2B26D}\u{2B26E}\u{2B26F}\u{2B270}\u{2B271}\u{2B272}\u{2B273}\u{2B274}\u{2B275}\u{2B276}\u{2B277}\u{2B278}\u{2B279}\u{2B27A}\u{2B27B}\u{2B27C}\u{2B27D}\u{2B27E}\u{2B27F}\u{2B280}\u{2B281}\u{2B282}\u{2B283}\u{2B284}\u{2B285}\u{2B286}\u{2B287}\u{2B288}\u{2B289}\u{2B28A}\u{2B28B}\u{2B28C}\u{2B28D}\u{2B28E}\u{2B28F}\u{2B290}\u{2B291}\u{2B292}\u{2B293}\u{2B294}\u{2B295}\u{2B296}\u{2B297}\u{2B298}\u{2B299}\u{2B29A}\u{2B29B}\u{2B29C}\u{2B29D}\u{2B29E}\u{2B29F}\u{2B2A0}\u{2B2A1}\u{2B2A2}\u{2B2A3}\u{2B2A4}\u{2B2A5}\u{2B2A6}\u{2B2A7}\u{2B2A8}\u{2B2A9}\u{2B2AA}\u{2B2AB}\u{2B2AC}\u{2B2AD}\u{2B2AE}\u{2B2AF}\u{2B2B0}\u{2B2B1}\u{2B2B2}\u{2B2B3}\u{2B2B4}\u{2B2B5}\u{2B2B6}\u{2B2B7}\u{2B2B8}\u{2B2B9}\u{2B2BA}\u{2B2BB}\u{2B2BC}\u{2B2BD}\u{2B2BE}\u{2B2BF}\u{2B2C0}\u{2B2C1}\u{2B2C2}\u{2B2C3}\u{2B2C4}\u{2B2C5}\u{2B2C6}\u{2B2C7}\u{2B2C8}\u{2B2C9}\u{2B2CA}\u{2B2CB}\u{2B2CC}\u{2B2CD}\u{2B2CE}\u{2B2CF}\u{2B2D0}\u{2B2D1}\u{2B2D2}\u{2B2D3}\u{2B2D4}\u{2B2D5}\u{2B2D6}\u{2B2D7}\u{2B2D8}\u{2B2D9}\u{2B2DA}\u{2B2DB}\u{2B2DC}\u{2B2DD}\u{2B2DE}\u{2B2DF}\u{2B2E0}\u{2B2E1}\u{2B2E2}\u{2B2E3}\u{2B2E4}\u{2B2E5}\u{2B2E6}\u{2B2E7}\u{2B2E8}\u{2B2E9}\u{2B2EA}\u{2B2EB}\u{2B2EC}\u{2B2ED}\u{2B2EE}\u{2B2EF}\u{2B2F0}\u{2B2F1}\u{2B2F2}\u{2B2F3}\u{2B2F4}\u{2B2F5}\u{2B2F6}\u{2B2F7}\u{2B2F8}\u{2B2F9}\u{2B2FA}\u{2B2FB}\u{2B2FC}\u{2B2FD}\u{2B2FE}\u{2B2FF}\u{2B300}\u{2B301}\u{2B302}\u{2B303}\u{2B304}\u{2B305}\u{2B306}\u{2B307}\u{2B308}\u{2B309}\u{2B30A}\u{2B30B}\u{2B30C}\u{2B30D}\u{2B30E}\u{2B30F}\u{2B310}\u{2B311}\u{2B312}\u{2B313}\u{2B314}\u{2B315}\u{2B316}\u{2B317}\u{2B318}\u{2B319}\u{2B31A}\u{2B31B}\u{2B31C}\u{2B31D}\u{2B31E}\u{2B31F}\u{2B320}\u{2B321}\u{2B322}\u{2B323}\u{2B324}\u{2B325}\u{2B326}\u{2B327}\u{2B328}\u{2B329}\u{2B32A}\u{2B32B}\u{2B32C}\u{2B32D}\u{2B32E}\u{2B32F}\u{2B330}\u{2B331}\u{2B332}\u{2B333}\u{2B334}\u{2B335}\u{2B336}\u{2B337}\u{2B338}\u{2B339}\u{2B33A}\u{2B33B}\u{2B33C}\u{2B33D}\u{2B33E}\u{2B33F}\u{2B340}\u{2B341}\u{2B342}\u{2B343}\u{2B344}\u{2B345}\u{2B346}\u{2B347}\u{2B348}\u{2B349}\u{2B34A}\u{2B34B}\u{2B34C}\u{2B34D}\u{2B34E}\u{2B34F}\u{2B350}\u{2B351}\u{2B352}\u{2B353}\u{2B354}\u{2B355}\u{2B356}\u{2B357}\u{2B358}\u{2B359}\u{2B35A}\u{2B35B}\u{2B35C}\u{2B35D}\u{2B35E}\u{2B35F}\u{2B360}\u{2B361}\u{2B362}\u{2B363}\u{2B364}\u{2B365}\u{2B366}\u{2B367}\u{2B368}\u{2B369}\u{2B36A}\u{2B36B}\u{2B36C}\u{2B36D}\u{2B36E}\u{2B36F}\u{2B370}\u{2B371}\u{2B372}\u{2B373}\u{2B374}\u{2B375}\u{2B376}\u{2B377}\u{2B378}\u{2B379}\u{2B37A}\u{2B37B}\u{2B37C}\u{2B37D}\u{2B37E}\u{2B37F}\u{2B380}\u{2B381}\u{2B382}\u{2B383}\u{2B384}\u{2B385}\u{2B386}\u{2B387}\u{2B388}\u{2B389}\u{2B38A}\u{2B38B}\u{2B38C}\u{2B38D}\u{2B38E}\u{2B38F}\u{2B390}\u{2B391}\u{2B392}\u{2B393}\u{2B394}\u{2B395}\u{2B396}\u{2B397}\u{2B398}\u{2B399}\u{2B39A}\u{2B39B}\u{2B39C}\u{2B39D}\u{2B39E}\u{2B39F}\u{2B3A0}\u{2B3A1}\u{2B3A2}\u{2B3A3}\u{2B3A4}\u{2B3A5}\u{2B3A6}\u{2B3A7}\u{2B3A8}\u{2B3A9}\u{2B3AA}\u{2B3AB}\u{2B3AC}\u{2B3AD}\u{2B3AE}\u{2B3AF}\u{2B3B0}\u{2B3B1}\u{2B3B2}\u{2B3B3}\u{2B3B4}\u{2B3B5}\u{2B3B6}\u{2B3B7}\u{2B3B8}\u{2B3B9}\u{2B3BA}\u{2B3BB}\u{2B3BC}\u{2B3BD}\u{2B3BE}\u{2B3BF}\u{2B3C0}\u{2B3C1}\u{2B3C2}\u{2B3C3}\u{2B3C4}\u{2B3C5}\u{2B3C6}\u{2B3C7}\u{2B3C8}\u{2B3C9}\u{2B3CA}\u{2B3CB}\u{2B3CC}\u{2B3CD}\u{2B3CE}\u{2B3CF}\u{2B3D0}\u{2B3D1}\u{2B3D2}\u{2B3D3}\u{2B3D4}\u{2B3D5}\u{2B3D6}\u{2B3D7}\u{2B3D8}\u{2B3D9}\u{2B3DA}\u{2B3DB}\u{2B3DC}\u{2B3DD}\u{2B3DE}\u{2B3DF}\u{2B3E0}\u{2B3E1}\u{2B3E2}\u{2B3E3}\u{2B3E4}\u{2B3E5}\u{2B3E6}\u{2B3E7}\u{2B3E8}\u{2B3E9}\u{2B3EA}\u{2B3EB}\u{2B3EC}\u{2B3ED}\u{2B3EE}\u{2B3EF}\u{2B3F0}\u{2B3F1}\u{2B3F2}\u{2B3F3}\u{2B3F4}\u{2B3F5}\u{2B3F6}\u{2B3F7}\u{2B3F8}\u{2B3F9}\u{2B3FA}\u{2B3FB}\u{2B3FC}\u{2B3FD}\u{2B3FE}\u{2B3FF}\u{2B400}\u{2B401}\u{2B402}\u{2B403}\u{2B404}\u{2B405}\u{2B406}\u{2B407}\u{2B408}\u{2B409}\u{2B40A}\u{2B40B}\u{2B40C}\u{2B40D}\u{2B40E}\u{2B40F}\u{2B410}\u{2B411}\u{2B412}\u{2B413}\u{2B414}\u{2B415}\u{2B416}\u{2B417}\u{2B418}\u{2B419}\u{2B41A}\u{2B41B}\u{2B41C}\u{2B41D}\u{2B41E}\u{2B41F}\u{2B420}\u{2B421}\u{2B422}\u{2B423}\u{2B424}\u{2B425}\u{2B426}\u{2B427}\u{2B428}\u{2B429}\u{2B42A}\u{2B42B}\u{2B42C}\u{2B42D}\u{2B42E}\u{2B42F}\u{2B430}\u{2B431}\u{2B432}\u{2B433}\u{2B434}\u{2B435}\u{2B436}\u{2B437}\u{2B438}\u{2B439}\u{2B43A}\u{2B43B}\u{2B43C}\u{2B43D}\u{2B43E}\u{2B43F}\u{2B440}\u{2B441}\u{2B442}\u{2B443}\u{2B444}\u{2B445}\u{2B446}\u{2B447}\u{2B448}\u{2B449}\u{2B44A}\u{2B44B}\u{2B44C}\u{2B44D}\u{2B44E}\u{2B44F}\u{2B450}\u{2B451}\u{2B452}\u{2B453}\u{2B454}\u{2B455}\u{2B456}\u{2B457}\u{2B458}\u{2B459}\u{2B45A}\u{2B45B}\u{2B45C}\u{2B45D}\u{2B45E}\u{2B45F}\u{2B460}\u{2B461}\u{2B462}\u{2B463}\u{2B464}\u{2B465}\u{2B466}\u{2B467}\u{2B468}\u{2B469}\u{2B46A}\u{2B46B}\u{2B46C}\u{2B46D}\u{2B46E}\u{2B46F}\u{2B470}\u{2B471}\u{2B472}\u{2B473}\u{2B474}\u{2B475}\u{2B476}\u{2B477}\u{2B478}\u{2B479}\u{2B47A}\u{2B47B}\u{2B47C}\u{2B47D}\u{2B47E}\u{2B47F}\u{2B480}\u{2B481}\u{2B482}\u{2B483}\u{2B484}\u{2B485}\u{2B486}\u{2B487}\u{2B488}\u{2B489}\u{2B48A}\u{2B48B}\u{2B48C}\u{2B48D}\u{2B48E}\u{2B48F}\u{2B490}\u{2B491}\u{2B492}\u{2B493}\u{2B494}\u{2B495}\u{2B496}\u{2B497}\u{2B498}\u{2B499}\u{2B49A}\u{2B49B}\u{2B49C}\u{2B49D}\u{2B49E}\u{2B49F}\u{2B4A0}\u{2B4A1}\u{2B4A2}\u{2B4A3}\u{2B4A4}\u{2B4A5}\u{2B4A6}\u{2B4A7}\u{2B4A8}\u{2B4A9}\u{2B4AA}\u{2B4AB}\u{2B4AC}\u{2B4AD}\u{2B4AE}\u{2B4AF}\u{2B4B0}\u{2B4B1}\u{2B4B2}\u{2B4B3}\u{2B4B4}\u{2B4B5}\u{2B4B6}\u{2B4B7}\u{2B4B8}\u{2B4B9}\u{2B4BA}\u{2B4BB}\u{2B4BC}\u{2B4BD}\u{2B4BE}\u{2B4BF}\u{2B4C0}\u{2B4C1}\u{2B4C2}\u{2B4C3}\u{2B4C4}\u{2B4C5}\u{2B4C6}\u{2B4C7}\u{2B4C8}\u{2B4C9}\u{2B4CA}\u{2B4CB}\u{2B4CC}\u{2B4CD}\u{2B4CE}\u{2B4CF}\u{2B4D0}\u{2B4D1}\u{2B4D2}\u{2B4D3}\u{2B4D4}\u{2B4D5}\u{2B4D6}\u{2B4D7}\u{2B4D8}\u{2B4D9}\u{2B4DA}\u{2B4DB}\u{2B4DC}\u{2B4DD}\u{2B4DE}\u{2B4DF}\u{2B4E0}\u{2B4E1}\u{2B4E2}\u{2B4E3}\u{2B4E4}\u{2B4E5}\u{2B4E6}\u{2B4E7}\u{2B4E8}\u{2B4E9}\u{2B4EA}\u{2B4EB}\u{2B4EC}\u{2B4ED}\u{2B4EE}\u{2B4EF}\u{2B4F0}\u{2B4F1}\u{2B4F2}\u{2B4F3}\u{2B4F4}\u{2B4F5}\u{2B4F6}\u{2B4F7}\u{2B4F8}\u{2B4F9}\u{2B4FA}\u{2B4FB}\u{2B4FC}\u{2B4FD}\u{2B4FE}\u{2B4FF}\u{2B500}\u{2B501}\u{2B502}\u{2B503}\u{2B504}\u{2B505}\u{2B506}\u{2B507}\u{2B508}\u{2B509}\u{2B50A}\u{2B50B}\u{2B50C}\u{2B50D}\u{2B50E}\u{2B50F}\u{2B510}\u{2B511}\u{2B512}\u{2B513}\u{2B514}\u{2B515}\u{2B516}\u{2B517}\u{2B518}\u{2B519}\u{2B51A}\u{2B51B}\u{2B51C}\u{2B51D}\u{2B51E}\u{2B51F}\u{2B520}\u{2B521}\u{2B522}\u{2B523}\u{2B524}\u{2B525}\u{2B526}\u{2B527}\u{2B528}\u{2B529}\u{2B52A}\u{2B52B}\u{2B52C}\u{2B52D}\u{2B52E}\u{2B52F}\u{2B530}\u{2B531}\u{2B532}\u{2B533}\u{2B534}\u{2B535}\u{2B536}\u{2B537}\u{2B538}\u{2B539}\u{2B53A}\u{2B53B}\u{2B53C}\u{2B53D}\u{2B53E}\u{2B53F}\u{2B540}\u{2B541}\u{2B542}\u{2B543}\u{2B544}\u{2B545}\u{2B546}\u{2B547}\u{2B548}\u{2B549}\u{2B54A}\u{2B54B}\u{2B54C}\u{2B54D}\u{2B54E}\u{2B54F}\u{2B550}\u{2B551}\u{2B552}\u{2B553}\u{2B554}\u{2B555}\u{2B556}\u{2B557}\u{2B558}\u{2B559}\u{2B55A}\u{2B55B}\u{2B55C}\u{2B55D}\u{2B55E}\u{2B55F}\u{2B560}\u{2B561}\u{2B562}\u{2B563}\u{2B564}\u{2B565}\u{2B566}\u{2B567}\u{2B568}\u{2B569}\u{2B56A}\u{2B56B}\u{2B56C}\u{2B56D}\u{2B56E}\u{2B56F}\u{2B570}\u{2B571}\u{2B572}\u{2B573}\u{2B574}\u{2B575}\u{2B576}\u{2B577}\u{2B578}\u{2B579}\u{2B57A}\u{2B57B}\u{2B57C}\u{2B57D}\u{2B57E}\u{2B57F}\u{2B580}\u{2B581}\u{2B582}\u{2B583}\u{2B584}\u{2B585}\u{2B586}\u{2B587}\u{2B588}\u{2B589}\u{2B58A}\u{2B58B}\u{2B58C}\u{2B58D}\u{2B58E}\u{2B58F}\u{2B590}\u{2B591}\u{2B592}\u{2B593}\u{2B594}\u{2B595}\u{2B596}\u{2B597}\u{2B598}\u{2B599}\u{2B59A}\u{2B59B}\u{2B59C}\u{2B59D}\u{2B59E}\u{2B59F}\u{2B5A0}\u{2B5A1}\u{2B5A2}\u{2B5A3}\u{2B5A4}\u{2B5A5}\u{2B5A6}\u{2B5A7}\u{2B5A8}\u{2B5A9}\u{2B5AA}\u{2B5AB}\u{2B5AC}\u{2B5AD}\u{2B5AE}\u{2B5AF}\u{2B5B0}\u{2B5B1}\u{2B5B2}\u{2B5B3}\u{2B5B4}\u{2B5B5}\u{2B5B6}\u{2B5B7}\u{2B5B8}\u{2B5B9}\u{2B5BA}\u{2B5BB}\u{2B5BC}\u{2B5BD}\u{2B5BE}\u{2B5BF}\u{2B5C0}\u{2B5C1}\u{2B5C2}\u{2B5C3}\u{2B5C4}\u{2B5C5}\u{2B5C6}\u{2B5C7}\u{2B5C8}\u{2B5C9}\u{2B5CA}\u{2B5CB}\u{2B5CC}\u{2B5CD}\u{2B5CE}\u{2B5CF}\u{2B5D0}\u{2B5D1}\u{2B5D2}\u{2B5D3}\u{2B5D4}\u{2B5D5}\u{2B5D6}\u{2B5D7}\u{2B5D8}\u{2B5D9}\u{2B5DA}\u{2B5DB}\u{2B5DC}\u{2B5DD}\u{2B5DE}\u{2B5DF}\u{2B5E0}\u{2B5E1}\u{2B5E2}\u{2B5E3}\u{2B5E4}\u{2B5E5}\u{2B5E6}\u{2B5E7}\u{2B5E8}\u{2B5E9}\u{2B5EA}\u{2B5EB}\u{2B5EC}\u{2B5ED}\u{2B5EE}\u{2B5EF}\u{2B5F0}\u{2B5F1}\u{2B5F2}\u{2B5F3}\u{2B5F4}\u{2B5F5}\u{2B5F6}\u{2B5F7}\u{2B5F8}\u{2B5F9}\u{2B5FA}\u{2B5FB}\u{2B5FC}\u{2B5FD}\u{2B5FE}\u{2B5FF}\u{2B600}\u{2B601}\u{2B602}\u{2B603}\u{2B604}\u{2B605}\u{2B606}\u{2B607}\u{2B608}\u{2B609}\u{2B60A}\u{2B60B}\u{2B60C}\u{2B60D}\u{2B60E}\u{2B60F}\u{2B610}\u{2B611}\u{2B612}\u{2B613}\u{2B614}\u{2B615}\u{2B616}\u{2B617}\u{2B618}\u{2B619}\u{2B61A}\u{2B61B}\u{2B61C}\u{2B61D}\u{2B61E}\u{2B61F}\u{2B620}\u{2B621}\u{2B622}\u{2B623}\u{2B624}\u{2B625}\u{2B626}\u{2B627}\u{2B628}\u{2B629}\u{2B62A}\u{2B62B}\u{2B62C}\u{2B62D}\u{2B62E}\u{2B62F}\u{2B630}\u{2B631}\u{2B632}\u{2B633}\u{2B634}\u{2B635}\u{2B636}\u{2B637}\u{2B638}\u{2B639}\u{2B63A}\u{2B63B}\u{2B63C}\u{2B63D}\u{2B63E}\u{2B63F}\u{2B640}\u{2B641}\u{2B642}\u{2B643}\u{2B644}\u{2B645}\u{2B646}\u{2B647}\u{2B648}\u{2B649}\u{2B64A}\u{2B64B}\u{2B64C}\u{2B64D}\u{2B64E}\u{2B64F}\u{2B650}\u{2B651}\u{2B652}\u{2B653}\u{2B654}\u{2B655}\u{2B656}\u{2B657}\u{2B658}\u{2B659}\u{2B65A}\u{2B65B}\u{2B65C}\u{2B65D}\u{2B65E}\u{2B65F}\u{2B660}\u{2B661}\u{2B662}\u{2B663}\u{2B664}\u{2B665}\u{2B666}\u{2B667}\u{2B668}\u{2B669}\u{2B66A}\u{2B66B}\u{2B66C}\u{2B66D}\u{2B66E}\u{2B66F}\u{2B670}\u{2B671}\u{2B672}\u{2B673}\u{2B674}\u{2B675}\u{2B676}\u{2B677}\u{2B678}\u{2B679}\u{2B67A}\u{2B67B}\u{2B67C}\u{2B67D}\u{2B67E}\u{2B67F}\u{2B680}\u{2B681}\u{2B682}\u{2B683}\u{2B684}\u{2B685}\u{2B686}\u{2B687}\u{2B688}\u{2B689}\u{2B68A}\u{2B68B}\u{2B68C}\u{2B68D}\u{2B68E}\u{2B68F}\u{2B690}\u{2B691}\u{2B692}\u{2B693}\u{2B694}\u{2B695}\u{2B696}\u{2B697}\u{2B698}\u{2B699}\u{2B69A}\u{2B69B}\u{2B69C}\u{2B69D}\u{2B69E}\u{2B69F}\u{2B6A0}\u{2B6A1}\u{2B6A2}\u{2B6A3}\u{2B6A4}\u{2B6A5}\u{2B6A6}\u{2B6A7}\u{2B6A8}\u{2B6A9}\u{2B6AA}\u{2B6AB}\u{2B6AC}\u{2B6AD}\u{2B6AE}\u{2B6AF}\u{2B6B0}\u{2B6B1}\u{2B6B2}\u{2B6B3}\u{2B6B4}\u{2B6B5}\u{2B6B6}\u{2B6B7}\u{2B6B8}\u{2B6B9}\u{2B6BA}\u{2B6BB}\u{2B6BC}\u{2B6BD}\u{2B6BE}\u{2B6BF}\u{2B6C0}\u{2B6C1}\u{2B6C2}\u{2B6C3}\u{2B6C4}\u{2B6C5}\u{2B6C6}\u{2B6C7}\u{2B6C8}\u{2B6C9}\u{2B6CA}\u{2B6CB}\u{2B6CC}\u{2B6CD}\u{2B6CE}\u{2B6CF}\u{2B6D0}\u{2B6D1}\u{2B6D2}\u{2B6D3}\u{2B6D4}\u{2B6D5}\u{2B6D6}\u{2B6D7}\u{2B6D8}\u{2B6D9}\u{2B6DA}\u{2B6DB}\u{2B6DC}\u{2B6DD}\u{2B6DE}\u{2B6DF}\u{2B6E0}\u{2B6E1}\u{2B6E2}\u{2B6E3}\u{2B6E4}\u{2B6E5}\u{2B6E6}\u{2B6E7}\u{2B6E8}\u{2B6E9}\u{2B6EA}\u{2B6EB}\u{2B6EC}\u{2B6ED}\u{2B6EE}\u{2B6EF}\u{2B6F0}\u{2B6F1}\u{2B6F2}\u{2B6F3}\u{2B6F4}\u{2B6F5}\u{2B6F6}\u{2B6F7}\u{2B6F8}\u{2B6F9}\u{2B6FA}\u{2B6FB}\u{2B6FC}\u{2B6FD}\u{2B6FE}\u{2B6FF}\u{2B700}\u{2B701}\u{2B702}\u{2B703}\u{2B704}\u{2B705}\u{2B706}\u{2B707}\u{2B708}\u{2B709}\u{2B70A}\u{2B70B}\u{2B70C}\u{2B70D}\u{2B70E}\u{2B70F}\u{2B710}\u{2B711}\u{2B712}\u{2B713}\u{2B714}\u{2B715}\u{2B716}\u{2B717}\u{2B718}\u{2B719}\u{2B71A}\u{2B71B}\u{2B71C}\u{2B71D}\u{2B71E}\u{2B71F}\u{2B720}\u{2B721}\u{2B722}\u{2B723}\u{2B724}\u{2B725}\u{2B726}\u{2B727}\u{2B728}\u{2B729}\u{2B72A}\u{2B72B}\u{2B72C}\u{2B72D}\u{2B72E}\u{2B72F}\u{2B730}\u{2B731}\u{2B732}\u{2B733}\u{2B734}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-class.js new file mode 100644 index 000000000000..fe07915fd84d --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v5.2.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ԤԥࠀࠁࠂࠃࠄࠅࠆࠇࠈࠉࠊࠋࠌࠍࠎࠏࠐࠑࠒࠓࠔࠕࠚࠤࠨॹॺᅚᅛᅜᅝᅞᆣᆤᆥᆦᆧᇺᇻᇼᇽᇾᇿᙷᙸᙹᙺᙻᙼᙽᙾᙿᢰᢱᢲᢳᢴᢵᢶᢷᢸᢹᢺᢻᢼᢽᢾᢿᣀᣁᣂᣃᣄᣅᣆᣇᣈᣉᣊᣋᣌᣍᣎᣏᣐᣑᣒᣓᣔᣕᣖᣗᣘᣙᣚᣛᣜᣝᣞᣟᣠᣡᣢᣣᣤᣥᣦᣧᣨᣩᣪᣫᣬᣭᣮᣯᣰᣱᣲᣳᣴᣵᦪᦫᨠᨡᨢᨣᨤᨥᨦᨧᨨᨩᨪᨫᨬᨭᨮᨯᨰᨱᨲᨳᨴᨵᨶᨷᨸᨹᨺᨻᨼᨽᨾᨿᩀᩁᩂᩃᩄᩅᩆᩇᩈᩉᩊᩋᩌᩍᩎᩏᩐᩑᩒᩓᩔᪧᳩᳪᳫᳬᳮᳯᳰᳱⱰⱾⱿⳫⳬⳭⳮ鿄鿅鿆鿇鿈鿉鿊鿋ꓐꓑꓒꓓꓔꓕꓖꓗꓘꓙꓚꓛꓜꓝꓞꓟꓠꓡꓢꓣꓤꓥꓦꓧꓨꓩꓪꓫꓬꓭꓮꓯꓰꓱꓲꓳꓴꓵꓶꓷꓸꓹꓺꓻꓼꓽꚠꚡꚢꚣꚤꚥꚦꚧꚨꚩꚪꚫꚬꚭꚮꚯꚰꚱꚲꚳꚴꚵꚶꚷꚸꚹꚺꚻꚼꚽꚾꚿꛀꛁꛂꛃꛄꛅꛆꛇꛈꛉꛊꛋꛌꛍꛎꛏꛐꛑꛒꛓꛔꛕꛖꛗꛘꛙꛚꛛꛜꛝꛞꛟꛠꛡꛢꛣꛤꛥꛦꛧꛨꛩꛪꛫꛬꛭꛮꛯꣲꣳꣴꣵꣶꣷꣻꥠꥡꥢꥣꥤꥥꥦꥧꥨꥩꥪꥫꥬꥭꥮꥯꥰꥱꥲꥳꥴꥵꥶꥷꥸꥹꥺꥻꥼꦄꦅꦆꦇꦈꦉꦊꦋꦌꦍꦎꦏꦐꦑꦒꦓꦔꦕꦖꦗꦘꦙꦚꦛꦜꦝꦞꦟꦠꦡꦢꦣꦤꦥꦦꦧꦨꦩꦪꦫꦬꦭꦮꦯꦰꦱꦲꧏꩠꩡꩢꩣꩤꩥꩦꩧꩨꩩꩪꩫꩬꩭꩮꩯꩰꩱꩲꩳꩴꩵꩶꩺꪀꪁꪂꪃꪄꪅꪆꪇꪈꪉꪊꪋꪌꪍꪎꪏꪐꪑꪒꪓꪔꪕꪖꪗꪘꪙꪚꪛꪜꪝꪞꪟꪠꪡꪢꪣꪤꪥꪦꪧꪨꪩꪪꪫꪬꪭꪮꪯꪱꪵꪶꪹꪺꪻꪼꪽꫀꫂꫛꫜꫝꯀꯁꯂꯃꯄꯅꯆꯇꯈꯉꯊꯋꯌꯍꯎꯏꯐꯑꯒꯓꯔꯕꯖꯗꯘꯙꯚꯛꯜꯝꯞꯟꯠꯡꯢힰힱힲힳힴힵힶힷힸힹힺힻힼힽힾힿퟀퟁퟂퟃퟄퟅퟆퟋퟌퟍퟎퟏퟐퟑퟒퟓퟔퟕퟖퟗퟘퟙퟚퟛퟜퟝퟞퟟퟠퟡퟢퟣퟤퟥퟦퟧퟨퟩퟪퟫퟬퟭퟮퟯퟰퟱퟲퟳퟴퟵퟶퟷퟸퟹퟺퟻ恵𤋮舘𐡀𐡁𐡂𐡃𐡄𐡅𐡆𐡇𐡈𐡉𐡊𐡋𐡌𐡍𐡎𐡏𐡐𐡑𐡒𐡓𐡔𐡕𐩠𐩡𐩢𐩣𐩤𐩥𐩦𐩧𐩨𐩩𐩪𐩫𐩬𐩭𐩮𐩯𐩰𐩱𐩲𐩳𐩴𐩵𐩶𐩷𐩸𐩹𐩺𐩻𐩼𐬀𐬁𐬂𐬃𐬄𐬅𐬆𐬇𐬈𐬉𐬊𐬋𐬌𐬍𐬎𐬏𐬐𐬑𐬒𐬓𐬔𐬕𐬖𐬗𐬘𐬙𐬚𐬛𐬜𐬝𐬞𐬟𐬠𐬡𐬢𐬣𐬤𐬥𐬦𐬧𐬨𐬩𐬪𐬫𐬬𐬭𐬮𐬯𐬰𐬱𐬲𐬳𐬴𐬵𐭀𐭁𐭂𐭃𐭄𐭅𐭆𐭇𐭈𐭉𐭊𐭋𐭌𐭍𐭎𐭏𐭐𐭑𐭒𐭓𐭔𐭕𐭠𐭡𐭢𐭣𐭤𐭥𐭦𐭧𐭨𐭩𐭪𐭫𐭬𐭭𐭮𐭯𐭰𐭱𐭲𐰀𐰁𐰂𐰃𐰄𐰅𐰆𐰇𐰈𐰉𐰊𐰋𐰌𐰍𐰎𐰏𐰐𐰑𐰒𐰓𐰔𐰕𐰖𐰗𐰘𐰙𐰚𐰛𐰜𐰝𐰞𐰟𐰠𐰡𐰢𐰣𐰤𐰥𐰦𐰧𐰨𐰩𐰪𐰫𐰬𐰭𐰮𐰯𐰰𐰱𐰲𐰳𐰴𐰵𐰶𐰷𐰸𐰹𐰺𐰻𐰼𐰽𐰾𐰿𐱀𐱁𐱂𐱃𐱄𐱅𐱆𐱇𐱈𑂃𑂄𑂅𑂆𑂇𑂈𑂉𑂊𑂋𑂌𑂍𑂎𑂏𑂐𑂑𑂒𑂓𑂔𑂕𑂖𑂗𑂘𑂙𑂚𑂛𑂜𑂝𑂞𑂟𑂠𑂡𑂢𑂣𑂤𑂥𑂦𑂧𑂨𑂩𑂪𑂫𑂬𑂭𑂮𑂯𓀀𓀁𓀂𓀃𓀄𓀅𓀆𓀇𓀈𓀉𓀊𓀋𓀌𓀍𓀎𓀏𓀐𓀑𓀒𓀓𓀔𓀕𓀖𓀗𓀘𓀙𓀚𓀛𓀜𓀝𓀞𓀟𓀠𓀡𓀢𓀣𓀤𓀥𓀦𓀧𓀨𓀩𓀪𓀫𓀬𓀭𓀮𓀯𓀰𓀱𓀲𓀳𓀴𓀵𓀶𓀷𓀸𓀹𓀺𓀻𓀼𓀽𓀾𓀿𓁀𓁁𓁂𓁃𓁄𓁅𓁆𓁇𓁈𓁉𓁊𓁋𓁌𓁍𓁎𓁏𓁐𓁑𓁒𓁓𓁔𓁕𓁖𓁗𓁘𓁙𓁚𓁛𓁜𓁝𓁞𓁟𓁠𓁡𓁢𓁣𓁤𓁥𓁦𓁧𓁨𓁩𓁪𓁫𓁬𓁭𓁮𓁯𓁰𓁱𓁲𓁳𓁴𓁵𓁶𓁷𓁸𓁹𓁺𓁻𓁼𓁽𓁾𓁿𓂀𓂁𓂂𓂃𓂄𓂅𓂆𓂇𓂈𓂉𓂊𓂋𓂌𓂍𓂎𓂏𓂐𓂑𓂒𓂓𓂔𓂕𓂖𓂗𓂘𓂙𓂚𓂛𓂜𓂝𓂞𓂟𓂠𓂡𓂢𓂣𓂤𓂥𓂦𓂧𓂨𓂩𓂪𓂫𓂬𓂭𓂮𓂯𓂰𓂱𓂲𓂳𓂴𓂵𓂶𓂷𓂸𓂹𓂺𓂻𓂼𓂽𓂾𓂿𓃀𓃁𓃂𓃃𓃄𓃅𓃆𓃇𓃈𓃉𓃊𓃋𓃌𓃍𓃎𓃏𓃐𓃑𓃒𓃓𓃔𓃕𓃖𓃗𓃘𓃙𓃚𓃛𓃜𓃝𓃞𓃟𓃠𓃡𓃢𓃣𓃤𓃥𓃦𓃧𓃨𓃩𓃪𓃫𓃬𓃭𓃮𓃯𓃰𓃱𓃲𓃳𓃴𓃵𓃶𓃷𓃸𓃹𓃺𓃻𓃼𓃽𓃾𓃿𓄀𓄁𓄂𓄃𓄄𓄅𓄆𓄇𓄈𓄉𓄊𓄋𓄌𓄍𓄎𓄏𓄐𓄑𓄒𓄓𓄔𓄕𓄖𓄗𓄘𓄙𓄚𓄛𓄜𓄝𓄞𓄟𓄠𓄡𓄢𓄣𓄤𓄥𓄦𓄧𓄨𓄩𓄪𓄫𓄬𓄭𓄮𓄯𓄰𓄱𓄲𓄳𓄴𓄵𓄶𓄷𓄸𓄹𓄺𓄻𓄼𓄽𓄾𓄿𓅀𓅁𓅂𓅃𓅄𓅅𓅆𓅇𓅈𓅉𓅊𓅋𓅌𓅍𓅎𓅏𓅐𓅑𓅒𓅓𓅔𓅕𓅖𓅗𓅘𓅙𓅚𓅛𓅜𓅝𓅞𓅟𓅠𓅡𓅢𓅣𓅤𓅥𓅦𓅧𓅨𓅩𓅪𓅫𓅬𓅭𓅮𓅯𓅰𓅱𓅲𓅳𓅴𓅵𓅶𓅷𓅸𓅹𓅺𓅻𓅼𓅽𓅾𓅿𓆀𓆁𓆂𓆃𓆄𓆅𓆆𓆇𓆈𓆉𓆊𓆋𓆌𓆍𓆎𓆏𓆐𓆑𓆒𓆓𓆔𓆕𓆖𓆗𓆘𓆙𓆚𓆛𓆜𓆝𓆞𓆟𓆠𓆡𓆢𓆣𓆤𓆥𓆦𓆧𓆨𓆩𓆪𓆫𓆬𓆭𓆮𓆯𓆰𓆱𓆲𓆳𓆴𓆵𓆶𓆷𓆸𓆹𓆺𓆻𓆼𓆽𓆾𓆿𓇀𓇁𓇂𓇃𓇄𓇅𓇆𓇇𓇈𓇉𓇊𓇋𓇌𓇍𓇎𓇏𓇐𓇑𓇒𓇓𓇔𓇕𓇖𓇗𓇘𓇙𓇚𓇛𓇜𓇝𓇞𓇟𓇠𓇡𓇢𓇣𓇤𓇥𓇦𓇧𓇨𓇩𓇪𓇫𓇬𓇭𓇮𓇯𓇰𓇱𓇲𓇳𓇴𓇵𓇶𓇷𓇸𓇹𓇺𓇻𓇼𓇽𓇾𓇿𓈀𓈁𓈂𓈃𓈄𓈅𓈆𓈇𓈈𓈉𓈊𓈋𓈌𓈍𓈎𓈏𓈐𓈑𓈒𓈓𓈔𓈕𓈖𓈗𓈘𓈙𓈚𓈛𓈜𓈝𓈞𓈟𓈠𓈡𓈢𓈣𓈤𓈥𓈦𓈧𓈨𓈩𓈪𓈫𓈬𓈭𓈮𓈯𓈰𓈱𓈲𓈳𓈴𓈵𓈶𓈷𓈸𓈹𓈺𓈻𓈼𓈽𓈾𓈿𓉀𓉁𓉂𓉃𓉄𓉅𓉆𓉇𓉈𓉉𓉊𓉋𓉌𓉍𓉎𓉏𓉐𓉑𓉒𓉓𓉔𓉕𓉖𓉗𓉘𓉙𓉚𓉛𓉜𓉝𓉞𓉟𓉠𓉡𓉢𓉣𓉤𓉥𓉦𓉧𓉨𓉩𓉪𓉫𓉬𓉭𓉮𓉯𓉰𓉱𓉲𓉳𓉴𓉵𓉶𓉷𓉸𓉹𓉺𓉻𓉼𓉽𓉾𓉿𓊀𓊁𓊂𓊃𓊄𓊅𓊆𓊇𓊈𓊉𓊊𓊋𓊌𓊍𓊎𓊏𓊐𓊑𓊒𓊓𓊔𓊕𓊖𓊗𓊘𓊙𓊚𓊛𓊜𓊝𓊞𓊟𓊠𓊡𓊢𓊣𓊤𓊥𓊦𓊧𓊨𓊩𓊪𓊫𓊬𓊭𓊮𓊯𓊰𓊱𓊲𓊳𓊴𓊵𓊶𓊷𓊸𓊹𓊺𓊻𓊼𓊽𓊾𓊿𓋀𓋁𓋂𓋃𓋄𓋅𓋆𓋇𓋈𓋉𓋊𓋋𓋌𓋍𓋎𓋏𓋐𓋑𓋒𓋓𓋔𓋕𓋖𓋗𓋘𓋙𓋚𓋛𓋜𓋝𓋞𓋟𓋠𓋡𓋢𓋣𓋤𓋥𓋦𓋧𓋨𓋩𓋪𓋫𓋬𓋭𓋮𓋯𓋰𓋱𓋲𓋳𓋴𓋵𓋶𓋷𓋸𓋹𓋺𓋻𓋼𓋽𓋾𓋿𓌀𓌁𓌂𓌃𓌄𓌅𓌆𓌇𓌈𓌉𓌊𓌋𓌌𓌍𓌎𓌏𓌐𓌑𓌒𓌓𓌔𓌕𓌖𓌗𓌘𓌙𓌚𓌛𓌜𓌝𓌞𓌟𓌠𓌡𓌢𓌣𓌤𓌥𓌦𓌧𓌨𓌩𓌪𓌫𓌬𓌭𓌮𓌯𓌰𓌱𓌲𓌳𓌴𓌵𓌶𓌷𓌸𓌹𓌺𓌻𓌼𓌽𓌾𓌿𓍀𓍁𓍂𓍃𓍄𓍅𓍆𓍇𓍈𓍉𓍊𓍋𓍌𓍍𓍎𓍏𓍐𓍑𓍒𓍓𓍔𓍕𓍖𓍗𓍘𓍙𓍚𓍛𓍜𓍝𓍞𓍟𓍠𓍡𓍢𓍣𓍤𓍥𓍦𓍧𓍨𓍩𓍪𓍫𓍬𓍭𓍮𓍯𓍰𓍱𓍲𓍳𓍴𓍵𓍶𓍷𓍸𓍹𓍺𓍻𓍼𓍽𓍾𓍿𓎀𓎁𓎂𓎃𓎄𓎅𓎆𓎇𓎈𓎉𓎊𓎋𓎌𓎍𓎎𓎏𓎐𓎑𓎒𓎓𓎔𓎕𓎖𓎗𓎘𓎙𓎚𓎛𓎜𓎝𓎞𓎟𓎠𓎡𓎢𓎣𓎤𓎥𓎦𓎧𓎨𓎩𓎪𓎫𓎬𓎭𓎮𓎯𓎰𓎱𓎲𓎳𓎴𓎵𓎶𓎷𓎸𓎹𓎺𓎻𓎼𓎽𓎾𓎿𓏀𓏁𓏂𓏃𓏄𓏅𓏆𓏇𓏈𓏉𓏊𓏋𓏌𓏍𓏎𓏏𓏐𓏑𓏒𓏓𓏔𓏕𓏖𓏗𓏘𓏙𓏚𓏛𓏜𓏝𓏞𓏟𓏠𓏡𓏢𓏣𓏤𓏥𓏦𓏧𓏨𓏩𓏪𓏫𓏬𓏭𓏮𓏯𓏰𓏱𓏲𓏳𓏴𓏵𓏶𓏷𓏸𓏹𓏺𓏻𓏼𓏽𓏾𓏿𓐀𓐁𓐂𓐃𓐄𓐅𓐆𓐇𓐈𓐉𓐊𓐋𓐌𓐍𓐎𓐏𓐐𓐑𓐒𓐓𓐔𓐕𓐖𓐗𓐘𓐙𓐚𓐛𓐜𓐝𓐞𓐟𓐠𓐡𓐢𓐣𓐤𓐥𓐦𓐧𓐨𓐩𓐪𓐫𓐬𓐭𓐮𪜀𪜁𪜂𪜃𪜄𪜅𪜆𪜇𪜈𪜉𪜊𪜋𪜌𪜍𪜎𪜏𪜐𪜑𪜒𪜓𪜔𪜕𪜖𪜗𪜘𪜙𪜚𪜛𪜜𪜝𪜞𪜟𪜠𪜡𪜢𪜣𪜤𪜥𪜦𪜧𪜨𪜩𪜪𪜫𪜬𪜭𪜮𪜯𪜰𪜱𪜲𪜳𪜴𪜵𪜶𪜷𪜸𪜹𪜺𪜻𪜼𪜽𪜾𪜿𪝀𪝁𪝂𪝃𪝄𪝅𪝆𪝇𪝈𪝉𪝊𪝋𪝌𪝍𪝎𪝏𪝐𪝑𪝒𪝓𪝔𪝕𪝖𪝗𪝘𪝙𪝚𪝛𪝜𪝝𪝞𪝟𪝠𪝡𪝢𪝣𪝤𪝥𪝦𪝧𪝨𪝩𪝪𪝫𪝬𪝭𪝮𪝯𪝰𪝱𪝲𪝳𪝴𪝵𪝶𪝷𪝸𪝹𪝺𪝻𪝼𪝽𪝾𪝿𪞀𪞁𪞂𪞃𪞄𪞅𪞆𪞇𪞈𪞉𪞊𪞋𪞌𪞍𪞎𪞏𪞐𪞑𪞒𪞓𪞔𪞕𪞖𪞗𪞘𪞙𪞚𪞛𪞜𪞝𪞞𪞟𪞠𪞡𪞢𪞣𪞤𪞥𪞦𪞧𪞨𪞩𪞪𪞫𪞬𪞭𪞮𪞯𪞰𪞱𪞲𪞳𪞴𪞵𪞶𪞷𪞸𪞹𪞺𪞻𪞼𪞽𪞾𪞿𪟀𪟁𪟂𪟃𪟄𪟅𪟆𪟇𪟈𪟉𪟊𪟋𪟌𪟍𪟎𪟏𪟐𪟑𪟒𪟓𪟔𪟕𪟖𪟗𪟘𪟙𪟚𪟛𪟜𪟝𪟞𪟟𪟠𪟡𪟢𪟣𪟤𪟥𪟦𪟧𪟨𪟩𪟪𪟫𪟬𪟭𪟮𪟯𪟰𪟱𪟲𪟳𪟴𪟵𪟶𪟷𪟸𪟹𪟺𪟻𪟼𪟽𪟾𪟿𪠀𪠁𪠂𪠃𪠄𪠅𪠆𪠇𪠈𪠉𪠊𪠋𪠌𪠍𪠎𪠏𪠐𪠑𪠒𪠓𪠔𪠕𪠖𪠗𪠘𪠙𪠚𪠛𪠜𪠝𪠞𪠟𪠠𪠡𪠢𪠣𪠤𪠥𪠦𪠧𪠨𪠩𪠪𪠫𪠬𪠭𪠮𪠯𪠰𪠱𪠲𪠳𪠴𪠵𪠶𪠷𪠸𪠹𪠺𪠻𪠼𪠽𪠾𪠿𪡀𪡁𪡂𪡃𪡄𪡅𪡆𪡇𪡈𪡉𪡊𪡋𪡌𪡍𪡎𪡏𪡐𪡑𪡒𪡓𪡔𪡕𪡖𪡗𪡘𪡙𪡚𪡛𪡜𪡝𪡞𪡟𪡠𪡡𪡢𪡣𪡤𪡥𪡦𪡧𪡨𪡩𪡪𪡫𪡬𪡭𪡮𪡯𪡰𪡱𪡲𪡳𪡴𪡵𪡶𪡷𪡸𪡹𪡺𪡻𪡼𪡽𪡾𪡿𪢀𪢁𪢂𪢃𪢄𪢅𪢆𪢇𪢈𪢉𪢊𪢋𪢌𪢍𪢎𪢏𪢐𪢑𪢒𪢓𪢔𪢕𪢖𪢗𪢘𪢙𪢚𪢛𪢜𪢝𪢞𪢟𪢠𪢡𪢢𪢣𪢤𪢥𪢦𪢧𪢨𪢩𪢪𪢫𪢬𪢭𪢮𪢯𪢰𪢱𪢲𪢳𪢴𪢵𪢶𪢷𪢸𪢹𪢺𪢻𪢼𪢽𪢾𪢿𪣀𪣁𪣂𪣃𪣄𪣅𪣆𪣇𪣈𪣉𪣊𪣋𪣌𪣍𪣎𪣏𪣐𪣑𪣒𪣓𪣔𪣕𪣖𪣗𪣘𪣙𪣚𪣛𪣜𪣝𪣞𪣟𪣠𪣡𪣢𪣣𪣤𪣥𪣦𪣧𪣨𪣩𪣪𪣫𪣬𪣭𪣮𪣯𪣰𪣱𪣲𪣳𪣴𪣵𪣶𪣷𪣸𪣹𪣺𪣻𪣼𪣽𪣾𪣿𪤀𪤁𪤂𪤃𪤄𪤅𪤆𪤇𪤈𪤉𪤊𪤋𪤌𪤍𪤎𪤏𪤐𪤑𪤒𪤓𪤔𪤕𪤖𪤗𪤘𪤙𪤚𪤛𪤜𪤝𪤞𪤟𪤠𪤡𪤢𪤣𪤤𪤥𪤦𪤧𪤨𪤩𪤪𪤫𪤬𪤭𪤮𪤯𪤰𪤱𪤲𪤳𪤴𪤵𪤶𪤷𪤸𪤹𪤺𪤻𪤼𪤽𪤾𪤿𪥀𪥁𪥂𪥃𪥄𪥅𪥆𪥇𪥈𪥉𪥊𪥋𪥌𪥍𪥎𪥏𪥐𪥑𪥒𪥓𪥔𪥕𪥖𪥗𪥘𪥙𪥚𪥛𪥜𪥝𪥞𪥟𪥠𪥡𪥢𪥣𪥤𪥥𪥦𪥧𪥨𪥩𪥪𪥫𪥬𪥭𪥮𪥯𪥰𪥱𪥲𪥳𪥴𪥵𪥶𪥷𪥸𪥹𪥺𪥻𪥼𪥽𪥾𪥿𪦀𪦁𪦂𪦃𪦄𪦅𪦆𪦇𪦈𪦉𪦊𪦋𪦌𪦍𪦎𪦏𪦐𪦑𪦒𪦓𪦔𪦕𪦖𪦗𪦘𪦙𪦚𪦛𪦜𪦝𪦞𪦟𪦠𪦡𪦢𪦣𪦤𪦥𪦦𪦧𪦨𪦩𪦪𪦫𪦬𪦭𪦮𪦯𪦰𪦱𪦲𪦳𪦴𪦵𪦶𪦷𪦸𪦹𪦺𪦻𪦼𪦽𪦾𪦿𪧀𪧁𪧂𪧃𪧄𪧅𪧆𪧇𪧈𪧉𪧊𪧋𪧌𪧍𪧎𪧏𪧐𪧑𪧒𪧓𪧔𪧕𪧖𪧗𪧘𪧙𪧚𪧛𪧜𪧝𪧞𪧟𪧠𪧡𪧢𪧣𪧤𪧥𪧦𪧧𪧨𪧩𪧪𪧫𪧬𪧭𪧮𪧯𪧰𪧱𪧲𪧳𪧴𪧵𪧶𪧷𪧸𪧹𪧺𪧻𪧼𪧽𪧾𪧿𪨀𪨁𪨂𪨃𪨄𪨅𪨆𪨇𪨈𪨉𪨊𪨋𪨌𪨍𪨎𪨏𪨐𪨑𪨒𪨓𪨔𪨕𪨖𪨗𪨘𪨙𪨚𪨛𪨜𪨝𪨞𪨟𪨠𪨡𪨢𪨣𪨤𪨥𪨦𪨧𪨨𪨩𪨪𪨫𪨬𪨭𪨮𪨯𪨰𪨱𪨲𪨳𪨴𪨵𪨶𪨷𪨸𪨹𪨺𪨻𪨼𪨽𪨾𪨿𪩀𪩁𪩂𪩃𪩄𪩅𪩆𪩇𪩈𪩉𪩊𪩋𪩌𪩍𪩎𪩏𪩐𪩑𪩒𪩓𪩔𪩕𪩖𪩗𪩘𪩙𪩚𪩛𪩜𪩝𪩞𪩟𪩠𪩡𪩢𪩣𪩤𪩥𪩦𪩧𪩨𪩩𪩪𪩫𪩬𪩭𪩮𪩯𪩰𪩱𪩲𪩳𪩴𪩵𪩶𪩷𪩸𪩹𪩺𪩻𪩼𪩽𪩾𪩿𪪀𪪁𪪂𪪃𪪄𪪅𪪆𪪇𪪈𪪉𪪊𪪋𪪌𪪍𪪎𪪏𪪐𪪑𪪒𪪓𪪔𪪕𪪖𪪗𪪘𪪙𪪚𪪛𪪜𪪝𪪞𪪟𪪠𪪡𪪢𪪣𪪤𪪥𪪦𪪧𪪨𪪩𪪪𪪫𪪬𪪭𪪮𪪯𪪰𪪱𪪲𪪳𪪴𪪵𪪶𪪷𪪸𪪹𪪺𪪻𪪼𪪽𪪾𪪿𪫀𪫁𪫂𪫃𪫄𪫅𪫆𪫇𪫈𪫉𪫊𪫋𪫌𪫍𪫎𪫏𪫐𪫑𪫒𪫓𪫔𪫕𪫖𪫗𪫘𪫙𪫚𪫛𪫜𪫝𪫞𪫟𪫠𪫡𪫢𪫣𪫤𪫥𪫦𪫧𪫨𪫩𪫪𪫫𪫬𪫭𪫮𪫯𪫰𪫱𪫲𪫳𪫴𪫵𪫶𪫷𪫸𪫹𪫺𪫻𪫼𪫽𪫾𪫿𪬀𪬁𪬂𪬃𪬄𪬅𪬆𪬇𪬈𪬉𪬊𪬋𪬌𪬍𪬎𪬏𪬐𪬑𪬒𪬓𪬔𪬕𪬖𪬗𪬘𪬙𪬚𪬛𪬜𪬝𪬞𪬟𪬠𪬡𪬢𪬣𪬤𪬥𪬦𪬧𪬨𪬩𪬪𪬫𪬬𪬭𪬮𪬯𪬰𪬱𪬲𪬳𪬴𪬵𪬶𪬷𪬸𪬹𪬺𪬻𪬼𪬽𪬾𪬿𪭀𪭁𪭂𪭃𪭄𪭅𪭆𪭇𪭈𪭉𪭊𪭋𪭌𪭍𪭎𪭏𪭐𪭑𪭒𪭓𪭔𪭕𪭖𪭗𪭘𪭙𪭚𪭛𪭜𪭝𪭞𪭟𪭠𪭡𪭢𪭣𪭤𪭥𪭦𪭧𪭨𪭩𪭪𪭫𪭬𪭭𪭮𪭯𪭰𪭱𪭲𪭳𪭴𪭵𪭶𪭷𪭸𪭹𪭺𪭻𪭼𪭽𪭾𪭿𪮀𪮁𪮂𪮃𪮄𪮅𪮆𪮇𪮈𪮉𪮊𪮋𪮌𪮍𪮎𪮏𪮐𪮑𪮒𪮓𪮔𪮕𪮖𪮗𪮘𪮙𪮚𪮛𪮜𪮝𪮞𪮟𪮠𪮡𪮢𪮣𪮤𪮥𪮦𪮧𪮨𪮩𪮪𪮫𪮬𪮭𪮮𪮯𪮰𪮱𪮲𪮳𪮴𪮵𪮶𪮷𪮸𪮹𪮺𪮻𪮼𪮽𪮾𪮿𪯀𪯁𪯂𪯃𪯄𪯅𪯆𪯇𪯈𪯉𪯊𪯋𪯌𪯍𪯎𪯏𪯐𪯑𪯒𪯓𪯔𪯕𪯖𪯗𪯘𪯙𪯚𪯛𪯜𪯝𪯞𪯟𪯠𪯡𪯢𪯣𪯤𪯥𪯦𪯧𪯨𪯩𪯪𪯫𪯬𪯭𪯮𪯯𪯰𪯱𪯲𪯳𪯴𪯵𪯶𪯷𪯸𪯹𪯺𪯻𪯼𪯽𪯾𪯿𪰀𪰁𪰂𪰃𪰄𪰅𪰆𪰇𪰈𪰉𪰊𪰋𪰌𪰍𪰎𪰏𪰐𪰑𪰒𪰓𪰔𪰕𪰖𪰗𪰘𪰙𪰚𪰛𪰜𪰝𪰞𪰟𪰠𪰡𪰢𪰣𪰤𪰥𪰦𪰧𪰨𪰩𪰪𪰫𪰬𪰭𪰮𪰯𪰰𪰱𪰲𪰳𪰴𪰵𪰶𪰷𪰸𪰹𪰺𪰻𪰼𪰽𪰾𪰿𪱀𪱁𪱂𪱃𪱄𪱅𪱆𪱇𪱈𪱉𪱊𪱋𪱌𪱍𪱎𪱏𪱐𪱑𪱒𪱓𪱔𪱕𪱖𪱗𪱘𪱙𪱚𪱛𪱜𪱝𪱞𪱟𪱠𪱡𪱢𪱣𪱤𪱥𪱦𪱧𪱨𪱩𪱪𪱫𪱬𪱭𪱮𪱯𪱰𪱱𪱲𪱳𪱴𪱵𪱶𪱷𪱸𪱹𪱺𪱻𪱼𪱽𪱾𪱿𪲀𪲁𪲂𪲃𪲄𪲅𪲆𪲇𪲈𪲉𪲊𪲋𪲌𪲍𪲎𪲏𪲐𪲑𪲒𪲓𪲔𪲕𪲖𪲗𪲘𪲙𪲚𪲛𪲜𪲝𪲞𪲟𪲠𪲡𪲢𪲣𪲤𪲥𪲦𪲧𪲨𪲩𪲪𪲫𪲬𪲭𪲮𪲯𪲰𪲱𪲲𪲳𪲴𪲵𪲶𪲷𪲸𪲹𪲺𪲻𪲼𪲽𪲾𪲿𪳀𪳁𪳂𪳃𪳄𪳅𪳆𪳇𪳈𪳉𪳊𪳋𪳌𪳍𪳎𪳏𪳐𪳑𪳒𪳓𪳔𪳕𪳖𪳗𪳘𪳙𪳚𪳛𪳜𪳝𪳞𪳟𪳠𪳡𪳢𪳣𪳤𪳥𪳦𪳧𪳨𪳩𪳪𪳫𪳬𪳭𪳮𪳯𪳰𪳱𪳲𪳳𪳴𪳵𪳶𪳷𪳸𪳹𪳺𪳻𪳼𪳽𪳾𪳿𪴀𪴁𪴂𪴃𪴄𪴅𪴆𪴇𪴈𪴉𪴊𪴋𪴌𪴍𪴎𪴏𪴐𪴑𪴒𪴓𪴔𪴕𪴖𪴗𪴘𪴙𪴚𪴛𪴜𪴝𪴞𪴟𪴠𪴡𪴢𪴣𪴤𪴥𪴦𪴧𪴨𪴩𪴪𪴫𪴬𪴭𪴮𪴯𪴰𪴱𪴲𪴳𪴴𪴵𪴶𪴷𪴸𪴹𪴺𪴻𪴼𪴽𪴾𪴿𪵀𪵁𪵂𪵃𪵄𪵅𪵆𪵇𪵈𪵉𪵊𪵋𪵌𪵍𪵎𪵏𪵐𪵑𪵒𪵓𪵔𪵕𪵖𪵗𪵘𪵙𪵚𪵛𪵜𪵝𪵞𪵟𪵠𪵡𪵢𪵣𪵤𪵥𪵦𪵧𪵨𪵩𪵪𪵫𪵬𪵭𪵮𪵯𪵰𪵱𪵲𪵳𪵴𪵵𪵶𪵷𪵸𪵹𪵺𪵻𪵼𪵽𪵾𪵿𪶀𪶁𪶂𪶃𪶄𪶅𪶆𪶇𪶈𪶉𪶊𪶋𪶌𪶍𪶎𪶏𪶐𪶑𪶒𪶓𪶔𪶕𪶖𪶗𪶘𪶙𪶚𪶛𪶜𪶝𪶞𪶟𪶠𪶡𪶢𪶣𪶤𪶥𪶦𪶧𪶨𪶩𪶪𪶫𪶬𪶭𪶮𪶯𪶰𪶱𪶲𪶳𪶴𪶵𪶶𪶷𪶸𪶹𪶺𪶻𪶼𪶽𪶾𪶿𪷀𪷁𪷂𪷃𪷄𪷅𪷆𪷇𪷈𪷉𪷊𪷋𪷌𪷍𪷎𪷏𪷐𪷑𪷒𪷓𪷔𪷕𪷖𪷗𪷘𪷙𪷚𪷛𪷜𪷝𪷞𪷟𪷠𪷡𪷢𪷣𪷤𪷥𪷦𪷧𪷨𪷩𪷪𪷫𪷬𪷭𪷮𪷯𪷰𪷱𪷲𪷳𪷴𪷵𪷶𪷷𪷸𪷹𪷺𪷻𪷼𪷽𪷾𪷿𪸀𪸁𪸂𪸃𪸄𪸅𪸆𪸇𪸈𪸉𪸊𪸋𪸌𪸍𪸎𪸏𪸐𪸑𪸒𪸓𪸔𪸕𪸖𪸗𪸘𪸙𪸚𪸛𪸜𪸝𪸞𪸟𪸠𪸡𪸢𪸣𪸤𪸥𪸦𪸧𪸨𪸩𪸪𪸫𪸬𪸭𪸮𪸯𪸰𪸱𪸲𪸳𪸴𪸵𪸶𪸷𪸸𪸹𪸺𪸻𪸼𪸽𪸾𪸿𪹀𪹁𪹂𪹃𪹄𪹅𪹆𪹇𪹈𪹉𪹊𪹋𪹌𪹍𪹎𪹏𪹐𪹑𪹒𪹓𪹔𪹕𪹖𪹗𪹘𪹙𪹚𪹛𪹜𪹝𪹞𪹟𪹠𪹡𪹢𪹣𪹤𪹥𪹦𪹧𪹨𪹩𪹪𪹫𪹬𪹭𪹮𪹯𪹰𪹱𪹲𪹳𪹴𪹵𪹶𪹷𪹸𪹹𪹺𪹻𪹼𪹽𪹾𪹿𪺀𪺁𪺂𪺃𪺄𪺅𪺆𪺇𪺈𪺉𪺊𪺋𪺌𪺍𪺎𪺏𪺐𪺑𪺒𪺓𪺔𪺕𪺖𪺗𪺘𪺙𪺚𪺛𪺜𪺝𪺞𪺟𪺠𪺡𪺢𪺣𪺤𪺥𪺦𪺧𪺨𪺩𪺪𪺫𪺬𪺭𪺮𪺯𪺰𪺱𪺲𪺳𪺴𪺵𪺶𪺷𪺸𪺹𪺺𪺻𪺼𪺽𪺾𪺿𪻀𪻁𪻂𪻃𪻄𪻅𪻆𪻇𪻈𪻉𪻊𪻋𪻌𪻍𪻎𪻏𪻐𪻑𪻒𪻓𪻔𪻕𪻖𪻗𪻘𪻙𪻚𪻛𪻜𪻝𪻞𪻟𪻠𪻡𪻢𪻣𪻤𪻥𪻦𪻧𪻨𪻩𪻪𪻫𪻬𪻭𪻮𪻯𪻰𪻱𪻲𪻳𪻴𪻵𪻶𪻷𪻸𪻹𪻺𪻻𪻼𪻽𪻾𪻿𪼀𪼁𪼂𪼃𪼄𪼅𪼆𪼇𪼈𪼉𪼊𪼋𪼌𪼍𪼎𪼏𪼐𪼑𪼒𪼓𪼔𪼕𪼖𪼗𪼘𪼙𪼚𪼛𪼜𪼝𪼞𪼟𪼠𪼡𪼢𪼣𪼤𪼥𪼦𪼧𪼨𪼩𪼪𪼫𪼬𪼭𪼮𪼯𪼰𪼱𪼲𪼳𪼴𪼵𪼶𪼷𪼸𪼹𪼺𪼻𪼼𪼽𪼾𪼿𪽀𪽁𪽂𪽃𪽄𪽅𪽆𪽇𪽈𪽉𪽊𪽋𪽌𪽍𪽎𪽏𪽐𪽑𪽒𪽓𪽔𪽕𪽖𪽗𪽘𪽙𪽚𪽛𪽜𪽝𪽞𪽟𪽠𪽡𪽢𪽣𪽤𪽥𪽦𪽧𪽨𪽩𪽪𪽫𪽬𪽭𪽮𪽯𪽰𪽱𪽲𪽳𪽴𪽵𪽶𪽷𪽸𪽹𪽺𪽻𪽼𪽽𪽾𪽿𪾀𪾁𪾂𪾃𪾄𪾅𪾆𪾇𪾈𪾉𪾊𪾋𪾌𪾍𪾎𪾏𪾐𪾑𪾒𪾓𪾔𪾕𪾖𪾗𪾘𪾙𪾚𪾛𪾜𪾝𪾞𪾟𪾠𪾡𪾢𪾣𪾤𪾥𪾦𪾧𪾨𪾩𪾪𪾫𪾬𪾭𪾮𪾯𪾰𪾱𪾲𪾳𪾴𪾵𪾶𪾷𪾸𪾹𪾺𪾻𪾼𪾽𪾾𪾿𪿀𪿁𪿂𪿃𪿄𪿅𪿆𪿇𪿈𪿉𪿊𪿋𪿌𪿍𪿎𪿏𪿐𪿑𪿒𪿓𪿔𪿕𪿖𪿗𪿘𪿙𪿚𪿛𪿜𪿝𪿞𪿟𪿠𪿡𪿢𪿣𪿤𪿥𪿦𪿧𪿨𪿩𪿪𪿫𪿬𪿭𪿮𪿯𪿰𪿱𪿲𪿳𪿴𪿵𪿶𪿷𪿸𪿹𪿺𪿻𪿼𪿽𪿾𪿿𫀀𫀁𫀂𫀃𫀄𫀅𫀆𫀇𫀈𫀉𫀊𫀋𫀌𫀍𫀎𫀏𫀐𫀑𫀒𫀓𫀔𫀕𫀖𫀗𫀘𫀙𫀚𫀛𫀜𫀝𫀞𫀟𫀠𫀡𫀢𫀣𫀤𫀥𫀦𫀧𫀨𫀩𫀪𫀫𫀬𫀭𫀮𫀯𫀰𫀱𫀲𫀳𫀴𫀵𫀶𫀷𫀸𫀹𫀺𫀻𫀼𫀽𫀾𫀿𫁀𫁁𫁂𫁃𫁄𫁅𫁆𫁇𫁈𫁉𫁊𫁋𫁌𫁍𫁎𫁏𫁐𫁑𫁒𫁓𫁔𫁕𫁖𫁗𫁘𫁙𫁚𫁛𫁜𫁝𫁞𫁟𫁠𫁡𫁢𫁣𫁤𫁥𫁦𫁧𫁨𫁩𫁪𫁫𫁬𫁭𫁮𫁯𫁰𫁱𫁲𫁳𫁴𫁵𫁶𫁷𫁸𫁹𫁺𫁻𫁼𫁽𫁾𫁿𫂀𫂁𫂂𫂃𫂄𫂅𫂆𫂇𫂈𫂉𫂊𫂋𫂌𫂍𫂎𫂏𫂐𫂑𫂒𫂓𫂔𫂕𫂖𫂗𫂘𫂙𫂚𫂛𫂜𫂝𫂞𫂟𫂠𫂡𫂢𫂣𫂤𫂥𫂦𫂧𫂨𫂩𫂪𫂫𫂬𫂭𫂮𫂯𫂰𫂱𫂲𫂳𫂴𫂵𫂶𫂷𫂸𫂹𫂺𫂻𫂼𫂽𫂾𫂿𫃀𫃁𫃂𫃃𫃄𫃅𫃆𫃇𫃈𫃉𫃊𫃋𫃌𫃍𫃎𫃏𫃐𫃑𫃒𫃓𫃔𫃕𫃖𫃗𫃘𫃙𫃚𫃛𫃜𫃝𫃞𫃟𫃠𫃡𫃢𫃣𫃤𫃥𫃦𫃧𫃨𫃩𫃪𫃫𫃬𫃭𫃮𫃯𫃰𫃱𫃲𫃳𫃴𫃵𫃶𫃷𫃸𫃹𫃺𫃻𫃼𫃽𫃾𫃿𫄀𫄁𫄂𫄃𫄄𫄅𫄆𫄇𫄈𫄉𫄊𫄋𫄌𫄍𫄎𫄏𫄐𫄑𫄒𫄓𫄔𫄕𫄖𫄗𫄘𫄙𫄚𫄛𫄜𫄝𫄞𫄟𫄠𫄡𫄢𫄣𫄤𫄥𫄦𫄧𫄨𫄩𫄪𫄫𫄬𫄭𫄮𫄯𫄰𫄱𫄲𫄳𫄴𫄵𫄶𫄷𫄸𫄹𫄺𫄻𫄼𫄽𫄾𫄿𫅀𫅁𫅂𫅃𫅄𫅅𫅆𫅇𫅈𫅉𫅊𫅋𫅌𫅍𫅎𫅏𫅐𫅑𫅒𫅓𫅔𫅕𫅖𫅗𫅘𫅙𫅚𫅛𫅜𫅝𫅞𫅟𫅠𫅡𫅢𫅣𫅤𫅥𫅦𫅧𫅨𫅩𫅪𫅫𫅬𫅭𫅮𫅯𫅰𫅱𫅲𫅳𫅴𫅵𫅶𫅷𫅸𫅹𫅺𫅻𫅼𫅽𫅾𫅿𫆀𫆁𫆂𫆃𫆄𫆅𫆆𫆇𫆈𫆉𫆊𫆋𫆌𫆍𫆎𫆏𫆐𫆑𫆒𫆓𫆔𫆕𫆖𫆗𫆘𫆙𫆚𫆛𫆜𫆝𫆞𫆟𫆠𫆡𫆢𫆣𫆤𫆥𫆦𫆧𫆨𫆩𫆪𫆫𫆬𫆭𫆮𫆯𫆰𫆱𫆲𫆳𫆴𫆵𫆶𫆷𫆸𫆹𫆺𫆻𫆼𫆽𫆾𫆿𫇀𫇁𫇂𫇃𫇄𫇅𫇆𫇇𫇈𫇉𫇊𫇋𫇌𫇍𫇎𫇏𫇐𫇑𫇒𫇓𫇔𫇕𫇖𫇗𫇘𫇙𫇚𫇛𫇜𫇝𫇞𫇟𫇠𫇡𫇢𫇣𫇤𫇥𫇦𫇧𫇨𫇩𫇪𫇫𫇬𫇭𫇮𫇯𫇰𫇱𫇲𫇳𫇴𫇵𫇶𫇷𫇸𫇹𫇺𫇻𫇼𫇽𫇾𫇿𫈀𫈁𫈂𫈃𫈄𫈅𫈆𫈇𫈈𫈉𫈊𫈋𫈌𫈍𫈎𫈏𫈐𫈑𫈒𫈓𫈔𫈕𫈖𫈗𫈘𫈙𫈚𫈛𫈜𫈝𫈞𫈟𫈠𫈡𫈢𫈣𫈤𫈥𫈦𫈧𫈨𫈩𫈪𫈫𫈬𫈭𫈮𫈯𫈰𫈱𫈲𫈳𫈴𫈵𫈶𫈷𫈸𫈹𫈺𫈻𫈼𫈽𫈾𫈿𫉀𫉁𫉂𫉃𫉄𫉅𫉆𫉇𫉈𫉉𫉊𫉋𫉌𫉍𫉎𫉏𫉐𫉑𫉒𫉓𫉔𫉕𫉖𫉗𫉘𫉙𫉚𫉛𫉜𫉝𫉞𫉟𫉠𫉡𫉢𫉣𫉤𫉥𫉦𫉧𫉨𫉩𫉪𫉫𫉬𫉭𫉮𫉯𫉰𫉱𫉲𫉳𫉴𫉵𫉶𫉷𫉸𫉹𫉺𫉻𫉼𫉽𫉾𫉿𫊀𫊁𫊂𫊃𫊄𫊅𫊆𫊇𫊈𫊉𫊊𫊋𫊌𫊍𫊎𫊏𫊐𫊑𫊒𫊓𫊔𫊕𫊖𫊗𫊘𫊙𫊚𫊛𫊜𫊝𫊞𫊟𫊠𫊡𫊢𫊣𫊤𫊥𫊦𫊧𫊨𫊩𫊪𫊫𫊬𫊭𫊮𫊯𫊰𫊱𫊲𫊳𫊴𫊵𫊶𫊷𫊸𫊹𫊺𫊻𫊼𫊽𫊾𫊿𫋀𫋁𫋂𫋃𫋄𫋅𫋆𫋇𫋈𫋉𫋊𫋋𫋌𫋍𫋎𫋏𫋐𫋑𫋒𫋓𫋔𫋕𫋖𫋗𫋘𫋙𫋚𫋛𫋜𫋝𫋞𫋟𫋠𫋡𫋢𫋣𫋤𫋥𫋦𫋧𫋨𫋩𫋪𫋫𫋬𫋭𫋮𫋯𫋰𫋱𫋲𫋳𫋴𫋵𫋶𫋷𫋸𫋹𫋺𫋻𫋼𫋽𫋾𫋿𫌀𫌁𫌂𫌃𫌄𫌅𫌆𫌇𫌈𫌉𫌊𫌋𫌌𫌍𫌎𫌏𫌐𫌑𫌒𫌓𫌔𫌕𫌖𫌗𫌘𫌙𫌚𫌛𫌜𫌝𫌞𫌟𫌠𫌡𫌢𫌣𫌤𫌥𫌦𫌧𫌨𫌩𫌪𫌫𫌬𫌭𫌮𫌯𫌰𫌱𫌲𫌳𫌴𫌵𫌶𫌷𫌸𫌹𫌺𫌻𫌼𫌽𫌾𫌿𫍀𫍁𫍂𫍃𫍄𫍅𫍆𫍇𫍈𫍉𫍊𫍋𫍌𫍍𫍎𫍏𫍐𫍑𫍒𫍓𫍔𫍕𫍖𫍗𫍘𫍙𫍚𫍛𫍜𫍝𫍞𫍟𫍠𫍡𫍢𫍣𫍤𫍥𫍦𫍧𫍨𫍩𫍪𫍫𫍬𫍭𫍮𫍯𫍰𫍱𫍲𫍳𫍴𫍵𫍶𫍷𫍸𫍹𫍺𫍻𫍼𫍽𫍾𫍿𫎀𫎁𫎂𫎃𫎄𫎅𫎆𫎇𫎈𫎉𫎊𫎋𫎌𫎍𫎎𫎏𫎐𫎑𫎒𫎓𫎔𫎕𫎖𫎗𫎘𫎙𫎚𫎛𫎜𫎝𫎞𫎟𫎠𫎡𫎢𫎣𫎤𫎥𫎦𫎧𫎨𫎩𫎪𫎫𫎬𫎭𫎮𫎯𫎰𫎱𫎲𫎳𫎴𫎵𫎶𫎷𫎸𫎹𫎺𫎻𫎼𫎽𫎾𫎿𫏀𫏁𫏂𫏃𫏄𫏅𫏆𫏇𫏈𫏉𫏊𫏋𫏌𫏍𫏎𫏏𫏐𫏑𫏒𫏓𫏔𫏕𫏖𫏗𫏘𫏙𫏚𫏛𫏜𫏝𫏞𫏟𫏠𫏡𫏢𫏣𫏤𫏥𫏦𫏧𫏨𫏩𫏪𫏫𫏬𫏭𫏮𫏯𫏰𫏱𫏲𫏳𫏴𫏵𫏶𫏷𫏸𫏹𫏺𫏻𫏼𫏽𫏾𫏿𫐀𫐁𫐂𫐃𫐄𫐅𫐆𫐇𫐈𫐉𫐊𫐋𫐌𫐍𫐎𫐏𫐐𫐑𫐒𫐓𫐔𫐕𫐖𫐗𫐘𫐙𫐚𫐛𫐜𫐝𫐞𫐟𫐠𫐡𫐢𫐣𫐤𫐥𫐦𫐧𫐨𫐩𫐪𫐫𫐬𫐭𫐮𫐯𫐰𫐱𫐲𫐳𫐴𫐵𫐶𫐷𫐸𫐹𫐺𫐻𫐼𫐽𫐾𫐿𫑀𫑁𫑂𫑃𫑄𫑅𫑆𫑇𫑈𫑉𫑊𫑋𫑌𫑍𫑎𫑏𫑐𫑑𫑒𫑓𫑔𫑕𫑖𫑗𫑘𫑙𫑚𫑛𫑜𫑝𫑞𫑟𫑠𫑡𫑢𫑣𫑤𫑥𫑦𫑧𫑨𫑩𫑪𫑫𫑬𫑭𫑮𫑯𫑰𫑱𫑲𫑳𫑴𫑵𫑶𫑷𫑸𫑹𫑺𫑻𫑼𫑽𫑾𫑿𫒀𫒁𫒂𫒃𫒄𫒅𫒆𫒇𫒈𫒉𫒊𫒋𫒌𫒍𫒎𫒏𫒐𫒑𫒒𫒓𫒔𫒕𫒖𫒗𫒘𫒙𫒚𫒛𫒜𫒝𫒞𫒟𫒠𫒡𫒢𫒣𫒤𫒥𫒦𫒧𫒨𫒩𫒪𫒫𫒬𫒭𫒮𫒯𫒰𫒱𫒲𫒳𫒴𫒵𫒶𫒷𫒸𫒹𫒺𫒻𫒼𫒽𫒾𫒿𫓀𫓁𫓂𫓃𫓄𫓅𫓆𫓇𫓈𫓉𫓊𫓋𫓌𫓍𫓎𫓏𫓐𫓑𫓒𫓓𫓔𫓕𫓖𫓗𫓘𫓙𫓚𫓛𫓜𫓝𫓞𫓟𫓠𫓡𫓢𫓣𫓤𫓥𫓦𫓧𫓨𫓩𫓪𫓫𫓬𫓭𫓮𫓯𫓰𫓱𫓲𫓳𫓴𫓵𫓶𫓷𫓸𫓹𫓺𫓻𫓼𫓽𫓾𫓿𫔀𫔁𫔂𫔃𫔄𫔅𫔆𫔇𫔈𫔉𫔊𫔋𫔌𫔍𫔎𫔏𫔐𫔑𫔒𫔓𫔔𫔕𫔖𫔗𫔘𫔙𫔚𫔛𫔜𫔝𫔞𫔟𫔠𫔡𫔢𫔣𫔤𫔥𫔦𫔧𫔨𫔩𫔪𫔫𫔬𫔭𫔮𫔯𫔰𫔱𫔲𫔳𫔴𫔵𫔶𫔷𫔸𫔹𫔺𫔻𫔼𫔽𫔾𫔿𫕀𫕁𫕂𫕃𫕄𫕅𫕆𫕇𫕈𫕉𫕊𫕋𫕌𫕍𫕎𫕏𫕐𫕑𫕒𫕓𫕔𫕕𫕖𫕗𫕘𫕙𫕚𫕛𫕜𫕝𫕞𫕟𫕠𫕡𫕢𫕣𫕤𫕥𫕦𫕧𫕨𫕩𫕪𫕫𫕬𫕭𫕮𫕯𫕰𫕱𫕲𫕳𫕴𫕵𫕶𫕷𫕸𫕹𫕺𫕻𫕼𫕽𫕾𫕿𫖀𫖁𫖂𫖃𫖄𫖅𫖆𫖇𫖈𫖉𫖊𫖋𫖌𫖍𫖎𫖏𫖐𫖑𫖒𫖓𫖔𫖕𫖖𫖗𫖘𫖙𫖚𫖛𫖜𫖝𫖞𫖟𫖠𫖡𫖢𫖣𫖤𫖥𫖦𫖧𫖨𫖩𫖪𫖫𫖬𫖭𫖮𫖯𫖰𫖱𫖲𫖳𫖴𫖵𫖶𫖷𫖸𫖹𫖺𫖻𫖼𫖽𫖾𫖿𫗀𫗁𫗂𫗃𫗄𫗅𫗆𫗇𫗈𫗉𫗊𫗋𫗌𫗍𫗎𫗏𫗐𫗑𫗒𫗓𫗔𫗕𫗖𫗗𫗘𫗙𫗚𫗛𫗜𫗝𫗞𫗟𫗠𫗡𫗢𫗣𫗤𫗥𫗦𫗧𫗨𫗩𫗪𫗫𫗬𫗭𫗮𫗯𫗰𫗱𫗲𫗳𫗴𫗵𫗶𫗷𫗸𫗹𫗺𫗻𫗼𫗽𫗾𫗿𫘀𫘁𫘂𫘃𫘄𫘅𫘆𫘇𫘈𫘉𫘊𫘋𫘌𫘍𫘎𫘏𫘐𫘑𫘒𫘓𫘔𫘕𫘖𫘗𫘘𫘙𫘚𫘛𫘜𫘝𫘞𫘟𫘠𫘡𫘢𫘣𫘤𫘥𫘦𫘧𫘨𫘩𫘪𫘫𫘬𫘭𫘮𫘯𫘰𫘱𫘲𫘳𫘴𫘵𫘶𫘷𫘸𫘹𫘺𫘻𫘼𫘽𫘾𫘿𫙀𫙁𫙂𫙃𫙄𫙅𫙆𫙇𫙈𫙉𫙊𫙋𫙌𫙍𫙎𫙏𫙐𫙑𫙒𫙓𫙔𫙕𫙖𫙗𫙘𫙙𫙚𫙛𫙜𫙝𫙞𫙟𫙠𫙡𫙢𫙣𫙤𫙥𫙦𫙧𫙨𫙩𫙪𫙫𫙬𫙭𫙮𫙯𫙰𫙱𫙲𫙳𫙴𫙵𫙶𫙷𫙸𫙹𫙺𫙻𫙼𫙽𫙾𫙿𫚀𫚁𫚂𫚃𫚄𫚅𫚆𫚇𫚈𫚉𫚊𫚋𫚌𫚍𫚎𫚏𫚐𫚑𫚒𫚓𫚔𫚕𫚖𫚗𫚘𫚙𫚚𫚛𫚜𫚝𫚞𫚟𫚠𫚡𫚢𫚣𫚤𫚥𫚦𫚧𫚨𫚩𫚪𫚫𫚬𫚭𫚮𫚯𫚰𫚱𫚲𫚳𫚴𫚵𫚶𫚷𫚸𫚹𫚺𫚻𫚼𫚽𫚾𫚿𫛀𫛁𫛂𫛃𫛄𫛅𫛆𫛇𫛈𫛉𫛊𫛋𫛌𫛍𫛎𫛏𫛐𫛑𫛒𫛓𫛔𫛕𫛖𫛗𫛘𫛙𫛚𫛛𫛜𫛝𫛞𫛟𫛠𫛡𫛢𫛣𫛤𫛥𫛦𫛧𫛨𫛩𫛪𫛫𫛬𫛭𫛮𫛯𫛰𫛱𫛲𫛳𫛴𫛵𫛶𫛷𫛸𫛹𫛺𫛻𫛼𫛽𫛾𫛿𫜀𫜁𫜂𫜃𫜄𫜅𫜆𫜇𫜈𫜉𫜊𫜋𫜌𫜍𫜎𫜏𫜐𫜑𫜒𫜓𫜔𫜕𫜖𫜗𫜘𫜙𫜚𫜛𫜜𫜝𫜞𫜟𫜠𫜡𫜢𫜣𫜤𫜥𫜦𫜧𫜨𫜩𫜪𫜫𫜬𫜭𫜮𫜯𫜰𫜱𫜲𫜳𫜴; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-escaped.js index b6af17141b79..fbf923cfa1a8 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-5.2.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-5.2.0.js b/js/src/tests/test262/language/identifiers/start-unicode-5.2.0.js index dd71e70373bd..a248d9f04ee5 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-5.2.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-5.2.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-class-escaped.js new file mode 100644 index 000000000000..d6107ac4f412 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v6.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u0526\u0527\u0620\u0840\u0841\u0842\u0843\u0844\u0845\u0846\u0847\u0848\u0849\u084A\u084B\u084C\u084D\u084E\u084F\u0850\u0851\u0852\u0853\u0854\u0855\u0856\u0857\u0858\u0973\u0974\u0975\u0976\u0977\u0CF1\u0CF2\u0D29\u0D3A\u0D4E\u0F8C\u1BC0\u1BC1\u1BC2\u1BC3\u1BC4\u1BC5\u1BC6\u1BC7\u1BC8\u1BC9\u1BCA\u1BCB\u1BCC\u1BCD\u1BCE\u1BCF\u1BD0\u1BD1\u1BD2\u1BD3\u1BD4\u1BD5\u1BD6\u1BD7\u1BD8\u1BD9\u1BDA\u1BDB\u1BDC\u1BDD\u1BDE\u1BDF\u1BE0\u1BE1\u1BE2\u1BE3\u1BE4\u1BE5\u2095\u2096\u2097\u2098\u2099\u209A\u209B\u209C\u31B8\u31B9\u31BA\uA660\uA661\uA78D\uA78E\uA790\uA791\uA7A0\uA7A1\uA7A2\uA7A3\uA7A4\uA7A5\uA7A6\uA7A7\uA7A8\uA7A9\uA7FA\uAB01\uAB02\uAB03\uAB04\uAB05\uAB06\uAB09\uAB0A\uAB0B\uAB0C\uAB0D\uAB0E\uAB11\uAB12\uAB13\uAB14\uAB15\uAB16\uAB20\uAB21\uAB22\uAB23\uAB24\uAB25\uAB26\uAB28\uAB29\uAB2A\uAB2B\uAB2C\uAB2D\uAB2E\u{11003}\u{11004}\u{11005}\u{11006}\u{11007}\u{11008}\u{11009}\u{1100A}\u{1100B}\u{1100C}\u{1100D}\u{1100E}\u{1100F}\u{11010}\u{11011}\u{11012}\u{11013}\u{11014}\u{11015}\u{11016}\u{11017}\u{11018}\u{11019}\u{1101A}\u{1101B}\u{1101C}\u{1101D}\u{1101E}\u{1101F}\u{11020}\u{11021}\u{11022}\u{11023}\u{11024}\u{11025}\u{11026}\u{11027}\u{11028}\u{11029}\u{1102A}\u{1102B}\u{1102C}\u{1102D}\u{1102E}\u{1102F}\u{11030}\u{11031}\u{11032}\u{11033}\u{11034}\u{11035}\u{11036}\u{11037}\u{16800}\u{16801}\u{16802}\u{16803}\u{16804}\u{16805}\u{16806}\u{16807}\u{16808}\u{16809}\u{1680A}\u{1680B}\u{1680C}\u{1680D}\u{1680E}\u{1680F}\u{16810}\u{16811}\u{16812}\u{16813}\u{16814}\u{16815}\u{16816}\u{16817}\u{16818}\u{16819}\u{1681A}\u{1681B}\u{1681C}\u{1681D}\u{1681E}\u{1681F}\u{16820}\u{16821}\u{16822}\u{16823}\u{16824}\u{16825}\u{16826}\u{16827}\u{16828}\u{16829}\u{1682A}\u{1682B}\u{1682C}\u{1682D}\u{1682E}\u{1682F}\u{16830}\u{16831}\u{16832}\u{16833}\u{16834}\u{16835}\u{16836}\u{16837}\u{16838}\u{16839}\u{1683A}\u{1683B}\u{1683C}\u{1683D}\u{1683E}\u{1683F}\u{16840}\u{16841}\u{16842}\u{16843}\u{16844}\u{16845}\u{16846}\u{16847}\u{16848}\u{16849}\u{1684A}\u{1684B}\u{1684C}\u{1684D}\u{1684E}\u{1684F}\u{16850}\u{16851}\u{16852}\u{16853}\u{16854}\u{16855}\u{16856}\u{16857}\u{16858}\u{16859}\u{1685A}\u{1685B}\u{1685C}\u{1685D}\u{1685E}\u{1685F}\u{16860}\u{16861}\u{16862}\u{16863}\u{16864}\u{16865}\u{16866}\u{16867}\u{16868}\u{16869}\u{1686A}\u{1686B}\u{1686C}\u{1686D}\u{1686E}\u{1686F}\u{16870}\u{16871}\u{16872}\u{16873}\u{16874}\u{16875}\u{16876}\u{16877}\u{16878}\u{16879}\u{1687A}\u{1687B}\u{1687C}\u{1687D}\u{1687E}\u{1687F}\u{16880}\u{16881}\u{16882}\u{16883}\u{16884}\u{16885}\u{16886}\u{16887}\u{16888}\u{16889}\u{1688A}\u{1688B}\u{1688C}\u{1688D}\u{1688E}\u{1688F}\u{16890}\u{16891}\u{16892}\u{16893}\u{16894}\u{16895}\u{16896}\u{16897}\u{16898}\u{16899}\u{1689A}\u{1689B}\u{1689C}\u{1689D}\u{1689E}\u{1689F}\u{168A0}\u{168A1}\u{168A2}\u{168A3}\u{168A4}\u{168A5}\u{168A6}\u{168A7}\u{168A8}\u{168A9}\u{168AA}\u{168AB}\u{168AC}\u{168AD}\u{168AE}\u{168AF}\u{168B0}\u{168B1}\u{168B2}\u{168B3}\u{168B4}\u{168B5}\u{168B6}\u{168B7}\u{168B8}\u{168B9}\u{168BA}\u{168BB}\u{168BC}\u{168BD}\u{168BE}\u{168BF}\u{168C0}\u{168C1}\u{168C2}\u{168C3}\u{168C4}\u{168C5}\u{168C6}\u{168C7}\u{168C8}\u{168C9}\u{168CA}\u{168CB}\u{168CC}\u{168CD}\u{168CE}\u{168CF}\u{168D0}\u{168D1}\u{168D2}\u{168D3}\u{168D4}\u{168D5}\u{168D6}\u{168D7}\u{168D8}\u{168D9}\u{168DA}\u{168DB}\u{168DC}\u{168DD}\u{168DE}\u{168DF}\u{168E0}\u{168E1}\u{168E2}\u{168E3}\u{168E4}\u{168E5}\u{168E6}\u{168E7}\u{168E8}\u{168E9}\u{168EA}\u{168EB}\u{168EC}\u{168ED}\u{168EE}\u{168EF}\u{168F0}\u{168F1}\u{168F2}\u{168F3}\u{168F4}\u{168F5}\u{168F6}\u{168F7}\u{168F8}\u{168F9}\u{168FA}\u{168FB}\u{168FC}\u{168FD}\u{168FE}\u{168FF}\u{16900}\u{16901}\u{16902}\u{16903}\u{16904}\u{16905}\u{16906}\u{16907}\u{16908}\u{16909}\u{1690A}\u{1690B}\u{1690C}\u{1690D}\u{1690E}\u{1690F}\u{16910}\u{16911}\u{16912}\u{16913}\u{16914}\u{16915}\u{16916}\u{16917}\u{16918}\u{16919}\u{1691A}\u{1691B}\u{1691C}\u{1691D}\u{1691E}\u{1691F}\u{16920}\u{16921}\u{16922}\u{16923}\u{16924}\u{16925}\u{16926}\u{16927}\u{16928}\u{16929}\u{1692A}\u{1692B}\u{1692C}\u{1692D}\u{1692E}\u{1692F}\u{16930}\u{16931}\u{16932}\u{16933}\u{16934}\u{16935}\u{16936}\u{16937}\u{16938}\u{16939}\u{1693A}\u{1693B}\u{1693C}\u{1693D}\u{1693E}\u{1693F}\u{16940}\u{16941}\u{16942}\u{16943}\u{16944}\u{16945}\u{16946}\u{16947}\u{16948}\u{16949}\u{1694A}\u{1694B}\u{1694C}\u{1694D}\u{1694E}\u{1694F}\u{16950}\u{16951}\u{16952}\u{16953}\u{16954}\u{16955}\u{16956}\u{16957}\u{16958}\u{16959}\u{1695A}\u{1695B}\u{1695C}\u{1695D}\u{1695E}\u{1695F}\u{16960}\u{16961}\u{16962}\u{16963}\u{16964}\u{16965}\u{16966}\u{16967}\u{16968}\u{16969}\u{1696A}\u{1696B}\u{1696C}\u{1696D}\u{1696E}\u{1696F}\u{16970}\u{16971}\u{16972}\u{16973}\u{16974}\u{16975}\u{16976}\u{16977}\u{16978}\u{16979}\u{1697A}\u{1697B}\u{1697C}\u{1697D}\u{1697E}\u{1697F}\u{16980}\u{16981}\u{16982}\u{16983}\u{16984}\u{16985}\u{16986}\u{16987}\u{16988}\u{16989}\u{1698A}\u{1698B}\u{1698C}\u{1698D}\u{1698E}\u{1698F}\u{16990}\u{16991}\u{16992}\u{16993}\u{16994}\u{16995}\u{16996}\u{16997}\u{16998}\u{16999}\u{1699A}\u{1699B}\u{1699C}\u{1699D}\u{1699E}\u{1699F}\u{169A0}\u{169A1}\u{169A2}\u{169A3}\u{169A4}\u{169A5}\u{169A6}\u{169A7}\u{169A8}\u{169A9}\u{169AA}\u{169AB}\u{169AC}\u{169AD}\u{169AE}\u{169AF}\u{169B0}\u{169B1}\u{169B2}\u{169B3}\u{169B4}\u{169B5}\u{169B6}\u{169B7}\u{169B8}\u{169B9}\u{169BA}\u{169BB}\u{169BC}\u{169BD}\u{169BE}\u{169BF}\u{169C0}\u{169C1}\u{169C2}\u{169C3}\u{169C4}\u{169C5}\u{169C6}\u{169C7}\u{169C8}\u{169C9}\u{169CA}\u{169CB}\u{169CC}\u{169CD}\u{169CE}\u{169CF}\u{169D0}\u{169D1}\u{169D2}\u{169D3}\u{169D4}\u{169D5}\u{169D6}\u{169D7}\u{169D8}\u{169D9}\u{169DA}\u{169DB}\u{169DC}\u{169DD}\u{169DE}\u{169DF}\u{169E0}\u{169E1}\u{169E2}\u{169E3}\u{169E4}\u{169E5}\u{169E6}\u{169E7}\u{169E8}\u{169E9}\u{169EA}\u{169EB}\u{169EC}\u{169ED}\u{169EE}\u{169EF}\u{169F0}\u{169F1}\u{169F2}\u{169F3}\u{169F4}\u{169F5}\u{169F6}\u{169F7}\u{169F8}\u{169F9}\u{169FA}\u{169FB}\u{169FC}\u{169FD}\u{169FE}\u{169FF}\u{16A00}\u{16A01}\u{16A02}\u{16A03}\u{16A04}\u{16A05}\u{16A06}\u{16A07}\u{16A08}\u{16A09}\u{16A0A}\u{16A0B}\u{16A0C}\u{16A0D}\u{16A0E}\u{16A0F}\u{16A10}\u{16A11}\u{16A12}\u{16A13}\u{16A14}\u{16A15}\u{16A16}\u{16A17}\u{16A18}\u{16A19}\u{16A1A}\u{16A1B}\u{16A1C}\u{16A1D}\u{16A1E}\u{16A1F}\u{16A20}\u{16A21}\u{16A22}\u{16A23}\u{16A24}\u{16A25}\u{16A26}\u{16A27}\u{16A28}\u{16A29}\u{16A2A}\u{16A2B}\u{16A2C}\u{16A2D}\u{16A2E}\u{16A2F}\u{16A30}\u{16A31}\u{16A32}\u{16A33}\u{16A34}\u{16A35}\u{16A36}\u{16A37}\u{16A38}\u{1B000}\u{1B001}\u{2B740}\u{2B741}\u{2B742}\u{2B743}\u{2B744}\u{2B745}\u{2B746}\u{2B747}\u{2B748}\u{2B749}\u{2B74A}\u{2B74B}\u{2B74C}\u{2B74D}\u{2B74E}\u{2B74F}\u{2B750}\u{2B751}\u{2B752}\u{2B753}\u{2B754}\u{2B755}\u{2B756}\u{2B757}\u{2B758}\u{2B759}\u{2B75A}\u{2B75B}\u{2B75C}\u{2B75D}\u{2B75E}\u{2B75F}\u{2B760}\u{2B761}\u{2B762}\u{2B763}\u{2B764}\u{2B765}\u{2B766}\u{2B767}\u{2B768}\u{2B769}\u{2B76A}\u{2B76B}\u{2B76C}\u{2B76D}\u{2B76E}\u{2B76F}\u{2B770}\u{2B771}\u{2B772}\u{2B773}\u{2B774}\u{2B775}\u{2B776}\u{2B777}\u{2B778}\u{2B779}\u{2B77A}\u{2B77B}\u{2B77C}\u{2B77D}\u{2B77E}\u{2B77F}\u{2B780}\u{2B781}\u{2B782}\u{2B783}\u{2B784}\u{2B785}\u{2B786}\u{2B787}\u{2B788}\u{2B789}\u{2B78A}\u{2B78B}\u{2B78C}\u{2B78D}\u{2B78E}\u{2B78F}\u{2B790}\u{2B791}\u{2B792}\u{2B793}\u{2B794}\u{2B795}\u{2B796}\u{2B797}\u{2B798}\u{2B799}\u{2B79A}\u{2B79B}\u{2B79C}\u{2B79D}\u{2B79E}\u{2B79F}\u{2B7A0}\u{2B7A1}\u{2B7A2}\u{2B7A3}\u{2B7A4}\u{2B7A5}\u{2B7A6}\u{2B7A7}\u{2B7A8}\u{2B7A9}\u{2B7AA}\u{2B7AB}\u{2B7AC}\u{2B7AD}\u{2B7AE}\u{2B7AF}\u{2B7B0}\u{2B7B1}\u{2B7B2}\u{2B7B3}\u{2B7B4}\u{2B7B5}\u{2B7B6}\u{2B7B7}\u{2B7B8}\u{2B7B9}\u{2B7BA}\u{2B7BB}\u{2B7BC}\u{2B7BD}\u{2B7BE}\u{2B7BF}\u{2B7C0}\u{2B7C1}\u{2B7C2}\u{2B7C3}\u{2B7C4}\u{2B7C5}\u{2B7C6}\u{2B7C7}\u{2B7C8}\u{2B7C9}\u{2B7CA}\u{2B7CB}\u{2B7CC}\u{2B7CD}\u{2B7CE}\u{2B7CF}\u{2B7D0}\u{2B7D1}\u{2B7D2}\u{2B7D3}\u{2B7D4}\u{2B7D5}\u{2B7D6}\u{2B7D7}\u{2B7D8}\u{2B7D9}\u{2B7DA}\u{2B7DB}\u{2B7DC}\u{2B7DD}\u{2B7DE}\u{2B7DF}\u{2B7E0}\u{2B7E1}\u{2B7E2}\u{2B7E3}\u{2B7E4}\u{2B7E5}\u{2B7E6}\u{2B7E7}\u{2B7E8}\u{2B7E9}\u{2B7EA}\u{2B7EB}\u{2B7EC}\u{2B7ED}\u{2B7EE}\u{2B7EF}\u{2B7F0}\u{2B7F1}\u{2B7F2}\u{2B7F3}\u{2B7F4}\u{2B7F5}\u{2B7F6}\u{2B7F7}\u{2B7F8}\u{2B7F9}\u{2B7FA}\u{2B7FB}\u{2B7FC}\u{2B7FD}\u{2B7FE}\u{2B7FF}\u{2B800}\u{2B801}\u{2B802}\u{2B803}\u{2B804}\u{2B805}\u{2B806}\u{2B807}\u{2B808}\u{2B809}\u{2B80A}\u{2B80B}\u{2B80C}\u{2B80D}\u{2B80E}\u{2B80F}\u{2B810}\u{2B811}\u{2B812}\u{2B813}\u{2B814}\u{2B815}\u{2B816}\u{2B817}\u{2B818}\u{2B819}\u{2B81A}\u{2B81B}\u{2B81C}\u{2B81D}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-class.js new file mode 100644 index 000000000000..924926aa46b9 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v6.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ԦԧؠࡀࡁࡂࡃࡄࡅࡆࡇࡈࡉࡊࡋࡌࡍࡎࡏࡐࡑࡒࡓࡔࡕࡖࡗࡘॳॴॵॶॷೱೲഩഺൎྌᯀᯁᯂᯃᯄᯅᯆᯇᯈᯉᯊᯋᯌᯍᯎᯏᯐᯑᯒᯓᯔᯕᯖᯗᯘᯙᯚᯛᯜᯝᯞᯟᯠᯡᯢᯣᯤᯥₕₖₗₘₙₚₛₜㆸㆹㆺꙠꙡꞍꞎꞐꞑꞠꞡꞢꞣꞤꞥꞦꞧꞨꞩꟺꬁꬂꬃꬄꬅꬆꬉꬊꬋꬌꬍꬎꬑꬒꬓꬔꬕꬖꬠꬡꬢꬣꬤꬥꬦꬨꬩꬪꬫꬬꬭꬮ𑀃𑀄𑀅𑀆𑀇𑀈𑀉𑀊𑀋𑀌𑀍𑀎𑀏𑀐𑀑𑀒𑀓𑀔𑀕𑀖𑀗𑀘𑀙𑀚𑀛𑀜𑀝𑀞𑀟𑀠𑀡𑀢𑀣𑀤𑀥𑀦𑀧𑀨𑀩𑀪𑀫𑀬𑀭𑀮𑀯𑀰𑀱𑀲𑀳𑀴𑀵𑀶𑀷𖠀𖠁𖠂𖠃𖠄𖠅𖠆𖠇𖠈𖠉𖠊𖠋𖠌𖠍𖠎𖠏𖠐𖠑𖠒𖠓𖠔𖠕𖠖𖠗𖠘𖠙𖠚𖠛𖠜𖠝𖠞𖠟𖠠𖠡𖠢𖠣𖠤𖠥𖠦𖠧𖠨𖠩𖠪𖠫𖠬𖠭𖠮𖠯𖠰𖠱𖠲𖠳𖠴𖠵𖠶𖠷𖠸𖠹𖠺𖠻𖠼𖠽𖠾𖠿𖡀𖡁𖡂𖡃𖡄𖡅𖡆𖡇𖡈𖡉𖡊𖡋𖡌𖡍𖡎𖡏𖡐𖡑𖡒𖡓𖡔𖡕𖡖𖡗𖡘𖡙𖡚𖡛𖡜𖡝𖡞𖡟𖡠𖡡𖡢𖡣𖡤𖡥𖡦𖡧𖡨𖡩𖡪𖡫𖡬𖡭𖡮𖡯𖡰𖡱𖡲𖡳𖡴𖡵𖡶𖡷𖡸𖡹𖡺𖡻𖡼𖡽𖡾𖡿𖢀𖢁𖢂𖢃𖢄𖢅𖢆𖢇𖢈𖢉𖢊𖢋𖢌𖢍𖢎𖢏𖢐𖢑𖢒𖢓𖢔𖢕𖢖𖢗𖢘𖢙𖢚𖢛𖢜𖢝𖢞𖢟𖢠𖢡𖢢𖢣𖢤𖢥𖢦𖢧𖢨𖢩𖢪𖢫𖢬𖢭𖢮𖢯𖢰𖢱𖢲𖢳𖢴𖢵𖢶𖢷𖢸𖢹𖢺𖢻𖢼𖢽𖢾𖢿𖣀𖣁𖣂𖣃𖣄𖣅𖣆𖣇𖣈𖣉𖣊𖣋𖣌𖣍𖣎𖣏𖣐𖣑𖣒𖣓𖣔𖣕𖣖𖣗𖣘𖣙𖣚𖣛𖣜𖣝𖣞𖣟𖣠𖣡𖣢𖣣𖣤𖣥𖣦𖣧𖣨𖣩𖣪𖣫𖣬𖣭𖣮𖣯𖣰𖣱𖣲𖣳𖣴𖣵𖣶𖣷𖣸𖣹𖣺𖣻𖣼𖣽𖣾𖣿𖤀𖤁𖤂𖤃𖤄𖤅𖤆𖤇𖤈𖤉𖤊𖤋𖤌𖤍𖤎𖤏𖤐𖤑𖤒𖤓𖤔𖤕𖤖𖤗𖤘𖤙𖤚𖤛𖤜𖤝𖤞𖤟𖤠𖤡𖤢𖤣𖤤𖤥𖤦𖤧𖤨𖤩𖤪𖤫𖤬𖤭𖤮𖤯𖤰𖤱𖤲𖤳𖤴𖤵𖤶𖤷𖤸𖤹𖤺𖤻𖤼𖤽𖤾𖤿𖥀𖥁𖥂𖥃𖥄𖥅𖥆𖥇𖥈𖥉𖥊𖥋𖥌𖥍𖥎𖥏𖥐𖥑𖥒𖥓𖥔𖥕𖥖𖥗𖥘𖥙𖥚𖥛𖥜𖥝𖥞𖥟𖥠𖥡𖥢𖥣𖥤𖥥𖥦𖥧𖥨𖥩𖥪𖥫𖥬𖥭𖥮𖥯𖥰𖥱𖥲𖥳𖥴𖥵𖥶𖥷𖥸𖥹𖥺𖥻𖥼𖥽𖥾𖥿𖦀𖦁𖦂𖦃𖦄𖦅𖦆𖦇𖦈𖦉𖦊𖦋𖦌𖦍𖦎𖦏𖦐𖦑𖦒𖦓𖦔𖦕𖦖𖦗𖦘𖦙𖦚𖦛𖦜𖦝𖦞𖦟𖦠𖦡𖦢𖦣𖦤𖦥𖦦𖦧𖦨𖦩𖦪𖦫𖦬𖦭𖦮𖦯𖦰𖦱𖦲𖦳𖦴𖦵𖦶𖦷𖦸𖦹𖦺𖦻𖦼𖦽𖦾𖦿𖧀𖧁𖧂𖧃𖧄𖧅𖧆𖧇𖧈𖧉𖧊𖧋𖧌𖧍𖧎𖧏𖧐𖧑𖧒𖧓𖧔𖧕𖧖𖧗𖧘𖧙𖧚𖧛𖧜𖧝𖧞𖧟𖧠𖧡𖧢𖧣𖧤𖧥𖧦𖧧𖧨𖧩𖧪𖧫𖧬𖧭𖧮𖧯𖧰𖧱𖧲𖧳𖧴𖧵𖧶𖧷𖧸𖧹𖧺𖧻𖧼𖧽𖧾𖧿𖨀𖨁𖨂𖨃𖨄𖨅𖨆𖨇𖨈𖨉𖨊𖨋𖨌𖨍𖨎𖨏𖨐𖨑𖨒𖨓𖨔𖨕𖨖𖨗𖨘𖨙𖨚𖨛𖨜𖨝𖨞𖨟𖨠𖨡𖨢𖨣𖨤𖨥𖨦𖨧𖨨𖨩𖨪𖨫𖨬𖨭𖨮𖨯𖨰𖨱𖨲𖨳𖨴𖨵𖨶𖨷𖨸𛀀𛀁𫝀𫝁𫝂𫝃𫝄𫝅𫝆𫝇𫝈𫝉𫝊𫝋𫝌𫝍𫝎𫝏𫝐𫝑𫝒𫝓𫝔𫝕𫝖𫝗𫝘𫝙𫝚𫝛𫝜𫝝𫝞𫝟𫝠𫝡𫝢𫝣𫝤𫝥𫝦𫝧𫝨𫝩𫝪𫝫𫝬𫝭𫝮𫝯𫝰𫝱𫝲𫝳𫝴𫝵𫝶𫝷𫝸𫝹𫝺𫝻𫝼𫝽𫝾𫝿𫞀𫞁𫞂𫞃𫞄𫞅𫞆𫞇𫞈𫞉𫞊𫞋𫞌𫞍𫞎𫞏𫞐𫞑𫞒𫞓𫞔𫞕𫞖𫞗𫞘𫞙𫞚𫞛𫞜𫞝𫞞𫞟𫞠𫞡𫞢𫞣𫞤𫞥𫞦𫞧𫞨𫞩𫞪𫞫𫞬𫞭𫞮𫞯𫞰𫞱𫞲𫞳𫞴𫞵𫞶𫞷𫞸𫞹𫞺𫞻𫞼𫞽𫞾𫞿𫟀𫟁𫟂𫟃𫟄𫟅𫟆𫟇𫟈𫟉𫟊𫟋𫟌𫟍𫟎𫟏𫟐𫟑𫟒𫟓𫟔𫟕𫟖𫟗𫟘𫟙𫟚𫟛𫟜𫟝𫟞𫟟𫟠𫟡𫟢𫟣𫟤𫟥𫟦𫟧𫟨𫟩𫟪𫟫𫟬𫟭𫟮𫟯𫟰𫟱𫟲𫟳𫟴𫟵𫟶𫟷𫟸𫟹𫟺𫟻𫟼𫟽𫟾𫟿𫠀𫠁𫠂𫠃𫠄𫠅𫠆𫠇𫠈𫠉𫠊𫠋𫠌𫠍𫠎𫠏𫠐𫠑𫠒𫠓𫠔𫠕𫠖𫠗𫠘𫠙𫠚𫠛𫠜𫠝; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-escaped.js index 7942573f3af0..b802edab9b06 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-6.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-6.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-6.0.0.js index 40d231198860..9d2975bd946c 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-6.0.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-6.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-class-escaped.js new file mode 100644 index 000000000000..04bea0d23876 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v6.1.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u08A0\u08A2\u08A3\u08A4\u08A5\u08A6\u08A7\u08A8\u08A9\u08AA\u08AB\u08AC\u0EDE\u0EDF\u10C7\u10CD\u10FD\u10FE\u10FF\u1BBA\u1BBB\u1BBC\u1BBD\u1BBE\u1BBF\u1CF5\u1CF6\u2CF2\u2CF3\u2D27\u2D2D\u2D66\u2D67\u9FCC\uA792\uA793\uA7AA\uA7F8\uA7F9\uAAE0\uAAE1\uAAE2\uAAE3\uAAE4\uAAE5\uAAE6\uAAE7\uAAE8\uAAE9\uAAEA\uAAF2\uAAF3\uAAF4\uFA2E\uFA2F\u{10980}\u{10981}\u{10982}\u{10983}\u{10984}\u{10985}\u{10986}\u{10987}\u{10988}\u{10989}\u{1098A}\u{1098B}\u{1098C}\u{1098D}\u{1098E}\u{1098F}\u{10990}\u{10991}\u{10992}\u{10993}\u{10994}\u{10995}\u{10996}\u{10997}\u{10998}\u{10999}\u{1099A}\u{1099B}\u{1099C}\u{1099D}\u{1099E}\u{1099F}\u{109A0}\u{109A1}\u{109A2}\u{109A3}\u{109A4}\u{109A5}\u{109A6}\u{109A7}\u{109A8}\u{109A9}\u{109AA}\u{109AB}\u{109AC}\u{109AD}\u{109AE}\u{109AF}\u{109B0}\u{109B1}\u{109B2}\u{109B3}\u{109B4}\u{109B5}\u{109B6}\u{109B7}\u{109BE}\u{109BF}\u{110D0}\u{110D1}\u{110D2}\u{110D3}\u{110D4}\u{110D5}\u{110D6}\u{110D7}\u{110D8}\u{110D9}\u{110DA}\u{110DB}\u{110DC}\u{110DD}\u{110DE}\u{110DF}\u{110E0}\u{110E1}\u{110E2}\u{110E3}\u{110E4}\u{110E5}\u{110E6}\u{110E7}\u{110E8}\u{11103}\u{11104}\u{11105}\u{11106}\u{11107}\u{11108}\u{11109}\u{1110A}\u{1110B}\u{1110C}\u{1110D}\u{1110E}\u{1110F}\u{11110}\u{11111}\u{11112}\u{11113}\u{11114}\u{11115}\u{11116}\u{11117}\u{11118}\u{11119}\u{1111A}\u{1111B}\u{1111C}\u{1111D}\u{1111E}\u{1111F}\u{11120}\u{11121}\u{11122}\u{11123}\u{11124}\u{11125}\u{11126}\u{11183}\u{11184}\u{11185}\u{11186}\u{11187}\u{11188}\u{11189}\u{1118A}\u{1118B}\u{1118C}\u{1118D}\u{1118E}\u{1118F}\u{11190}\u{11191}\u{11192}\u{11193}\u{11194}\u{11195}\u{11196}\u{11197}\u{11198}\u{11199}\u{1119A}\u{1119B}\u{1119C}\u{1119D}\u{1119E}\u{1119F}\u{111A0}\u{111A1}\u{111A2}\u{111A3}\u{111A4}\u{111A5}\u{111A6}\u{111A7}\u{111A8}\u{111A9}\u{111AA}\u{111AB}\u{111AC}\u{111AD}\u{111AE}\u{111AF}\u{111B0}\u{111B1}\u{111B2}\u{111C1}\u{111C2}\u{111C3}\u{111C4}\u{11680}\u{11681}\u{11682}\u{11683}\u{11684}\u{11685}\u{11686}\u{11687}\u{11688}\u{11689}\u{1168A}\u{1168B}\u{1168C}\u{1168D}\u{1168E}\u{1168F}\u{11690}\u{11691}\u{11692}\u{11693}\u{11694}\u{11695}\u{11696}\u{11697}\u{11698}\u{11699}\u{1169A}\u{1169B}\u{1169C}\u{1169D}\u{1169E}\u{1169F}\u{116A0}\u{116A1}\u{116A2}\u{116A3}\u{116A4}\u{116A5}\u{116A6}\u{116A7}\u{116A8}\u{116A9}\u{116AA}\u{16F00}\u{16F01}\u{16F02}\u{16F03}\u{16F04}\u{16F05}\u{16F06}\u{16F07}\u{16F08}\u{16F09}\u{16F0A}\u{16F0B}\u{16F0C}\u{16F0D}\u{16F0E}\u{16F0F}\u{16F10}\u{16F11}\u{16F12}\u{16F13}\u{16F14}\u{16F15}\u{16F16}\u{16F17}\u{16F18}\u{16F19}\u{16F1A}\u{16F1B}\u{16F1C}\u{16F1D}\u{16F1E}\u{16F1F}\u{16F20}\u{16F21}\u{16F22}\u{16F23}\u{16F24}\u{16F25}\u{16F26}\u{16F27}\u{16F28}\u{16F29}\u{16F2A}\u{16F2B}\u{16F2C}\u{16F2D}\u{16F2E}\u{16F2F}\u{16F30}\u{16F31}\u{16F32}\u{16F33}\u{16F34}\u{16F35}\u{16F36}\u{16F37}\u{16F38}\u{16F39}\u{16F3A}\u{16F3B}\u{16F3C}\u{16F3D}\u{16F3E}\u{16F3F}\u{16F40}\u{16F41}\u{16F42}\u{16F43}\u{16F44}\u{16F50}\u{16F93}\u{16F94}\u{16F95}\u{16F96}\u{16F97}\u{16F98}\u{16F99}\u{16F9A}\u{16F9B}\u{16F9C}\u{16F9D}\u{16F9E}\u{16F9F}\u{1EE00}\u{1EE01}\u{1EE02}\u{1EE03}\u{1EE05}\u{1EE06}\u{1EE07}\u{1EE08}\u{1EE09}\u{1EE0A}\u{1EE0B}\u{1EE0C}\u{1EE0D}\u{1EE0E}\u{1EE0F}\u{1EE10}\u{1EE11}\u{1EE12}\u{1EE13}\u{1EE14}\u{1EE15}\u{1EE16}\u{1EE17}\u{1EE18}\u{1EE19}\u{1EE1A}\u{1EE1B}\u{1EE1C}\u{1EE1D}\u{1EE1E}\u{1EE1F}\u{1EE21}\u{1EE22}\u{1EE24}\u{1EE27}\u{1EE29}\u{1EE2A}\u{1EE2B}\u{1EE2C}\u{1EE2D}\u{1EE2E}\u{1EE2F}\u{1EE30}\u{1EE31}\u{1EE32}\u{1EE34}\u{1EE35}\u{1EE36}\u{1EE37}\u{1EE39}\u{1EE3B}\u{1EE42}\u{1EE47}\u{1EE49}\u{1EE4B}\u{1EE4D}\u{1EE4E}\u{1EE4F}\u{1EE51}\u{1EE52}\u{1EE54}\u{1EE57}\u{1EE59}\u{1EE5B}\u{1EE5D}\u{1EE5F}\u{1EE61}\u{1EE62}\u{1EE64}\u{1EE67}\u{1EE68}\u{1EE69}\u{1EE6A}\u{1EE6C}\u{1EE6D}\u{1EE6E}\u{1EE6F}\u{1EE70}\u{1EE71}\u{1EE72}\u{1EE74}\u{1EE75}\u{1EE76}\u{1EE77}\u{1EE79}\u{1EE7A}\u{1EE7B}\u{1EE7C}\u{1EE7E}\u{1EE80}\u{1EE81}\u{1EE82}\u{1EE83}\u{1EE84}\u{1EE85}\u{1EE86}\u{1EE87}\u{1EE88}\u{1EE89}\u{1EE8B}\u{1EE8C}\u{1EE8D}\u{1EE8E}\u{1EE8F}\u{1EE90}\u{1EE91}\u{1EE92}\u{1EE93}\u{1EE94}\u{1EE95}\u{1EE96}\u{1EE97}\u{1EE98}\u{1EE99}\u{1EE9A}\u{1EE9B}\u{1EEA1}\u{1EEA2}\u{1EEA3}\u{1EEA5}\u{1EEA6}\u{1EEA7}\u{1EEA8}\u{1EEA9}\u{1EEAB}\u{1EEAC}\u{1EEAD}\u{1EEAE}\u{1EEAF}\u{1EEB0}\u{1EEB1}\u{1EEB2}\u{1EEB3}\u{1EEB4}\u{1EEB5}\u{1EEB6}\u{1EEB7}\u{1EEB8}\u{1EEB9}\u{1EEBA}\u{1EEBB}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-class.js new file mode 100644 index 000000000000..3cb9acb18ac1 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v6.1.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ࢠࢢࢣࢤࢥࢦࢧࢨࢩࢪࢫࢬໞໟჇჍჽჾჿᮺᮻᮼᮽᮾᮿᳵᳶⳲⳳⴧⴭⵦⵧ鿌ꞒꞓꞪꟸꟹꫠꫡꫢꫣꫤꫥꫦꫧꫨꫩꫪꫲꫳꫴ郞隷𐦀𐦁𐦂𐦃𐦄𐦅𐦆𐦇𐦈𐦉𐦊𐦋𐦌𐦍𐦎𐦏𐦐𐦑𐦒𐦓𐦔𐦕𐦖𐦗𐦘𐦙𐦚𐦛𐦜𐦝𐦞𐦟𐦠𐦡𐦢𐦣𐦤𐦥𐦦𐦧𐦨𐦩𐦪𐦫𐦬𐦭𐦮𐦯𐦰𐦱𐦲𐦳𐦴𐦵𐦶𐦷𐦾𐦿𑃐𑃑𑃒𑃓𑃔𑃕𑃖𑃗𑃘𑃙𑃚𑃛𑃜𑃝𑃞𑃟𑃠𑃡𑃢𑃣𑃤𑃥𑃦𑃧𑃨𑄃𑄄𑄅𑄆𑄇𑄈𑄉𑄊𑄋𑄌𑄍𑄎𑄏𑄐𑄑𑄒𑄓𑄔𑄕𑄖𑄗𑄘𑄙𑄚𑄛𑄜𑄝𑄞𑄟𑄠𑄡𑄢𑄣𑄤𑄥𑄦𑆃𑆄𑆅𑆆𑆇𑆈𑆉𑆊𑆋𑆌𑆍𑆎𑆏𑆐𑆑𑆒𑆓𑆔𑆕𑆖𑆗𑆘𑆙𑆚𑆛𑆜𑆝𑆞𑆟𑆠𑆡𑆢𑆣𑆤𑆥𑆦𑆧𑆨𑆩𑆪𑆫𑆬𑆭𑆮𑆯𑆰𑆱𑆲𑇁𑇂𑇃𑇄𑚀𑚁𑚂𑚃𑚄𑚅𑚆𑚇𑚈𑚉𑚊𑚋𑚌𑚍𑚎𑚏𑚐𑚑𑚒𑚓𑚔𑚕𑚖𑚗𑚘𑚙𑚚𑚛𑚜𑚝𑚞𑚟𑚠𑚡𑚢𑚣𑚤𑚥𑚦𑚧𑚨𑚩𑚪𖼀𖼁𖼂𖼃𖼄𖼅𖼆𖼇𖼈𖼉𖼊𖼋𖼌𖼍𖼎𖼏𖼐𖼑𖼒𖼓𖼔𖼕𖼖𖼗𖼘𖼙𖼚𖼛𖼜𖼝𖼞𖼟𖼠𖼡𖼢𖼣𖼤𖼥𖼦𖼧𖼨𖼩𖼪𖼫𖼬𖼭𖼮𖼯𖼰𖼱𖼲𖼳𖼴𖼵𖼶𖼷𖼸𖼹𖼺𖼻𖼼𖼽𖼾𖼿𖽀𖽁𖽂𖽃𖽄𖽐𖾓𖾔𖾕𖾖𖾗𖾘𖾙𖾚𖾛𖾜𖾝𖾞𖾟𞸀𞸁𞸂𞸃𞸅𞸆𞸇𞸈𞸉𞸊𞸋𞸌𞸍𞸎𞸏𞸐𞸑𞸒𞸓𞸔𞸕𞸖𞸗𞸘𞸙𞸚𞸛𞸜𞸝𞸞𞸟𞸡𞸢𞸤𞸧𞸩𞸪𞸫𞸬𞸭𞸮𞸯𞸰𞸱𞸲𞸴𞸵𞸶𞸷𞸹𞸻𞹂𞹇𞹉𞹋𞹍𞹎𞹏𞹑𞹒𞹔𞹗𞹙𞹛𞹝𞹟𞹡𞹢𞹤𞹧𞹨𞹩𞹪𞹬𞹭𞹮𞹯𞹰𞹱𞹲𞹴𞹵𞹶𞹷𞹹𞹺𞹻𞹼𞹾𞺀𞺁𞺂𞺃𞺄𞺅𞺆𞺇𞺈𞺉𞺋𞺌𞺍𞺎𞺏𞺐𞺑𞺒𞺓𞺔𞺕𞺖𞺗𞺘𞺙𞺚𞺛𞺡𞺢𞺣𞺥𞺦𞺧𞺨𞺩𞺫𞺬𞺭𞺮𞺯𞺰𞺱𞺲𞺳𞺴𞺵𞺶𞺷𞺸𞺹𞺺𞺻; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-escaped.js index 87310c15de81..b7d19ba4c61f 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-6.1.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-6.1.0.js b/js/src/tests/test262/language/identifiers/start-unicode-6.1.0.js index 7d30d6d7b87c..b5759ea94880 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-6.1.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-6.1.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-class-escaped.js new file mode 100644 index 000000000000..44ea9b92d6d9 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v7.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u037F\u0528\u0529\u052A\u052B\u052C\u052D\u052E\u052F\u08A1\u08AD\u08AE\u08AF\u08B0\u08B1\u08B2\u0978\u0980\u0C34\u16F1\u16F2\u16F3\u16F4\u16F5\u16F6\u16F7\u16F8\u191D\u191E\uA698\uA699\uA69A\uA69B\uA69C\uA69D\uA794\uA795\uA796\uA797\uA798\uA799\uA79A\uA79B\uA79C\uA79D\uA79E\uA79F\uA7AB\uA7AC\uA7AD\uA7B0\uA7B1\uA7F7\uA9E0\uA9E1\uA9E2\uA9E3\uA9E4\uA9E6\uA9E7\uA9E8\uA9E9\uA9EA\uA9EB\uA9EC\uA9ED\uA9EE\uA9EF\uA9FA\uA9FB\uA9FC\uA9FD\uA9FE\uAA7E\uAA7F\uAB30\uAB31\uAB32\uAB33\uAB34\uAB35\uAB36\uAB37\uAB38\uAB39\uAB3A\uAB3B\uAB3C\uAB3D\uAB3E\uAB3F\uAB40\uAB41\uAB42\uAB43\uAB44\uAB45\uAB46\uAB47\uAB48\uAB49\uAB4A\uAB4B\uAB4C\uAB4D\uAB4E\uAB4F\uAB50\uAB51\uAB52\uAB53\uAB54\uAB55\uAB56\uAB57\uAB58\uAB59\uAB5A\uAB5C\uAB5D\uAB5E\uAB5F\uAB64\uAB65\u{1031F}\u{10350}\u{10351}\u{10352}\u{10353}\u{10354}\u{10355}\u{10356}\u{10357}\u{10358}\u{10359}\u{1035A}\u{1035B}\u{1035C}\u{1035D}\u{1035E}\u{1035F}\u{10360}\u{10361}\u{10362}\u{10363}\u{10364}\u{10365}\u{10366}\u{10367}\u{10368}\u{10369}\u{1036A}\u{1036B}\u{1036C}\u{1036D}\u{1036E}\u{1036F}\u{10370}\u{10371}\u{10372}\u{10373}\u{10374}\u{10375}\u{10500}\u{10501}\u{10502}\u{10503}\u{10504}\u{10505}\u{10506}\u{10507}\u{10508}\u{10509}\u{1050A}\u{1050B}\u{1050C}\u{1050D}\u{1050E}\u{1050F}\u{10510}\u{10511}\u{10512}\u{10513}\u{10514}\u{10515}\u{10516}\u{10517}\u{10518}\u{10519}\u{1051A}\u{1051B}\u{1051C}\u{1051D}\u{1051E}\u{1051F}\u{10520}\u{10521}\u{10522}\u{10523}\u{10524}\u{10525}\u{10526}\u{10527}\u{10530}\u{10531}\u{10532}\u{10533}\u{10534}\u{10535}\u{10536}\u{10537}\u{10538}\u{10539}\u{1053A}\u{1053B}\u{1053C}\u{1053D}\u{1053E}\u{1053F}\u{10540}\u{10541}\u{10542}\u{10543}\u{10544}\u{10545}\u{10546}\u{10547}\u{10548}\u{10549}\u{1054A}\u{1054B}\u{1054C}\u{1054D}\u{1054E}\u{1054F}\u{10550}\u{10551}\u{10552}\u{10553}\u{10554}\u{10555}\u{10556}\u{10557}\u{10558}\u{10559}\u{1055A}\u{1055B}\u{1055C}\u{1055D}\u{1055E}\u{1055F}\u{10560}\u{10561}\u{10562}\u{10563}\u{10600}\u{10601}\u{10602}\u{10603}\u{10604}\u{10605}\u{10606}\u{10607}\u{10608}\u{10609}\u{1060A}\u{1060B}\u{1060C}\u{1060D}\u{1060E}\u{1060F}\u{10610}\u{10611}\u{10612}\u{10613}\u{10614}\u{10615}\u{10616}\u{10617}\u{10618}\u{10619}\u{1061A}\u{1061B}\u{1061C}\u{1061D}\u{1061E}\u{1061F}\u{10620}\u{10621}\u{10622}\u{10623}\u{10624}\u{10625}\u{10626}\u{10627}\u{10628}\u{10629}\u{1062A}\u{1062B}\u{1062C}\u{1062D}\u{1062E}\u{1062F}\u{10630}\u{10631}\u{10632}\u{10633}\u{10634}\u{10635}\u{10636}\u{10637}\u{10638}\u{10639}\u{1063A}\u{1063B}\u{1063C}\u{1063D}\u{1063E}\u{1063F}\u{10640}\u{10641}\u{10642}\u{10643}\u{10644}\u{10645}\u{10646}\u{10647}\u{10648}\u{10649}\u{1064A}\u{1064B}\u{1064C}\u{1064D}\u{1064E}\u{1064F}\u{10650}\u{10651}\u{10652}\u{10653}\u{10654}\u{10655}\u{10656}\u{10657}\u{10658}\u{10659}\u{1065A}\u{1065B}\u{1065C}\u{1065D}\u{1065E}\u{1065F}\u{10660}\u{10661}\u{10662}\u{10663}\u{10664}\u{10665}\u{10666}\u{10667}\u{10668}\u{10669}\u{1066A}\u{1066B}\u{1066C}\u{1066D}\u{1066E}\u{1066F}\u{10670}\u{10671}\u{10672}\u{10673}\u{10674}\u{10675}\u{10676}\u{10677}\u{10678}\u{10679}\u{1067A}\u{1067B}\u{1067C}\u{1067D}\u{1067E}\u{1067F}\u{10680}\u{10681}\u{10682}\u{10683}\u{10684}\u{10685}\u{10686}\u{10687}\u{10688}\u{10689}\u{1068A}\u{1068B}\u{1068C}\u{1068D}\u{1068E}\u{1068F}\u{10690}\u{10691}\u{10692}\u{10693}\u{10694}\u{10695}\u{10696}\u{10697}\u{10698}\u{10699}\u{1069A}\u{1069B}\u{1069C}\u{1069D}\u{1069E}\u{1069F}\u{106A0}\u{106A1}\u{106A2}\u{106A3}\u{106A4}\u{106A5}\u{106A6}\u{106A7}\u{106A8}\u{106A9}\u{106AA}\u{106AB}\u{106AC}\u{106AD}\u{106AE}\u{106AF}\u{106B0}\u{106B1}\u{106B2}\u{106B3}\u{106B4}\u{106B5}\u{106B6}\u{106B7}\u{106B8}\u{106B9}\u{106BA}\u{106BB}\u{106BC}\u{106BD}\u{106BE}\u{106BF}\u{106C0}\u{106C1}\u{106C2}\u{106C3}\u{106C4}\u{106C5}\u{106C6}\u{106C7}\u{106C8}\u{106C9}\u{106CA}\u{106CB}\u{106CC}\u{106CD}\u{106CE}\u{106CF}\u{106D0}\u{106D1}\u{106D2}\u{106D3}\u{106D4}\u{106D5}\u{106D6}\u{106D7}\u{106D8}\u{106D9}\u{106DA}\u{106DB}\u{106DC}\u{106DD}\u{106DE}\u{106DF}\u{106E0}\u{106E1}\u{106E2}\u{106E3}\u{106E4}\u{106E5}\u{106E6}\u{106E7}\u{106E8}\u{106E9}\u{106EA}\u{106EB}\u{106EC}\u{106ED}\u{106EE}\u{106EF}\u{106F0}\u{106F1}\u{106F2}\u{106F3}\u{106F4}\u{106F5}\u{106F6}\u{106F7}\u{106F8}\u{106F9}\u{106FA}\u{106FB}\u{106FC}\u{106FD}\u{106FE}\u{106FF}\u{10700}\u{10701}\u{10702}\u{10703}\u{10704}\u{10705}\u{10706}\u{10707}\u{10708}\u{10709}\u{1070A}\u{1070B}\u{1070C}\u{1070D}\u{1070E}\u{1070F}\u{10710}\u{10711}\u{10712}\u{10713}\u{10714}\u{10715}\u{10716}\u{10717}\u{10718}\u{10719}\u{1071A}\u{1071B}\u{1071C}\u{1071D}\u{1071E}\u{1071F}\u{10720}\u{10721}\u{10722}\u{10723}\u{10724}\u{10725}\u{10726}\u{10727}\u{10728}\u{10729}\u{1072A}\u{1072B}\u{1072C}\u{1072D}\u{1072E}\u{1072F}\u{10730}\u{10731}\u{10732}\u{10733}\u{10734}\u{10735}\u{10736}\u{10740}\u{10741}\u{10742}\u{10743}\u{10744}\u{10745}\u{10746}\u{10747}\u{10748}\u{10749}\u{1074A}\u{1074B}\u{1074C}\u{1074D}\u{1074E}\u{1074F}\u{10750}\u{10751}\u{10752}\u{10753}\u{10754}\u{10755}\u{10760}\u{10761}\u{10762}\u{10763}\u{10764}\u{10765}\u{10766}\u{10767}\u{10860}\u{10861}\u{10862}\u{10863}\u{10864}\u{10865}\u{10866}\u{10867}\u{10868}\u{10869}\u{1086A}\u{1086B}\u{1086C}\u{1086D}\u{1086E}\u{1086F}\u{10870}\u{10871}\u{10872}\u{10873}\u{10874}\u{10875}\u{10876}\u{10880}\u{10881}\u{10882}\u{10883}\u{10884}\u{10885}\u{10886}\u{10887}\u{10888}\u{10889}\u{1088A}\u{1088B}\u{1088C}\u{1088D}\u{1088E}\u{1088F}\u{10890}\u{10891}\u{10892}\u{10893}\u{10894}\u{10895}\u{10896}\u{10897}\u{10898}\u{10899}\u{1089A}\u{1089B}\u{1089C}\u{1089D}\u{1089E}\u{10A80}\u{10A81}\u{10A82}\u{10A83}\u{10A84}\u{10A85}\u{10A86}\u{10A87}\u{10A88}\u{10A89}\u{10A8A}\u{10A8B}\u{10A8C}\u{10A8D}\u{10A8E}\u{10A8F}\u{10A90}\u{10A91}\u{10A92}\u{10A93}\u{10A94}\u{10A95}\u{10A96}\u{10A97}\u{10A98}\u{10A99}\u{10A9A}\u{10A9B}\u{10A9C}\u{10AC0}\u{10AC1}\u{10AC2}\u{10AC3}\u{10AC4}\u{10AC5}\u{10AC6}\u{10AC7}\u{10AC9}\u{10ACA}\u{10ACB}\u{10ACC}\u{10ACD}\u{10ACE}\u{10ACF}\u{10AD0}\u{10AD1}\u{10AD2}\u{10AD3}\u{10AD4}\u{10AD5}\u{10AD6}\u{10AD7}\u{10AD8}\u{10AD9}\u{10ADA}\u{10ADB}\u{10ADC}\u{10ADD}\u{10ADE}\u{10ADF}\u{10AE0}\u{10AE1}\u{10AE2}\u{10AE3}\u{10AE4}\u{10B80}\u{10B81}\u{10B82}\u{10B83}\u{10B84}\u{10B85}\u{10B86}\u{10B87}\u{10B88}\u{10B89}\u{10B8A}\u{10B8B}\u{10B8C}\u{10B8D}\u{10B8E}\u{10B8F}\u{10B90}\u{10B91}\u{11150}\u{11151}\u{11152}\u{11153}\u{11154}\u{11155}\u{11156}\u{11157}\u{11158}\u{11159}\u{1115A}\u{1115B}\u{1115C}\u{1115D}\u{1115E}\u{1115F}\u{11160}\u{11161}\u{11162}\u{11163}\u{11164}\u{11165}\u{11166}\u{11167}\u{11168}\u{11169}\u{1116A}\u{1116B}\u{1116C}\u{1116D}\u{1116E}\u{1116F}\u{11170}\u{11171}\u{11172}\u{11176}\u{111DA}\u{11200}\u{11201}\u{11202}\u{11203}\u{11204}\u{11205}\u{11206}\u{11207}\u{11208}\u{11209}\u{1120A}\u{1120B}\u{1120C}\u{1120D}\u{1120E}\u{1120F}\u{11210}\u{11211}\u{11213}\u{11214}\u{11215}\u{11216}\u{11217}\u{11218}\u{11219}\u{1121A}\u{1121B}\u{1121C}\u{1121D}\u{1121E}\u{1121F}\u{11220}\u{11221}\u{11222}\u{11223}\u{11224}\u{11225}\u{11226}\u{11227}\u{11228}\u{11229}\u{1122A}\u{1122B}\u{112B0}\u{112B1}\u{112B2}\u{112B3}\u{112B4}\u{112B5}\u{112B6}\u{112B7}\u{112B8}\u{112B9}\u{112BA}\u{112BB}\u{112BC}\u{112BD}\u{112BE}\u{112BF}\u{112C0}\u{112C1}\u{112C2}\u{112C3}\u{112C4}\u{112C5}\u{112C6}\u{112C7}\u{112C8}\u{112C9}\u{112CA}\u{112CB}\u{112CC}\u{112CD}\u{112CE}\u{112CF}\u{112D0}\u{112D1}\u{112D2}\u{112D3}\u{112D4}\u{112D5}\u{112D6}\u{112D7}\u{112D8}\u{112D9}\u{112DA}\u{112DB}\u{112DC}\u{112DD}\u{112DE}\u{11305}\u{11306}\u{11307}\u{11308}\u{11309}\u{1130A}\u{1130B}\u{1130C}\u{1130F}\u{11310}\u{11313}\u{11314}\u{11315}\u{11316}\u{11317}\u{11318}\u{11319}\u{1131A}\u{1131B}\u{1131C}\u{1131D}\u{1131E}\u{1131F}\u{11320}\u{11321}\u{11322}\u{11323}\u{11324}\u{11325}\u{11326}\u{11327}\u{11328}\u{1132A}\u{1132B}\u{1132C}\u{1132D}\u{1132E}\u{1132F}\u{11330}\u{11332}\u{11333}\u{11335}\u{11336}\u{11337}\u{11338}\u{11339}\u{1133D}\u{1135D}\u{1135E}\u{1135F}\u{11360}\u{11361}\u{11480}\u{11481}\u{11482}\u{11483}\u{11484}\u{11485}\u{11486}\u{11487}\u{11488}\u{11489}\u{1148A}\u{1148B}\u{1148C}\u{1148D}\u{1148E}\u{1148F}\u{11490}\u{11491}\u{11492}\u{11493}\u{11494}\u{11495}\u{11496}\u{11497}\u{11498}\u{11499}\u{1149A}\u{1149B}\u{1149C}\u{1149D}\u{1149E}\u{1149F}\u{114A0}\u{114A1}\u{114A2}\u{114A3}\u{114A4}\u{114A5}\u{114A6}\u{114A7}\u{114A8}\u{114A9}\u{114AA}\u{114AB}\u{114AC}\u{114AD}\u{114AE}\u{114AF}\u{114C4}\u{114C5}\u{114C7}\u{11580}\u{11581}\u{11582}\u{11583}\u{11584}\u{11585}\u{11586}\u{11587}\u{11588}\u{11589}\u{1158A}\u{1158B}\u{1158C}\u{1158D}\u{1158E}\u{1158F}\u{11590}\u{11591}\u{11592}\u{11593}\u{11594}\u{11595}\u{11596}\u{11597}\u{11598}\u{11599}\u{1159A}\u{1159B}\u{1159C}\u{1159D}\u{1159E}\u{1159F}\u{115A0}\u{115A1}\u{115A2}\u{115A3}\u{115A4}\u{115A5}\u{115A6}\u{115A7}\u{115A8}\u{115A9}\u{115AA}\u{115AB}\u{115AC}\u{115AD}\u{115AE}\u{11600}\u{11601}\u{11602}\u{11603}\u{11604}\u{11605}\u{11606}\u{11607}\u{11608}\u{11609}\u{1160A}\u{1160B}\u{1160C}\u{1160D}\u{1160E}\u{1160F}\u{11610}\u{11611}\u{11612}\u{11613}\u{11614}\u{11615}\u{11616}\u{11617}\u{11618}\u{11619}\u{1161A}\u{1161B}\u{1161C}\u{1161D}\u{1161E}\u{1161F}\u{11620}\u{11621}\u{11622}\u{11623}\u{11624}\u{11625}\u{11626}\u{11627}\u{11628}\u{11629}\u{1162A}\u{1162B}\u{1162C}\u{1162D}\u{1162E}\u{1162F}\u{11644}\u{118A0}\u{118A1}\u{118A2}\u{118A3}\u{118A4}\u{118A5}\u{118A6}\u{118A7}\u{118A8}\u{118A9}\u{118AA}\u{118AB}\u{118AC}\u{118AD}\u{118AE}\u{118AF}\u{118B0}\u{118B1}\u{118B2}\u{118B3}\u{118B4}\u{118B5}\u{118B6}\u{118B7}\u{118B8}\u{118B9}\u{118BA}\u{118BB}\u{118BC}\u{118BD}\u{118BE}\u{118BF}\u{118C0}\u{118C1}\u{118C2}\u{118C3}\u{118C4}\u{118C5}\u{118C6}\u{118C7}\u{118C8}\u{118C9}\u{118CA}\u{118CB}\u{118CC}\u{118CD}\u{118CE}\u{118CF}\u{118D0}\u{118D1}\u{118D2}\u{118D3}\u{118D4}\u{118D5}\u{118D6}\u{118D7}\u{118D8}\u{118D9}\u{118DA}\u{118DB}\u{118DC}\u{118DD}\u{118DE}\u{118DF}\u{118FF}\u{11AC0}\u{11AC1}\u{11AC2}\u{11AC3}\u{11AC4}\u{11AC5}\u{11AC6}\u{11AC7}\u{11AC8}\u{11AC9}\u{11ACA}\u{11ACB}\u{11ACC}\u{11ACD}\u{11ACE}\u{11ACF}\u{11AD0}\u{11AD1}\u{11AD2}\u{11AD3}\u{11AD4}\u{11AD5}\u{11AD6}\u{11AD7}\u{11AD8}\u{11AD9}\u{11ADA}\u{11ADB}\u{11ADC}\u{11ADD}\u{11ADE}\u{11ADF}\u{11AE0}\u{11AE1}\u{11AE2}\u{11AE3}\u{11AE4}\u{11AE5}\u{11AE6}\u{11AE7}\u{11AE8}\u{11AE9}\u{11AEA}\u{11AEB}\u{11AEC}\u{11AED}\u{11AEE}\u{11AEF}\u{11AF0}\u{11AF1}\u{11AF2}\u{11AF3}\u{11AF4}\u{11AF5}\u{11AF6}\u{11AF7}\u{11AF8}\u{1236F}\u{12370}\u{12371}\u{12372}\u{12373}\u{12374}\u{12375}\u{12376}\u{12377}\u{12378}\u{12379}\u{1237A}\u{1237B}\u{1237C}\u{1237D}\u{1237E}\u{1237F}\u{12380}\u{12381}\u{12382}\u{12383}\u{12384}\u{12385}\u{12386}\u{12387}\u{12388}\u{12389}\u{1238A}\u{1238B}\u{1238C}\u{1238D}\u{1238E}\u{1238F}\u{12390}\u{12391}\u{12392}\u{12393}\u{12394}\u{12395}\u{12396}\u{12397}\u{12398}\u{12463}\u{12464}\u{12465}\u{12466}\u{12467}\u{12468}\u{12469}\u{1246A}\u{1246B}\u{1246C}\u{1246D}\u{1246E}\u{16A40}\u{16A41}\u{16A42}\u{16A43}\u{16A44}\u{16A45}\u{16A46}\u{16A47}\u{16A48}\u{16A49}\u{16A4A}\u{16A4B}\u{16A4C}\u{16A4D}\u{16A4E}\u{16A4F}\u{16A50}\u{16A51}\u{16A52}\u{16A53}\u{16A54}\u{16A55}\u{16A56}\u{16A57}\u{16A58}\u{16A59}\u{16A5A}\u{16A5B}\u{16A5C}\u{16A5D}\u{16A5E}\u{16AD0}\u{16AD1}\u{16AD2}\u{16AD3}\u{16AD4}\u{16AD5}\u{16AD6}\u{16AD7}\u{16AD8}\u{16AD9}\u{16ADA}\u{16ADB}\u{16ADC}\u{16ADD}\u{16ADE}\u{16ADF}\u{16AE0}\u{16AE1}\u{16AE2}\u{16AE3}\u{16AE4}\u{16AE5}\u{16AE6}\u{16AE7}\u{16AE8}\u{16AE9}\u{16AEA}\u{16AEB}\u{16AEC}\u{16AED}\u{16B00}\u{16B01}\u{16B02}\u{16B03}\u{16B04}\u{16B05}\u{16B06}\u{16B07}\u{16B08}\u{16B09}\u{16B0A}\u{16B0B}\u{16B0C}\u{16B0D}\u{16B0E}\u{16B0F}\u{16B10}\u{16B11}\u{16B12}\u{16B13}\u{16B14}\u{16B15}\u{16B16}\u{16B17}\u{16B18}\u{16B19}\u{16B1A}\u{16B1B}\u{16B1C}\u{16B1D}\u{16B1E}\u{16B1F}\u{16B20}\u{16B21}\u{16B22}\u{16B23}\u{16B24}\u{16B25}\u{16B26}\u{16B27}\u{16B28}\u{16B29}\u{16B2A}\u{16B2B}\u{16B2C}\u{16B2D}\u{16B2E}\u{16B2F}\u{16B40}\u{16B41}\u{16B42}\u{16B43}\u{16B63}\u{16B64}\u{16B65}\u{16B66}\u{16B67}\u{16B68}\u{16B69}\u{16B6A}\u{16B6B}\u{16B6C}\u{16B6D}\u{16B6E}\u{16B6F}\u{16B70}\u{16B71}\u{16B72}\u{16B73}\u{16B74}\u{16B75}\u{16B76}\u{16B77}\u{16B7D}\u{16B7E}\u{16B7F}\u{16B80}\u{16B81}\u{16B82}\u{16B83}\u{16B84}\u{16B85}\u{16B86}\u{16B87}\u{16B88}\u{16B89}\u{16B8A}\u{16B8B}\u{16B8C}\u{16B8D}\u{16B8E}\u{16B8F}\u{1BC00}\u{1BC01}\u{1BC02}\u{1BC03}\u{1BC04}\u{1BC05}\u{1BC06}\u{1BC07}\u{1BC08}\u{1BC09}\u{1BC0A}\u{1BC0B}\u{1BC0C}\u{1BC0D}\u{1BC0E}\u{1BC0F}\u{1BC10}\u{1BC11}\u{1BC12}\u{1BC13}\u{1BC14}\u{1BC15}\u{1BC16}\u{1BC17}\u{1BC18}\u{1BC19}\u{1BC1A}\u{1BC1B}\u{1BC1C}\u{1BC1D}\u{1BC1E}\u{1BC1F}\u{1BC20}\u{1BC21}\u{1BC22}\u{1BC23}\u{1BC24}\u{1BC25}\u{1BC26}\u{1BC27}\u{1BC28}\u{1BC29}\u{1BC2A}\u{1BC2B}\u{1BC2C}\u{1BC2D}\u{1BC2E}\u{1BC2F}\u{1BC30}\u{1BC31}\u{1BC32}\u{1BC33}\u{1BC34}\u{1BC35}\u{1BC36}\u{1BC37}\u{1BC38}\u{1BC39}\u{1BC3A}\u{1BC3B}\u{1BC3C}\u{1BC3D}\u{1BC3E}\u{1BC3F}\u{1BC40}\u{1BC41}\u{1BC42}\u{1BC43}\u{1BC44}\u{1BC45}\u{1BC46}\u{1BC47}\u{1BC48}\u{1BC49}\u{1BC4A}\u{1BC4B}\u{1BC4C}\u{1BC4D}\u{1BC4E}\u{1BC4F}\u{1BC50}\u{1BC51}\u{1BC52}\u{1BC53}\u{1BC54}\u{1BC55}\u{1BC56}\u{1BC57}\u{1BC58}\u{1BC59}\u{1BC5A}\u{1BC5B}\u{1BC5C}\u{1BC5D}\u{1BC5E}\u{1BC5F}\u{1BC60}\u{1BC61}\u{1BC62}\u{1BC63}\u{1BC64}\u{1BC65}\u{1BC66}\u{1BC67}\u{1BC68}\u{1BC69}\u{1BC6A}\u{1BC70}\u{1BC71}\u{1BC72}\u{1BC73}\u{1BC74}\u{1BC75}\u{1BC76}\u{1BC77}\u{1BC78}\u{1BC79}\u{1BC7A}\u{1BC7B}\u{1BC7C}\u{1BC80}\u{1BC81}\u{1BC82}\u{1BC83}\u{1BC84}\u{1BC85}\u{1BC86}\u{1BC87}\u{1BC88}\u{1BC90}\u{1BC91}\u{1BC92}\u{1BC93}\u{1BC94}\u{1BC95}\u{1BC96}\u{1BC97}\u{1BC98}\u{1BC99}\u{1E800}\u{1E801}\u{1E802}\u{1E803}\u{1E804}\u{1E805}\u{1E806}\u{1E807}\u{1E808}\u{1E809}\u{1E80A}\u{1E80B}\u{1E80C}\u{1E80D}\u{1E80E}\u{1E80F}\u{1E810}\u{1E811}\u{1E812}\u{1E813}\u{1E814}\u{1E815}\u{1E816}\u{1E817}\u{1E818}\u{1E819}\u{1E81A}\u{1E81B}\u{1E81C}\u{1E81D}\u{1E81E}\u{1E81F}\u{1E820}\u{1E821}\u{1E822}\u{1E823}\u{1E824}\u{1E825}\u{1E826}\u{1E827}\u{1E828}\u{1E829}\u{1E82A}\u{1E82B}\u{1E82C}\u{1E82D}\u{1E82E}\u{1E82F}\u{1E830}\u{1E831}\u{1E832}\u{1E833}\u{1E834}\u{1E835}\u{1E836}\u{1E837}\u{1E838}\u{1E839}\u{1E83A}\u{1E83B}\u{1E83C}\u{1E83D}\u{1E83E}\u{1E83F}\u{1E840}\u{1E841}\u{1E842}\u{1E843}\u{1E844}\u{1E845}\u{1E846}\u{1E847}\u{1E848}\u{1E849}\u{1E84A}\u{1E84B}\u{1E84C}\u{1E84D}\u{1E84E}\u{1E84F}\u{1E850}\u{1E851}\u{1E852}\u{1E853}\u{1E854}\u{1E855}\u{1E856}\u{1E857}\u{1E858}\u{1E859}\u{1E85A}\u{1E85B}\u{1E85C}\u{1E85D}\u{1E85E}\u{1E85F}\u{1E860}\u{1E861}\u{1E862}\u{1E863}\u{1E864}\u{1E865}\u{1E866}\u{1E867}\u{1E868}\u{1E869}\u{1E86A}\u{1E86B}\u{1E86C}\u{1E86D}\u{1E86E}\u{1E86F}\u{1E870}\u{1E871}\u{1E872}\u{1E873}\u{1E874}\u{1E875}\u{1E876}\u{1E877}\u{1E878}\u{1E879}\u{1E87A}\u{1E87B}\u{1E87C}\u{1E87D}\u{1E87E}\u{1E87F}\u{1E880}\u{1E881}\u{1E882}\u{1E883}\u{1E884}\u{1E885}\u{1E886}\u{1E887}\u{1E888}\u{1E889}\u{1E88A}\u{1E88B}\u{1E88C}\u{1E88D}\u{1E88E}\u{1E88F}\u{1E890}\u{1E891}\u{1E892}\u{1E893}\u{1E894}\u{1E895}\u{1E896}\u{1E897}\u{1E898}\u{1E899}\u{1E89A}\u{1E89B}\u{1E89C}\u{1E89D}\u{1E89E}\u{1E89F}\u{1E8A0}\u{1E8A1}\u{1E8A2}\u{1E8A3}\u{1E8A4}\u{1E8A5}\u{1E8A6}\u{1E8A7}\u{1E8A8}\u{1E8A9}\u{1E8AA}\u{1E8AB}\u{1E8AC}\u{1E8AD}\u{1E8AE}\u{1E8AF}\u{1E8B0}\u{1E8B1}\u{1E8B2}\u{1E8B3}\u{1E8B4}\u{1E8B5}\u{1E8B6}\u{1E8B7}\u{1E8B8}\u{1E8B9}\u{1E8BA}\u{1E8BB}\u{1E8BC}\u{1E8BD}\u{1E8BE}\u{1E8BF}\u{1E8C0}\u{1E8C1}\u{1E8C2}\u{1E8C3}\u{1E8C4}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-class.js new file mode 100644 index 000000000000..67bcb640742b --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v7.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ͿԨԩԪԫԬԭԮԯࢡࢭࢮࢯࢰࢱࢲॸঀఴᛱᛲᛳᛴᛵᛶᛷᛸᤝᤞꚘꚙꚚꚛꚜꚝꞔꞕꞖꞗꞘꞙꞚꞛꞜꞝꞞꞟꞫꞬꞭꞰꞱꟷꧠꧡꧢꧣꧤꧦꧧꧨꧩꧪꧫꧬꧭꧮꧯꧺꧻꧼꧽꧾꩾꩿꬰꬱꬲꬳꬴꬵꬶꬷꬸꬹꬺꬻꬼꬽꬾꬿꭀꭁꭂꭃꭄꭅꭆꭇꭈꭉꭊꭋꭌꭍꭎꭏꭐꭑꭒꭓꭔꭕꭖꭗꭘꭙꭚꭜꭝꭞꭟꭤꭥ𐌟𐍐𐍑𐍒𐍓𐍔𐍕𐍖𐍗𐍘𐍙𐍚𐍛𐍜𐍝𐍞𐍟𐍠𐍡𐍢𐍣𐍤𐍥𐍦𐍧𐍨𐍩𐍪𐍫𐍬𐍭𐍮𐍯𐍰𐍱𐍲𐍳𐍴𐍵𐔀𐔁𐔂𐔃𐔄𐔅𐔆𐔇𐔈𐔉𐔊𐔋𐔌𐔍𐔎𐔏𐔐𐔑𐔒𐔓𐔔𐔕𐔖𐔗𐔘𐔙𐔚𐔛𐔜𐔝𐔞𐔟𐔠𐔡𐔢𐔣𐔤𐔥𐔦𐔧𐔰𐔱𐔲𐔳𐔴𐔵𐔶𐔷𐔸𐔹𐔺𐔻𐔼𐔽𐔾𐔿𐕀𐕁𐕂𐕃𐕄𐕅𐕆𐕇𐕈𐕉𐕊𐕋𐕌𐕍𐕎𐕏𐕐𐕑𐕒𐕓𐕔𐕕𐕖𐕗𐕘𐕙𐕚𐕛𐕜𐕝𐕞𐕟𐕠𐕡𐕢𐕣𐘀𐘁𐘂𐘃𐘄𐘅𐘆𐘇𐘈𐘉𐘊𐘋𐘌𐘍𐘎𐘏𐘐𐘑𐘒𐘓𐘔𐘕𐘖𐘗𐘘𐘙𐘚𐘛𐘜𐘝𐘞𐘟𐘠𐘡𐘢𐘣𐘤𐘥𐘦𐘧𐘨𐘩𐘪𐘫𐘬𐘭𐘮𐘯𐘰𐘱𐘲𐘳𐘴𐘵𐘶𐘷𐘸𐘹𐘺𐘻𐘼𐘽𐘾𐘿𐙀𐙁𐙂𐙃𐙄𐙅𐙆𐙇𐙈𐙉𐙊𐙋𐙌𐙍𐙎𐙏𐙐𐙑𐙒𐙓𐙔𐙕𐙖𐙗𐙘𐙙𐙚𐙛𐙜𐙝𐙞𐙟𐙠𐙡𐙢𐙣𐙤𐙥𐙦𐙧𐙨𐙩𐙪𐙫𐙬𐙭𐙮𐙯𐙰𐙱𐙲𐙳𐙴𐙵𐙶𐙷𐙸𐙹𐙺𐙻𐙼𐙽𐙾𐙿𐚀𐚁𐚂𐚃𐚄𐚅𐚆𐚇𐚈𐚉𐚊𐚋𐚌𐚍𐚎𐚏𐚐𐚑𐚒𐚓𐚔𐚕𐚖𐚗𐚘𐚙𐚚𐚛𐚜𐚝𐚞𐚟𐚠𐚡𐚢𐚣𐚤𐚥𐚦𐚧𐚨𐚩𐚪𐚫𐚬𐚭𐚮𐚯𐚰𐚱𐚲𐚳𐚴𐚵𐚶𐚷𐚸𐚹𐚺𐚻𐚼𐚽𐚾𐚿𐛀𐛁𐛂𐛃𐛄𐛅𐛆𐛇𐛈𐛉𐛊𐛋𐛌𐛍𐛎𐛏𐛐𐛑𐛒𐛓𐛔𐛕𐛖𐛗𐛘𐛙𐛚𐛛𐛜𐛝𐛞𐛟𐛠𐛡𐛢𐛣𐛤𐛥𐛦𐛧𐛨𐛩𐛪𐛫𐛬𐛭𐛮𐛯𐛰𐛱𐛲𐛳𐛴𐛵𐛶𐛷𐛸𐛹𐛺𐛻𐛼𐛽𐛾𐛿𐜀𐜁𐜂𐜃𐜄𐜅𐜆𐜇𐜈𐜉𐜊𐜋𐜌𐜍𐜎𐜏𐜐𐜑𐜒𐜓𐜔𐜕𐜖𐜗𐜘𐜙𐜚𐜛𐜜𐜝𐜞𐜟𐜠𐜡𐜢𐜣𐜤𐜥𐜦𐜧𐜨𐜩𐜪𐜫𐜬𐜭𐜮𐜯𐜰𐜱𐜲𐜳𐜴𐜵𐜶𐝀𐝁𐝂𐝃𐝄𐝅𐝆𐝇𐝈𐝉𐝊𐝋𐝌𐝍𐝎𐝏𐝐𐝑𐝒𐝓𐝔𐝕𐝠𐝡𐝢𐝣𐝤𐝥𐝦𐝧𐡠𐡡𐡢𐡣𐡤𐡥𐡦𐡧𐡨𐡩𐡪𐡫𐡬𐡭𐡮𐡯𐡰𐡱𐡲𐡳𐡴𐡵𐡶𐢀𐢁𐢂𐢃𐢄𐢅𐢆𐢇𐢈𐢉𐢊𐢋𐢌𐢍𐢎𐢏𐢐𐢑𐢒𐢓𐢔𐢕𐢖𐢗𐢘𐢙𐢚𐢛𐢜𐢝𐢞𐪀𐪁𐪂𐪃𐪄𐪅𐪆𐪇𐪈𐪉𐪊𐪋𐪌𐪍𐪎𐪏𐪐𐪑𐪒𐪓𐪔𐪕𐪖𐪗𐪘𐪙𐪚𐪛𐪜𐫀𐫁𐫂𐫃𐫄𐫅𐫆𐫇𐫉𐫊𐫋𐫌𐫍𐫎𐫏𐫐𐫑𐫒𐫓𐫔𐫕𐫖𐫗𐫘𐫙𐫚𐫛𐫜𐫝𐫞𐫟𐫠𐫡𐫢𐫣𐫤𐮀𐮁𐮂𐮃𐮄𐮅𐮆𐮇𐮈𐮉𐮊𐮋𐮌𐮍𐮎𐮏𐮐𐮑𑅐𑅑𑅒𑅓𑅔𑅕𑅖𑅗𑅘𑅙𑅚𑅛𑅜𑅝𑅞𑅟𑅠𑅡𑅢𑅣𑅤𑅥𑅦𑅧𑅨𑅩𑅪𑅫𑅬𑅭𑅮𑅯𑅰𑅱𑅲𑅶𑇚𑈀𑈁𑈂𑈃𑈄𑈅𑈆𑈇𑈈𑈉𑈊𑈋𑈌𑈍𑈎𑈏𑈐𑈑𑈓𑈔𑈕𑈖𑈗𑈘𑈙𑈚𑈛𑈜𑈝𑈞𑈟𑈠𑈡𑈢𑈣𑈤𑈥𑈦𑈧𑈨𑈩𑈪𑈫𑊰𑊱𑊲𑊳𑊴𑊵𑊶𑊷𑊸𑊹𑊺𑊻𑊼𑊽𑊾𑊿𑋀𑋁𑋂𑋃𑋄𑋅𑋆𑋇𑋈𑋉𑋊𑋋𑋌𑋍𑋎𑋏𑋐𑋑𑋒𑋓𑋔𑋕𑋖𑋗𑋘𑋙𑋚𑋛𑋜𑋝𑋞𑌅𑌆𑌇𑌈𑌉𑌊𑌋𑌌𑌏𑌐𑌓𑌔𑌕𑌖𑌗𑌘𑌙𑌚𑌛𑌜𑌝𑌞𑌟𑌠𑌡𑌢𑌣𑌤𑌥𑌦𑌧𑌨𑌪𑌫𑌬𑌭𑌮𑌯𑌰𑌲𑌳𑌵𑌶𑌷𑌸𑌹𑌽𑍝𑍞𑍟𑍠𑍡𑒀𑒁𑒂𑒃𑒄𑒅𑒆𑒇𑒈𑒉𑒊𑒋𑒌𑒍𑒎𑒏𑒐𑒑𑒒𑒓𑒔𑒕𑒖𑒗𑒘𑒙𑒚𑒛𑒜𑒝𑒞𑒟𑒠𑒡𑒢𑒣𑒤𑒥𑒦𑒧𑒨𑒩𑒪𑒫𑒬𑒭𑒮𑒯𑓄𑓅𑓇𑖀𑖁𑖂𑖃𑖄𑖅𑖆𑖇𑖈𑖉𑖊𑖋𑖌𑖍𑖎𑖏𑖐𑖑𑖒𑖓𑖔𑖕𑖖𑖗𑖘𑖙𑖚𑖛𑖜𑖝𑖞𑖟𑖠𑖡𑖢𑖣𑖤𑖥𑖦𑖧𑖨𑖩𑖪𑖫𑖬𑖭𑖮𑘀𑘁𑘂𑘃𑘄𑘅𑘆𑘇𑘈𑘉𑘊𑘋𑘌𑘍𑘎𑘏𑘐𑘑𑘒𑘓𑘔𑘕𑘖𑘗𑘘𑘙𑘚𑘛𑘜𑘝𑘞𑘟𑘠𑘡𑘢𑘣𑘤𑘥𑘦𑘧𑘨𑘩𑘪𑘫𑘬𑘭𑘮𑘯𑙄𑢠𑢡𑢢𑢣𑢤𑢥𑢦𑢧𑢨𑢩𑢪𑢫𑢬𑢭𑢮𑢯𑢰𑢱𑢲𑢳𑢴𑢵𑢶𑢷𑢸𑢹𑢺𑢻𑢼𑢽𑢾𑢿𑣀𑣁𑣂𑣃𑣄𑣅𑣆𑣇𑣈𑣉𑣊𑣋𑣌𑣍𑣎𑣏𑣐𑣑𑣒𑣓𑣔𑣕𑣖𑣗𑣘𑣙𑣚𑣛𑣜𑣝𑣞𑣟𑣿𑫀𑫁𑫂𑫃𑫄𑫅𑫆𑫇𑫈𑫉𑫊𑫋𑫌𑫍𑫎𑫏𑫐𑫑𑫒𑫓𑫔𑫕𑫖𑫗𑫘𑫙𑫚𑫛𑫜𑫝𑫞𑫟𑫠𑫡𑫢𑫣𑫤𑫥𑫦𑫧𑫨𑫩𑫪𑫫𑫬𑫭𑫮𑫯𑫰𑫱𑫲𑫳𑫴𑫵𑫶𑫷𑫸𒍯𒍰𒍱𒍲𒍳𒍴𒍵𒍶𒍷𒍸𒍹𒍺𒍻𒍼𒍽𒍾𒍿𒎀𒎁𒎂𒎃𒎄𒎅𒎆𒎇𒎈𒎉𒎊𒎋𒎌𒎍𒎎𒎏𒎐𒎑𒎒𒎓𒎔𒎕𒎖𒎗𒎘𒑣𒑤𒑥𒑦𒑧𒑨𒑩𒑪𒑫𒑬𒑭𒑮𖩀𖩁𖩂𖩃𖩄𖩅𖩆𖩇𖩈𖩉𖩊𖩋𖩌𖩍𖩎𖩏𖩐𖩑𖩒𖩓𖩔𖩕𖩖𖩗𖩘𖩙𖩚𖩛𖩜𖩝𖩞𖫐𖫑𖫒𖫓𖫔𖫕𖫖𖫗𖫘𖫙𖫚𖫛𖫜𖫝𖫞𖫟𖫠𖫡𖫢𖫣𖫤𖫥𖫦𖫧𖫨𖫩𖫪𖫫𖫬𖫭𖬀𖬁𖬂𖬃𖬄𖬅𖬆𖬇𖬈𖬉𖬊𖬋𖬌𖬍𖬎𖬏𖬐𖬑𖬒𖬓𖬔𖬕𖬖𖬗𖬘𖬙𖬚𖬛𖬜𖬝𖬞𖬟𖬠𖬡𖬢𖬣𖬤𖬥𖬦𖬧𖬨𖬩𖬪𖬫𖬬𖬭𖬮𖬯𖭀𖭁𖭂𖭃𖭣𖭤𖭥𖭦𖭧𖭨𖭩𖭪𖭫𖭬𖭭𖭮𖭯𖭰𖭱𖭲𖭳𖭴𖭵𖭶𖭷𖭽𖭾𖭿𖮀𖮁𖮂𖮃𖮄𖮅𖮆𖮇𖮈𖮉𖮊𖮋𖮌𖮍𖮎𖮏𛰀𛰁𛰂𛰃𛰄𛰅𛰆𛰇𛰈𛰉𛰊𛰋𛰌𛰍𛰎𛰏𛰐𛰑𛰒𛰓𛰔𛰕𛰖𛰗𛰘𛰙𛰚𛰛𛰜𛰝𛰞𛰟𛰠𛰡𛰢𛰣𛰤𛰥𛰦𛰧𛰨𛰩𛰪𛰫𛰬𛰭𛰮𛰯𛰰𛰱𛰲𛰳𛰴𛰵𛰶𛰷𛰸𛰹𛰺𛰻𛰼𛰽𛰾𛰿𛱀𛱁𛱂𛱃𛱄𛱅𛱆𛱇𛱈𛱉𛱊𛱋𛱌𛱍𛱎𛱏𛱐𛱑𛱒𛱓𛱔𛱕𛱖𛱗𛱘𛱙𛱚𛱛𛱜𛱝𛱞𛱟𛱠𛱡𛱢𛱣𛱤𛱥𛱦𛱧𛱨𛱩𛱪𛱰𛱱𛱲𛱳𛱴𛱵𛱶𛱷𛱸𛱹𛱺𛱻𛱼𛲀𛲁𛲂𛲃𛲄𛲅𛲆𛲇𛲈𛲐𛲑𛲒𛲓𛲔𛲕𛲖𛲗𛲘𛲙𞠀𞠁𞠂𞠃𞠄𞠅𞠆𞠇𞠈𞠉𞠊𞠋𞠌𞠍𞠎𞠏𞠐𞠑𞠒𞠓𞠔𞠕𞠖𞠗𞠘𞠙𞠚𞠛𞠜𞠝𞠞𞠟𞠠𞠡𞠢𞠣𞠤𞠥𞠦𞠧𞠨𞠩𞠪𞠫𞠬𞠭𞠮𞠯𞠰𞠱𞠲𞠳𞠴𞠵𞠶𞠷𞠸𞠹𞠺𞠻𞠼𞠽𞠾𞠿𞡀𞡁𞡂𞡃𞡄𞡅𞡆𞡇𞡈𞡉𞡊𞡋𞡌𞡍𞡎𞡏𞡐𞡑𞡒𞡓𞡔𞡕𞡖𞡗𞡘𞡙𞡚𞡛𞡜𞡝𞡞𞡟𞡠𞡡𞡢𞡣𞡤𞡥𞡦𞡧𞡨𞡩𞡪𞡫𞡬𞡭𞡮𞡯𞡰𞡱𞡲𞡳𞡴𞡵𞡶𞡷𞡸𞡹𞡺𞡻𞡼𞡽𞡾𞡿𞢀𞢁𞢂𞢃𞢄𞢅𞢆𞢇𞢈𞢉𞢊𞢋𞢌𞢍𞢎𞢏𞢐𞢑𞢒𞢓𞢔𞢕𞢖𞢗𞢘𞢙𞢚𞢛𞢜𞢝𞢞𞢟𞢠𞢡𞢢𞢣𞢤𞢥𞢦𞢧𞢨𞢩𞢪𞢫𞢬𞢭𞢮𞢯𞢰𞢱𞢲𞢳𞢴𞢵𞢶𞢷𞢸𞢹𞢺𞢻𞢼𞢽𞢾𞢿𞣀𞣁𞣂𞣃𞣄; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-escaped.js index a1ec9a68ae04..f1a4a91bb727 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-7.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-7.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-7.0.0.js index 6acab16e6ea4..c317bbdd6329 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-7.0.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-7.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-class-escaped.js new file mode 100644 index 000000000000..65922a9d8c10 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v8.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u08B3\u08B4\u0AF9\u0C5A\u0D5F\u13F5\u13F8\u13F9\u13FA\u13FB\u13FC\u13FD\u19B0\u19B1\u19B2\u19B3\u19B4\u19B5\u19B6\u19B7\u19B8\u19B9\u19BA\u19BB\u19BC\u19BD\u19BE\u19BF\u19C0\u19C8\u19C9\u9FCD\u9FCE\u9FCF\u9FD0\u9FD1\u9FD2\u9FD3\u9FD4\u9FD5\uA78F\uA7B2\uA7B3\uA7B4\uA7B5\uA7B6\uA7B7\uA8FD\uAB60\uAB61\uAB62\uAB63\uAB70\uAB71\uAB72\uAB73\uAB74\uAB75\uAB76\uAB77\uAB78\uAB79\uAB7A\uAB7B\uAB7C\uAB7D\uAB7E\uAB7F\uAB80\uAB81\uAB82\uAB83\uAB84\uAB85\uAB86\uAB87\uAB88\uAB89\uAB8A\uAB8B\uAB8C\uAB8D\uAB8E\uAB8F\uAB90\uAB91\uAB92\uAB93\uAB94\uAB95\uAB96\uAB97\uAB98\uAB99\uAB9A\uAB9B\uAB9C\uAB9D\uAB9E\uAB9F\uABA0\uABA1\uABA2\uABA3\uABA4\uABA5\uABA6\uABA7\uABA8\uABA9\uABAA\uABAB\uABAC\uABAD\uABAE\uABAF\uABB0\uABB1\uABB2\uABB3\uABB4\uABB5\uABB6\uABB7\uABB8\uABB9\uABBA\uABBB\uABBC\uABBD\uABBE\uABBF\u{108E0}\u{108E1}\u{108E2}\u{108E3}\u{108E4}\u{108E5}\u{108E6}\u{108E7}\u{108E8}\u{108E9}\u{108EA}\u{108EB}\u{108EC}\u{108ED}\u{108EE}\u{108EF}\u{108F0}\u{108F1}\u{108F2}\u{108F4}\u{108F5}\u{10C80}\u{10C81}\u{10C82}\u{10C83}\u{10C84}\u{10C85}\u{10C86}\u{10C87}\u{10C88}\u{10C89}\u{10C8A}\u{10C8B}\u{10C8C}\u{10C8D}\u{10C8E}\u{10C8F}\u{10C90}\u{10C91}\u{10C92}\u{10C93}\u{10C94}\u{10C95}\u{10C96}\u{10C97}\u{10C98}\u{10C99}\u{10C9A}\u{10C9B}\u{10C9C}\u{10C9D}\u{10C9E}\u{10C9F}\u{10CA0}\u{10CA1}\u{10CA2}\u{10CA3}\u{10CA4}\u{10CA5}\u{10CA6}\u{10CA7}\u{10CA8}\u{10CA9}\u{10CAA}\u{10CAB}\u{10CAC}\u{10CAD}\u{10CAE}\u{10CAF}\u{10CB0}\u{10CB1}\u{10CB2}\u{10CC0}\u{10CC1}\u{10CC2}\u{10CC3}\u{10CC4}\u{10CC5}\u{10CC6}\u{10CC7}\u{10CC8}\u{10CC9}\u{10CCA}\u{10CCB}\u{10CCC}\u{10CCD}\u{10CCE}\u{10CCF}\u{10CD0}\u{10CD1}\u{10CD2}\u{10CD3}\u{10CD4}\u{10CD5}\u{10CD6}\u{10CD7}\u{10CD8}\u{10CD9}\u{10CDA}\u{10CDB}\u{10CDC}\u{10CDD}\u{10CDE}\u{10CDF}\u{10CE0}\u{10CE1}\u{10CE2}\u{10CE3}\u{10CE4}\u{10CE5}\u{10CE6}\u{10CE7}\u{10CE8}\u{10CE9}\u{10CEA}\u{10CEB}\u{10CEC}\u{10CED}\u{10CEE}\u{10CEF}\u{10CF0}\u{10CF1}\u{10CF2}\u{111DC}\u{11280}\u{11281}\u{11282}\u{11283}\u{11284}\u{11285}\u{11286}\u{11288}\u{1128A}\u{1128B}\u{1128C}\u{1128D}\u{1128F}\u{11290}\u{11291}\u{11292}\u{11293}\u{11294}\u{11295}\u{11296}\u{11297}\u{11298}\u{11299}\u{1129A}\u{1129B}\u{1129C}\u{1129D}\u{1129F}\u{112A0}\u{112A1}\u{112A2}\u{112A3}\u{112A4}\u{112A5}\u{112A6}\u{112A7}\u{112A8}\u{11350}\u{115D8}\u{115D9}\u{115DA}\u{115DB}\u{11700}\u{11701}\u{11702}\u{11703}\u{11704}\u{11705}\u{11706}\u{11707}\u{11708}\u{11709}\u{1170A}\u{1170B}\u{1170C}\u{1170D}\u{1170E}\u{1170F}\u{11710}\u{11711}\u{11712}\u{11713}\u{11714}\u{11715}\u{11716}\u{11717}\u{11718}\u{11719}\u{12399}\u{12480}\u{12481}\u{12482}\u{12483}\u{12484}\u{12485}\u{12486}\u{12487}\u{12488}\u{12489}\u{1248A}\u{1248B}\u{1248C}\u{1248D}\u{1248E}\u{1248F}\u{12490}\u{12491}\u{12492}\u{12493}\u{12494}\u{12495}\u{12496}\u{12497}\u{12498}\u{12499}\u{1249A}\u{1249B}\u{1249C}\u{1249D}\u{1249E}\u{1249F}\u{124A0}\u{124A1}\u{124A2}\u{124A3}\u{124A4}\u{124A5}\u{124A6}\u{124A7}\u{124A8}\u{124A9}\u{124AA}\u{124AB}\u{124AC}\u{124AD}\u{124AE}\u{124AF}\u{124B0}\u{124B1}\u{124B2}\u{124B3}\u{124B4}\u{124B5}\u{124B6}\u{124B7}\u{124B8}\u{124B9}\u{124BA}\u{124BB}\u{124BC}\u{124BD}\u{124BE}\u{124BF}\u{124C0}\u{124C1}\u{124C2}\u{124C3}\u{124C4}\u{124C5}\u{124C6}\u{124C7}\u{124C8}\u{124C9}\u{124CA}\u{124CB}\u{124CC}\u{124CD}\u{124CE}\u{124CF}\u{124D0}\u{124D1}\u{124D2}\u{124D3}\u{124D4}\u{124D5}\u{124D6}\u{124D7}\u{124D8}\u{124D9}\u{124DA}\u{124DB}\u{124DC}\u{124DD}\u{124DE}\u{124DF}\u{124E0}\u{124E1}\u{124E2}\u{124E3}\u{124E4}\u{124E5}\u{124E6}\u{124E7}\u{124E8}\u{124E9}\u{124EA}\u{124EB}\u{124EC}\u{124ED}\u{124EE}\u{124EF}\u{124F0}\u{124F1}\u{124F2}\u{124F3}\u{124F4}\u{124F5}\u{124F6}\u{124F7}\u{124F8}\u{124F9}\u{124FA}\u{124FB}\u{124FC}\u{124FD}\u{124FE}\u{124FF}\u{12500}\u{12501}\u{12502}\u{12503}\u{12504}\u{12505}\u{12506}\u{12507}\u{12508}\u{12509}\u{1250A}\u{1250B}\u{1250C}\u{1250D}\u{1250E}\u{1250F}\u{12510}\u{12511}\u{12512}\u{12513}\u{12514}\u{12515}\u{12516}\u{12517}\u{12518}\u{12519}\u{1251A}\u{1251B}\u{1251C}\u{1251D}\u{1251E}\u{1251F}\u{12520}\u{12521}\u{12522}\u{12523}\u{12524}\u{12525}\u{12526}\u{12527}\u{12528}\u{12529}\u{1252A}\u{1252B}\u{1252C}\u{1252D}\u{1252E}\u{1252F}\u{12530}\u{12531}\u{12532}\u{12533}\u{12534}\u{12535}\u{12536}\u{12537}\u{12538}\u{12539}\u{1253A}\u{1253B}\u{1253C}\u{1253D}\u{1253E}\u{1253F}\u{12540}\u{12541}\u{12542}\u{12543}\u{14400}\u{14401}\u{14402}\u{14403}\u{14404}\u{14405}\u{14406}\u{14407}\u{14408}\u{14409}\u{1440A}\u{1440B}\u{1440C}\u{1440D}\u{1440E}\u{1440F}\u{14410}\u{14411}\u{14412}\u{14413}\u{14414}\u{14415}\u{14416}\u{14417}\u{14418}\u{14419}\u{1441A}\u{1441B}\u{1441C}\u{1441D}\u{1441E}\u{1441F}\u{14420}\u{14421}\u{14422}\u{14423}\u{14424}\u{14425}\u{14426}\u{14427}\u{14428}\u{14429}\u{1442A}\u{1442B}\u{1442C}\u{1442D}\u{1442E}\u{1442F}\u{14430}\u{14431}\u{14432}\u{14433}\u{14434}\u{14435}\u{14436}\u{14437}\u{14438}\u{14439}\u{1443A}\u{1443B}\u{1443C}\u{1443D}\u{1443E}\u{1443F}\u{14440}\u{14441}\u{14442}\u{14443}\u{14444}\u{14445}\u{14446}\u{14447}\u{14448}\u{14449}\u{1444A}\u{1444B}\u{1444C}\u{1444D}\u{1444E}\u{1444F}\u{14450}\u{14451}\u{14452}\u{14453}\u{14454}\u{14455}\u{14456}\u{14457}\u{14458}\u{14459}\u{1445A}\u{1445B}\u{1445C}\u{1445D}\u{1445E}\u{1445F}\u{14460}\u{14461}\u{14462}\u{14463}\u{14464}\u{14465}\u{14466}\u{14467}\u{14468}\u{14469}\u{1446A}\u{1446B}\u{1446C}\u{1446D}\u{1446E}\u{1446F}\u{14470}\u{14471}\u{14472}\u{14473}\u{14474}\u{14475}\u{14476}\u{14477}\u{14478}\u{14479}\u{1447A}\u{1447B}\u{1447C}\u{1447D}\u{1447E}\u{1447F}\u{14480}\u{14481}\u{14482}\u{14483}\u{14484}\u{14485}\u{14486}\u{14487}\u{14488}\u{14489}\u{1448A}\u{1448B}\u{1448C}\u{1448D}\u{1448E}\u{1448F}\u{14490}\u{14491}\u{14492}\u{14493}\u{14494}\u{14495}\u{14496}\u{14497}\u{14498}\u{14499}\u{1449A}\u{1449B}\u{1449C}\u{1449D}\u{1449E}\u{1449F}\u{144A0}\u{144A1}\u{144A2}\u{144A3}\u{144A4}\u{144A5}\u{144A6}\u{144A7}\u{144A8}\u{144A9}\u{144AA}\u{144AB}\u{144AC}\u{144AD}\u{144AE}\u{144AF}\u{144B0}\u{144B1}\u{144B2}\u{144B3}\u{144B4}\u{144B5}\u{144B6}\u{144B7}\u{144B8}\u{144B9}\u{144BA}\u{144BB}\u{144BC}\u{144BD}\u{144BE}\u{144BF}\u{144C0}\u{144C1}\u{144C2}\u{144C3}\u{144C4}\u{144C5}\u{144C6}\u{144C7}\u{144C8}\u{144C9}\u{144CA}\u{144CB}\u{144CC}\u{144CD}\u{144CE}\u{144CF}\u{144D0}\u{144D1}\u{144D2}\u{144D3}\u{144D4}\u{144D5}\u{144D6}\u{144D7}\u{144D8}\u{144D9}\u{144DA}\u{144DB}\u{144DC}\u{144DD}\u{144DE}\u{144DF}\u{144E0}\u{144E1}\u{144E2}\u{144E3}\u{144E4}\u{144E5}\u{144E6}\u{144E7}\u{144E8}\u{144E9}\u{144EA}\u{144EB}\u{144EC}\u{144ED}\u{144EE}\u{144EF}\u{144F0}\u{144F1}\u{144F2}\u{144F3}\u{144F4}\u{144F5}\u{144F6}\u{144F7}\u{144F8}\u{144F9}\u{144FA}\u{144FB}\u{144FC}\u{144FD}\u{144FE}\u{144FF}\u{14500}\u{14501}\u{14502}\u{14503}\u{14504}\u{14505}\u{14506}\u{14507}\u{14508}\u{14509}\u{1450A}\u{1450B}\u{1450C}\u{1450D}\u{1450E}\u{1450F}\u{14510}\u{14511}\u{14512}\u{14513}\u{14514}\u{14515}\u{14516}\u{14517}\u{14518}\u{14519}\u{1451A}\u{1451B}\u{1451C}\u{1451D}\u{1451E}\u{1451F}\u{14520}\u{14521}\u{14522}\u{14523}\u{14524}\u{14525}\u{14526}\u{14527}\u{14528}\u{14529}\u{1452A}\u{1452B}\u{1452C}\u{1452D}\u{1452E}\u{1452F}\u{14530}\u{14531}\u{14532}\u{14533}\u{14534}\u{14535}\u{14536}\u{14537}\u{14538}\u{14539}\u{1453A}\u{1453B}\u{1453C}\u{1453D}\u{1453E}\u{1453F}\u{14540}\u{14541}\u{14542}\u{14543}\u{14544}\u{14545}\u{14546}\u{14547}\u{14548}\u{14549}\u{1454A}\u{1454B}\u{1454C}\u{1454D}\u{1454E}\u{1454F}\u{14550}\u{14551}\u{14552}\u{14553}\u{14554}\u{14555}\u{14556}\u{14557}\u{14558}\u{14559}\u{1455A}\u{1455B}\u{1455C}\u{1455D}\u{1455E}\u{1455F}\u{14560}\u{14561}\u{14562}\u{14563}\u{14564}\u{14565}\u{14566}\u{14567}\u{14568}\u{14569}\u{1456A}\u{1456B}\u{1456C}\u{1456D}\u{1456E}\u{1456F}\u{14570}\u{14571}\u{14572}\u{14573}\u{14574}\u{14575}\u{14576}\u{14577}\u{14578}\u{14579}\u{1457A}\u{1457B}\u{1457C}\u{1457D}\u{1457E}\u{1457F}\u{14580}\u{14581}\u{14582}\u{14583}\u{14584}\u{14585}\u{14586}\u{14587}\u{14588}\u{14589}\u{1458A}\u{1458B}\u{1458C}\u{1458D}\u{1458E}\u{1458F}\u{14590}\u{14591}\u{14592}\u{14593}\u{14594}\u{14595}\u{14596}\u{14597}\u{14598}\u{14599}\u{1459A}\u{1459B}\u{1459C}\u{1459D}\u{1459E}\u{1459F}\u{145A0}\u{145A1}\u{145A2}\u{145A3}\u{145A4}\u{145A5}\u{145A6}\u{145A7}\u{145A8}\u{145A9}\u{145AA}\u{145AB}\u{145AC}\u{145AD}\u{145AE}\u{145AF}\u{145B0}\u{145B1}\u{145B2}\u{145B3}\u{145B4}\u{145B5}\u{145B6}\u{145B7}\u{145B8}\u{145B9}\u{145BA}\u{145BB}\u{145BC}\u{145BD}\u{145BE}\u{145BF}\u{145C0}\u{145C1}\u{145C2}\u{145C3}\u{145C4}\u{145C5}\u{145C6}\u{145C7}\u{145C8}\u{145C9}\u{145CA}\u{145CB}\u{145CC}\u{145CD}\u{145CE}\u{145CF}\u{145D0}\u{145D1}\u{145D2}\u{145D3}\u{145D4}\u{145D5}\u{145D6}\u{145D7}\u{145D8}\u{145D9}\u{145DA}\u{145DB}\u{145DC}\u{145DD}\u{145DE}\u{145DF}\u{145E0}\u{145E1}\u{145E2}\u{145E3}\u{145E4}\u{145E5}\u{145E6}\u{145E7}\u{145E8}\u{145E9}\u{145EA}\u{145EB}\u{145EC}\u{145ED}\u{145EE}\u{145EF}\u{145F0}\u{145F1}\u{145F2}\u{145F3}\u{145F4}\u{145F5}\u{145F6}\u{145F7}\u{145F8}\u{145F9}\u{145FA}\u{145FB}\u{145FC}\u{145FD}\u{145FE}\u{145FF}\u{14600}\u{14601}\u{14602}\u{14603}\u{14604}\u{14605}\u{14606}\u{14607}\u{14608}\u{14609}\u{1460A}\u{1460B}\u{1460C}\u{1460D}\u{1460E}\u{1460F}\u{14610}\u{14611}\u{14612}\u{14613}\u{14614}\u{14615}\u{14616}\u{14617}\u{14618}\u{14619}\u{1461A}\u{1461B}\u{1461C}\u{1461D}\u{1461E}\u{1461F}\u{14620}\u{14621}\u{14622}\u{14623}\u{14624}\u{14625}\u{14626}\u{14627}\u{14628}\u{14629}\u{1462A}\u{1462B}\u{1462C}\u{1462D}\u{1462E}\u{1462F}\u{14630}\u{14631}\u{14632}\u{14633}\u{14634}\u{14635}\u{14636}\u{14637}\u{14638}\u{14639}\u{1463A}\u{1463B}\u{1463C}\u{1463D}\u{1463E}\u{1463F}\u{14640}\u{14641}\u{14642}\u{14643}\u{14644}\u{14645}\u{14646}\u{2B820}\u{2B821}\u{2B822}\u{2B823}\u{2B824}\u{2B825}\u{2B826}\u{2B827}\u{2B828}\u{2B829}\u{2B82A}\u{2B82B}\u{2B82C}\u{2B82D}\u{2B82E}\u{2B82F}\u{2B830}\u{2B831}\u{2B832}\u{2B833}\u{2B834}\u{2B835}\u{2B836}\u{2B837}\u{2B838}\u{2B839}\u{2B83A}\u{2B83B}\u{2B83C}\u{2B83D}\u{2B83E}\u{2B83F}\u{2B840}\u{2B841}\u{2B842}\u{2B843}\u{2B844}\u{2B845}\u{2B846}\u{2B847}\u{2B848}\u{2B849}\u{2B84A}\u{2B84B}\u{2B84C}\u{2B84D}\u{2B84E}\u{2B84F}\u{2B850}\u{2B851}\u{2B852}\u{2B853}\u{2B854}\u{2B855}\u{2B856}\u{2B857}\u{2B858}\u{2B859}\u{2B85A}\u{2B85B}\u{2B85C}\u{2B85D}\u{2B85E}\u{2B85F}\u{2B860}\u{2B861}\u{2B862}\u{2B863}\u{2B864}\u{2B865}\u{2B866}\u{2B867}\u{2B868}\u{2B869}\u{2B86A}\u{2B86B}\u{2B86C}\u{2B86D}\u{2B86E}\u{2B86F}\u{2B870}\u{2B871}\u{2B872}\u{2B873}\u{2B874}\u{2B875}\u{2B876}\u{2B877}\u{2B878}\u{2B879}\u{2B87A}\u{2B87B}\u{2B87C}\u{2B87D}\u{2B87E}\u{2B87F}\u{2B880}\u{2B881}\u{2B882}\u{2B883}\u{2B884}\u{2B885}\u{2B886}\u{2B887}\u{2B888}\u{2B889}\u{2B88A}\u{2B88B}\u{2B88C}\u{2B88D}\u{2B88E}\u{2B88F}\u{2B890}\u{2B891}\u{2B892}\u{2B893}\u{2B894}\u{2B895}\u{2B896}\u{2B897}\u{2B898}\u{2B899}\u{2B89A}\u{2B89B}\u{2B89C}\u{2B89D}\u{2B89E}\u{2B89F}\u{2B8A0}\u{2B8A1}\u{2B8A2}\u{2B8A3}\u{2B8A4}\u{2B8A5}\u{2B8A6}\u{2B8A7}\u{2B8A8}\u{2B8A9}\u{2B8AA}\u{2B8AB}\u{2B8AC}\u{2B8AD}\u{2B8AE}\u{2B8AF}\u{2B8B0}\u{2B8B1}\u{2B8B2}\u{2B8B3}\u{2B8B4}\u{2B8B5}\u{2B8B6}\u{2B8B7}\u{2B8B8}\u{2B8B9}\u{2B8BA}\u{2B8BB}\u{2B8BC}\u{2B8BD}\u{2B8BE}\u{2B8BF}\u{2B8C0}\u{2B8C1}\u{2B8C2}\u{2B8C3}\u{2B8C4}\u{2B8C5}\u{2B8C6}\u{2B8C7}\u{2B8C8}\u{2B8C9}\u{2B8CA}\u{2B8CB}\u{2B8CC}\u{2B8CD}\u{2B8CE}\u{2B8CF}\u{2B8D0}\u{2B8D1}\u{2B8D2}\u{2B8D3}\u{2B8D4}\u{2B8D5}\u{2B8D6}\u{2B8D7}\u{2B8D8}\u{2B8D9}\u{2B8DA}\u{2B8DB}\u{2B8DC}\u{2B8DD}\u{2B8DE}\u{2B8DF}\u{2B8E0}\u{2B8E1}\u{2B8E2}\u{2B8E3}\u{2B8E4}\u{2B8E5}\u{2B8E6}\u{2B8E7}\u{2B8E8}\u{2B8E9}\u{2B8EA}\u{2B8EB}\u{2B8EC}\u{2B8ED}\u{2B8EE}\u{2B8EF}\u{2B8F0}\u{2B8F1}\u{2B8F2}\u{2B8F3}\u{2B8F4}\u{2B8F5}\u{2B8F6}\u{2B8F7}\u{2B8F8}\u{2B8F9}\u{2B8FA}\u{2B8FB}\u{2B8FC}\u{2B8FD}\u{2B8FE}\u{2B8FF}\u{2B900}\u{2B901}\u{2B902}\u{2B903}\u{2B904}\u{2B905}\u{2B906}\u{2B907}\u{2B908}\u{2B909}\u{2B90A}\u{2B90B}\u{2B90C}\u{2B90D}\u{2B90E}\u{2B90F}\u{2B910}\u{2B911}\u{2B912}\u{2B913}\u{2B914}\u{2B915}\u{2B916}\u{2B917}\u{2B918}\u{2B919}\u{2B91A}\u{2B91B}\u{2B91C}\u{2B91D}\u{2B91E}\u{2B91F}\u{2B920}\u{2B921}\u{2B922}\u{2B923}\u{2B924}\u{2B925}\u{2B926}\u{2B927}\u{2B928}\u{2B929}\u{2B92A}\u{2B92B}\u{2B92C}\u{2B92D}\u{2B92E}\u{2B92F}\u{2B930}\u{2B931}\u{2B932}\u{2B933}\u{2B934}\u{2B935}\u{2B936}\u{2B937}\u{2B938}\u{2B939}\u{2B93A}\u{2B93B}\u{2B93C}\u{2B93D}\u{2B93E}\u{2B93F}\u{2B940}\u{2B941}\u{2B942}\u{2B943}\u{2B944}\u{2B945}\u{2B946}\u{2B947}\u{2B948}\u{2B949}\u{2B94A}\u{2B94B}\u{2B94C}\u{2B94D}\u{2B94E}\u{2B94F}\u{2B950}\u{2B951}\u{2B952}\u{2B953}\u{2B954}\u{2B955}\u{2B956}\u{2B957}\u{2B958}\u{2B959}\u{2B95A}\u{2B95B}\u{2B95C}\u{2B95D}\u{2B95E}\u{2B95F}\u{2B960}\u{2B961}\u{2B962}\u{2B963}\u{2B964}\u{2B965}\u{2B966}\u{2B967}\u{2B968}\u{2B969}\u{2B96A}\u{2B96B}\u{2B96C}\u{2B96D}\u{2B96E}\u{2B96F}\u{2B970}\u{2B971}\u{2B972}\u{2B973}\u{2B974}\u{2B975}\u{2B976}\u{2B977}\u{2B978}\u{2B979}\u{2B97A}\u{2B97B}\u{2B97C}\u{2B97D}\u{2B97E}\u{2B97F}\u{2B980}\u{2B981}\u{2B982}\u{2B983}\u{2B984}\u{2B985}\u{2B986}\u{2B987}\u{2B988}\u{2B989}\u{2B98A}\u{2B98B}\u{2B98C}\u{2B98D}\u{2B98E}\u{2B98F}\u{2B990}\u{2B991}\u{2B992}\u{2B993}\u{2B994}\u{2B995}\u{2B996}\u{2B997}\u{2B998}\u{2B999}\u{2B99A}\u{2B99B}\u{2B99C}\u{2B99D}\u{2B99E}\u{2B99F}\u{2B9A0}\u{2B9A1}\u{2B9A2}\u{2B9A3}\u{2B9A4}\u{2B9A5}\u{2B9A6}\u{2B9A7}\u{2B9A8}\u{2B9A9}\u{2B9AA}\u{2B9AB}\u{2B9AC}\u{2B9AD}\u{2B9AE}\u{2B9AF}\u{2B9B0}\u{2B9B1}\u{2B9B2}\u{2B9B3}\u{2B9B4}\u{2B9B5}\u{2B9B6}\u{2B9B7}\u{2B9B8}\u{2B9B9}\u{2B9BA}\u{2B9BB}\u{2B9BC}\u{2B9BD}\u{2B9BE}\u{2B9BF}\u{2B9C0}\u{2B9C1}\u{2B9C2}\u{2B9C3}\u{2B9C4}\u{2B9C5}\u{2B9C6}\u{2B9C7}\u{2B9C8}\u{2B9C9}\u{2B9CA}\u{2B9CB}\u{2B9CC}\u{2B9CD}\u{2B9CE}\u{2B9CF}\u{2B9D0}\u{2B9D1}\u{2B9D2}\u{2B9D3}\u{2B9D4}\u{2B9D5}\u{2B9D6}\u{2B9D7}\u{2B9D8}\u{2B9D9}\u{2B9DA}\u{2B9DB}\u{2B9DC}\u{2B9DD}\u{2B9DE}\u{2B9DF}\u{2B9E0}\u{2B9E1}\u{2B9E2}\u{2B9E3}\u{2B9E4}\u{2B9E5}\u{2B9E6}\u{2B9E7}\u{2B9E8}\u{2B9E9}\u{2B9EA}\u{2B9EB}\u{2B9EC}\u{2B9ED}\u{2B9EE}\u{2B9EF}\u{2B9F0}\u{2B9F1}\u{2B9F2}\u{2B9F3}\u{2B9F4}\u{2B9F5}\u{2B9F6}\u{2B9F7}\u{2B9F8}\u{2B9F9}\u{2B9FA}\u{2B9FB}\u{2B9FC}\u{2B9FD}\u{2B9FE}\u{2B9FF}\u{2BA00}\u{2BA01}\u{2BA02}\u{2BA03}\u{2BA04}\u{2BA05}\u{2BA06}\u{2BA07}\u{2BA08}\u{2BA09}\u{2BA0A}\u{2BA0B}\u{2BA0C}\u{2BA0D}\u{2BA0E}\u{2BA0F}\u{2BA10}\u{2BA11}\u{2BA12}\u{2BA13}\u{2BA14}\u{2BA15}\u{2BA16}\u{2BA17}\u{2BA18}\u{2BA19}\u{2BA1A}\u{2BA1B}\u{2BA1C}\u{2BA1D}\u{2BA1E}\u{2BA1F}\u{2BA20}\u{2BA21}\u{2BA22}\u{2BA23}\u{2BA24}\u{2BA25}\u{2BA26}\u{2BA27}\u{2BA28}\u{2BA29}\u{2BA2A}\u{2BA2B}\u{2BA2C}\u{2BA2D}\u{2BA2E}\u{2BA2F}\u{2BA30}\u{2BA31}\u{2BA32}\u{2BA33}\u{2BA34}\u{2BA35}\u{2BA36}\u{2BA37}\u{2BA38}\u{2BA39}\u{2BA3A}\u{2BA3B}\u{2BA3C}\u{2BA3D}\u{2BA3E}\u{2BA3F}\u{2BA40}\u{2BA41}\u{2BA42}\u{2BA43}\u{2BA44}\u{2BA45}\u{2BA46}\u{2BA47}\u{2BA48}\u{2BA49}\u{2BA4A}\u{2BA4B}\u{2BA4C}\u{2BA4D}\u{2BA4E}\u{2BA4F}\u{2BA50}\u{2BA51}\u{2BA52}\u{2BA53}\u{2BA54}\u{2BA55}\u{2BA56}\u{2BA57}\u{2BA58}\u{2BA59}\u{2BA5A}\u{2BA5B}\u{2BA5C}\u{2BA5D}\u{2BA5E}\u{2BA5F}\u{2BA60}\u{2BA61}\u{2BA62}\u{2BA63}\u{2BA64}\u{2BA65}\u{2BA66}\u{2BA67}\u{2BA68}\u{2BA69}\u{2BA6A}\u{2BA6B}\u{2BA6C}\u{2BA6D}\u{2BA6E}\u{2BA6F}\u{2BA70}\u{2BA71}\u{2BA72}\u{2BA73}\u{2BA74}\u{2BA75}\u{2BA76}\u{2BA77}\u{2BA78}\u{2BA79}\u{2BA7A}\u{2BA7B}\u{2BA7C}\u{2BA7D}\u{2BA7E}\u{2BA7F}\u{2BA80}\u{2BA81}\u{2BA82}\u{2BA83}\u{2BA84}\u{2BA85}\u{2BA86}\u{2BA87}\u{2BA88}\u{2BA89}\u{2BA8A}\u{2BA8B}\u{2BA8C}\u{2BA8D}\u{2BA8E}\u{2BA8F}\u{2BA90}\u{2BA91}\u{2BA92}\u{2BA93}\u{2BA94}\u{2BA95}\u{2BA96}\u{2BA97}\u{2BA98}\u{2BA99}\u{2BA9A}\u{2BA9B}\u{2BA9C}\u{2BA9D}\u{2BA9E}\u{2BA9F}\u{2BAA0}\u{2BAA1}\u{2BAA2}\u{2BAA3}\u{2BAA4}\u{2BAA5}\u{2BAA6}\u{2BAA7}\u{2BAA8}\u{2BAA9}\u{2BAAA}\u{2BAAB}\u{2BAAC}\u{2BAAD}\u{2BAAE}\u{2BAAF}\u{2BAB0}\u{2BAB1}\u{2BAB2}\u{2BAB3}\u{2BAB4}\u{2BAB5}\u{2BAB6}\u{2BAB7}\u{2BAB8}\u{2BAB9}\u{2BABA}\u{2BABB}\u{2BABC}\u{2BABD}\u{2BABE}\u{2BABF}\u{2BAC0}\u{2BAC1}\u{2BAC2}\u{2BAC3}\u{2BAC4}\u{2BAC5}\u{2BAC6}\u{2BAC7}\u{2BAC8}\u{2BAC9}\u{2BACA}\u{2BACB}\u{2BACC}\u{2BACD}\u{2BACE}\u{2BACF}\u{2BAD0}\u{2BAD1}\u{2BAD2}\u{2BAD3}\u{2BAD4}\u{2BAD5}\u{2BAD6}\u{2BAD7}\u{2BAD8}\u{2BAD9}\u{2BADA}\u{2BADB}\u{2BADC}\u{2BADD}\u{2BADE}\u{2BADF}\u{2BAE0}\u{2BAE1}\u{2BAE2}\u{2BAE3}\u{2BAE4}\u{2BAE5}\u{2BAE6}\u{2BAE7}\u{2BAE8}\u{2BAE9}\u{2BAEA}\u{2BAEB}\u{2BAEC}\u{2BAED}\u{2BAEE}\u{2BAEF}\u{2BAF0}\u{2BAF1}\u{2BAF2}\u{2BAF3}\u{2BAF4}\u{2BAF5}\u{2BAF6}\u{2BAF7}\u{2BAF8}\u{2BAF9}\u{2BAFA}\u{2BAFB}\u{2BAFC}\u{2BAFD}\u{2BAFE}\u{2BAFF}\u{2BB00}\u{2BB01}\u{2BB02}\u{2BB03}\u{2BB04}\u{2BB05}\u{2BB06}\u{2BB07}\u{2BB08}\u{2BB09}\u{2BB0A}\u{2BB0B}\u{2BB0C}\u{2BB0D}\u{2BB0E}\u{2BB0F}\u{2BB10}\u{2BB11}\u{2BB12}\u{2BB13}\u{2BB14}\u{2BB15}\u{2BB16}\u{2BB17}\u{2BB18}\u{2BB19}\u{2BB1A}\u{2BB1B}\u{2BB1C}\u{2BB1D}\u{2BB1E}\u{2BB1F}\u{2BB20}\u{2BB21}\u{2BB22}\u{2BB23}\u{2BB24}\u{2BB25}\u{2BB26}\u{2BB27}\u{2BB28}\u{2BB29}\u{2BB2A}\u{2BB2B}\u{2BB2C}\u{2BB2D}\u{2BB2E}\u{2BB2F}\u{2BB30}\u{2BB31}\u{2BB32}\u{2BB33}\u{2BB34}\u{2BB35}\u{2BB36}\u{2BB37}\u{2BB38}\u{2BB39}\u{2BB3A}\u{2BB3B}\u{2BB3C}\u{2BB3D}\u{2BB3E}\u{2BB3F}\u{2BB40}\u{2BB41}\u{2BB42}\u{2BB43}\u{2BB44}\u{2BB45}\u{2BB46}\u{2BB47}\u{2BB48}\u{2BB49}\u{2BB4A}\u{2BB4B}\u{2BB4C}\u{2BB4D}\u{2BB4E}\u{2BB4F}\u{2BB50}\u{2BB51}\u{2BB52}\u{2BB53}\u{2BB54}\u{2BB55}\u{2BB56}\u{2BB57}\u{2BB58}\u{2BB59}\u{2BB5A}\u{2BB5B}\u{2BB5C}\u{2BB5D}\u{2BB5E}\u{2BB5F}\u{2BB60}\u{2BB61}\u{2BB62}\u{2BB63}\u{2BB64}\u{2BB65}\u{2BB66}\u{2BB67}\u{2BB68}\u{2BB69}\u{2BB6A}\u{2BB6B}\u{2BB6C}\u{2BB6D}\u{2BB6E}\u{2BB6F}\u{2BB70}\u{2BB71}\u{2BB72}\u{2BB73}\u{2BB74}\u{2BB75}\u{2BB76}\u{2BB77}\u{2BB78}\u{2BB79}\u{2BB7A}\u{2BB7B}\u{2BB7C}\u{2BB7D}\u{2BB7E}\u{2BB7F}\u{2BB80}\u{2BB81}\u{2BB82}\u{2BB83}\u{2BB84}\u{2BB85}\u{2BB86}\u{2BB87}\u{2BB88}\u{2BB89}\u{2BB8A}\u{2BB8B}\u{2BB8C}\u{2BB8D}\u{2BB8E}\u{2BB8F}\u{2BB90}\u{2BB91}\u{2BB92}\u{2BB93}\u{2BB94}\u{2BB95}\u{2BB96}\u{2BB97}\u{2BB98}\u{2BB99}\u{2BB9A}\u{2BB9B}\u{2BB9C}\u{2BB9D}\u{2BB9E}\u{2BB9F}\u{2BBA0}\u{2BBA1}\u{2BBA2}\u{2BBA3}\u{2BBA4}\u{2BBA5}\u{2BBA6}\u{2BBA7}\u{2BBA8}\u{2BBA9}\u{2BBAA}\u{2BBAB}\u{2BBAC}\u{2BBAD}\u{2BBAE}\u{2BBAF}\u{2BBB0}\u{2BBB1}\u{2BBB2}\u{2BBB3}\u{2BBB4}\u{2BBB5}\u{2BBB6}\u{2BBB7}\u{2BBB8}\u{2BBB9}\u{2BBBA}\u{2BBBB}\u{2BBBC}\u{2BBBD}\u{2BBBE}\u{2BBBF}\u{2BBC0}\u{2BBC1}\u{2BBC2}\u{2BBC3}\u{2BBC4}\u{2BBC5}\u{2BBC6}\u{2BBC7}\u{2BBC8}\u{2BBC9}\u{2BBCA}\u{2BBCB}\u{2BBCC}\u{2BBCD}\u{2BBCE}\u{2BBCF}\u{2BBD0}\u{2BBD1}\u{2BBD2}\u{2BBD3}\u{2BBD4}\u{2BBD5}\u{2BBD6}\u{2BBD7}\u{2BBD8}\u{2BBD9}\u{2BBDA}\u{2BBDB}\u{2BBDC}\u{2BBDD}\u{2BBDE}\u{2BBDF}\u{2BBE0}\u{2BBE1}\u{2BBE2}\u{2BBE3}\u{2BBE4}\u{2BBE5}\u{2BBE6}\u{2BBE7}\u{2BBE8}\u{2BBE9}\u{2BBEA}\u{2BBEB}\u{2BBEC}\u{2BBED}\u{2BBEE}\u{2BBEF}\u{2BBF0}\u{2BBF1}\u{2BBF2}\u{2BBF3}\u{2BBF4}\u{2BBF5}\u{2BBF6}\u{2BBF7}\u{2BBF8}\u{2BBF9}\u{2BBFA}\u{2BBFB}\u{2BBFC}\u{2BBFD}\u{2BBFE}\u{2BBFF}\u{2BC00}\u{2BC01}\u{2BC02}\u{2BC03}\u{2BC04}\u{2BC05}\u{2BC06}\u{2BC07}\u{2BC08}\u{2BC09}\u{2BC0A}\u{2BC0B}\u{2BC0C}\u{2BC0D}\u{2BC0E}\u{2BC0F}\u{2BC10}\u{2BC11}\u{2BC12}\u{2BC13}\u{2BC14}\u{2BC15}\u{2BC16}\u{2BC17}\u{2BC18}\u{2BC19}\u{2BC1A}\u{2BC1B}\u{2BC1C}\u{2BC1D}\u{2BC1E}\u{2BC1F}\u{2BC20}\u{2BC21}\u{2BC22}\u{2BC23}\u{2BC24}\u{2BC25}\u{2BC26}\u{2BC27}\u{2BC28}\u{2BC29}\u{2BC2A}\u{2BC2B}\u{2BC2C}\u{2BC2D}\u{2BC2E}\u{2BC2F}\u{2BC30}\u{2BC31}\u{2BC32}\u{2BC33}\u{2BC34}\u{2BC35}\u{2BC36}\u{2BC37}\u{2BC38}\u{2BC39}\u{2BC3A}\u{2BC3B}\u{2BC3C}\u{2BC3D}\u{2BC3E}\u{2BC3F}\u{2BC40}\u{2BC41}\u{2BC42}\u{2BC43}\u{2BC44}\u{2BC45}\u{2BC46}\u{2BC47}\u{2BC48}\u{2BC49}\u{2BC4A}\u{2BC4B}\u{2BC4C}\u{2BC4D}\u{2BC4E}\u{2BC4F}\u{2BC50}\u{2BC51}\u{2BC52}\u{2BC53}\u{2BC54}\u{2BC55}\u{2BC56}\u{2BC57}\u{2BC58}\u{2BC59}\u{2BC5A}\u{2BC5B}\u{2BC5C}\u{2BC5D}\u{2BC5E}\u{2BC5F}\u{2BC60}\u{2BC61}\u{2BC62}\u{2BC63}\u{2BC64}\u{2BC65}\u{2BC66}\u{2BC67}\u{2BC68}\u{2BC69}\u{2BC6A}\u{2BC6B}\u{2BC6C}\u{2BC6D}\u{2BC6E}\u{2BC6F}\u{2BC70}\u{2BC71}\u{2BC72}\u{2BC73}\u{2BC74}\u{2BC75}\u{2BC76}\u{2BC77}\u{2BC78}\u{2BC79}\u{2BC7A}\u{2BC7B}\u{2BC7C}\u{2BC7D}\u{2BC7E}\u{2BC7F}\u{2BC80}\u{2BC81}\u{2BC82}\u{2BC83}\u{2BC84}\u{2BC85}\u{2BC86}\u{2BC87}\u{2BC88}\u{2BC89}\u{2BC8A}\u{2BC8B}\u{2BC8C}\u{2BC8D}\u{2BC8E}\u{2BC8F}\u{2BC90}\u{2BC91}\u{2BC92}\u{2BC93}\u{2BC94}\u{2BC95}\u{2BC96}\u{2BC97}\u{2BC98}\u{2BC99}\u{2BC9A}\u{2BC9B}\u{2BC9C}\u{2BC9D}\u{2BC9E}\u{2BC9F}\u{2BCA0}\u{2BCA1}\u{2BCA2}\u{2BCA3}\u{2BCA4}\u{2BCA5}\u{2BCA6}\u{2BCA7}\u{2BCA8}\u{2BCA9}\u{2BCAA}\u{2BCAB}\u{2BCAC}\u{2BCAD}\u{2BCAE}\u{2BCAF}\u{2BCB0}\u{2BCB1}\u{2BCB2}\u{2BCB3}\u{2BCB4}\u{2BCB5}\u{2BCB6}\u{2BCB7}\u{2BCB8}\u{2BCB9}\u{2BCBA}\u{2BCBB}\u{2BCBC}\u{2BCBD}\u{2BCBE}\u{2BCBF}\u{2BCC0}\u{2BCC1}\u{2BCC2}\u{2BCC3}\u{2BCC4}\u{2BCC5}\u{2BCC6}\u{2BCC7}\u{2BCC8}\u{2BCC9}\u{2BCCA}\u{2BCCB}\u{2BCCC}\u{2BCCD}\u{2BCCE}\u{2BCCF}\u{2BCD0}\u{2BCD1}\u{2BCD2}\u{2BCD3}\u{2BCD4}\u{2BCD5}\u{2BCD6}\u{2BCD7}\u{2BCD8}\u{2BCD9}\u{2BCDA}\u{2BCDB}\u{2BCDC}\u{2BCDD}\u{2BCDE}\u{2BCDF}\u{2BCE0}\u{2BCE1}\u{2BCE2}\u{2BCE3}\u{2BCE4}\u{2BCE5}\u{2BCE6}\u{2BCE7}\u{2BCE8}\u{2BCE9}\u{2BCEA}\u{2BCEB}\u{2BCEC}\u{2BCED}\u{2BCEE}\u{2BCEF}\u{2BCF0}\u{2BCF1}\u{2BCF2}\u{2BCF3}\u{2BCF4}\u{2BCF5}\u{2BCF6}\u{2BCF7}\u{2BCF8}\u{2BCF9}\u{2BCFA}\u{2BCFB}\u{2BCFC}\u{2BCFD}\u{2BCFE}\u{2BCFF}\u{2BD00}\u{2BD01}\u{2BD02}\u{2BD03}\u{2BD04}\u{2BD05}\u{2BD06}\u{2BD07}\u{2BD08}\u{2BD09}\u{2BD0A}\u{2BD0B}\u{2BD0C}\u{2BD0D}\u{2BD0E}\u{2BD0F}\u{2BD10}\u{2BD11}\u{2BD12}\u{2BD13}\u{2BD14}\u{2BD15}\u{2BD16}\u{2BD17}\u{2BD18}\u{2BD19}\u{2BD1A}\u{2BD1B}\u{2BD1C}\u{2BD1D}\u{2BD1E}\u{2BD1F}\u{2BD20}\u{2BD21}\u{2BD22}\u{2BD23}\u{2BD24}\u{2BD25}\u{2BD26}\u{2BD27}\u{2BD28}\u{2BD29}\u{2BD2A}\u{2BD2B}\u{2BD2C}\u{2BD2D}\u{2BD2E}\u{2BD2F}\u{2BD30}\u{2BD31}\u{2BD32}\u{2BD33}\u{2BD34}\u{2BD35}\u{2BD36}\u{2BD37}\u{2BD38}\u{2BD39}\u{2BD3A}\u{2BD3B}\u{2BD3C}\u{2BD3D}\u{2BD3E}\u{2BD3F}\u{2BD40}\u{2BD41}\u{2BD42}\u{2BD43}\u{2BD44}\u{2BD45}\u{2BD46}\u{2BD47}\u{2BD48}\u{2BD49}\u{2BD4A}\u{2BD4B}\u{2BD4C}\u{2BD4D}\u{2BD4E}\u{2BD4F}\u{2BD50}\u{2BD51}\u{2BD52}\u{2BD53}\u{2BD54}\u{2BD55}\u{2BD56}\u{2BD57}\u{2BD58}\u{2BD59}\u{2BD5A}\u{2BD5B}\u{2BD5C}\u{2BD5D}\u{2BD5E}\u{2BD5F}\u{2BD60}\u{2BD61}\u{2BD62}\u{2BD63}\u{2BD64}\u{2BD65}\u{2BD66}\u{2BD67}\u{2BD68}\u{2BD69}\u{2BD6A}\u{2BD6B}\u{2BD6C}\u{2BD6D}\u{2BD6E}\u{2BD6F}\u{2BD70}\u{2BD71}\u{2BD72}\u{2BD73}\u{2BD74}\u{2BD75}\u{2BD76}\u{2BD77}\u{2BD78}\u{2BD79}\u{2BD7A}\u{2BD7B}\u{2BD7C}\u{2BD7D}\u{2BD7E}\u{2BD7F}\u{2BD80}\u{2BD81}\u{2BD82}\u{2BD83}\u{2BD84}\u{2BD85}\u{2BD86}\u{2BD87}\u{2BD88}\u{2BD89}\u{2BD8A}\u{2BD8B}\u{2BD8C}\u{2BD8D}\u{2BD8E}\u{2BD8F}\u{2BD90}\u{2BD91}\u{2BD92}\u{2BD93}\u{2BD94}\u{2BD95}\u{2BD96}\u{2BD97}\u{2BD98}\u{2BD99}\u{2BD9A}\u{2BD9B}\u{2BD9C}\u{2BD9D}\u{2BD9E}\u{2BD9F}\u{2BDA0}\u{2BDA1}\u{2BDA2}\u{2BDA3}\u{2BDA4}\u{2BDA5}\u{2BDA6}\u{2BDA7}\u{2BDA8}\u{2BDA9}\u{2BDAA}\u{2BDAB}\u{2BDAC}\u{2BDAD}\u{2BDAE}\u{2BDAF}\u{2BDB0}\u{2BDB1}\u{2BDB2}\u{2BDB3}\u{2BDB4}\u{2BDB5}\u{2BDB6}\u{2BDB7}\u{2BDB8}\u{2BDB9}\u{2BDBA}\u{2BDBB}\u{2BDBC}\u{2BDBD}\u{2BDBE}\u{2BDBF}\u{2BDC0}\u{2BDC1}\u{2BDC2}\u{2BDC3}\u{2BDC4}\u{2BDC5}\u{2BDC6}\u{2BDC7}\u{2BDC8}\u{2BDC9}\u{2BDCA}\u{2BDCB}\u{2BDCC}\u{2BDCD}\u{2BDCE}\u{2BDCF}\u{2BDD0}\u{2BDD1}\u{2BDD2}\u{2BDD3}\u{2BDD4}\u{2BDD5}\u{2BDD6}\u{2BDD7}\u{2BDD8}\u{2BDD9}\u{2BDDA}\u{2BDDB}\u{2BDDC}\u{2BDDD}\u{2BDDE}\u{2BDDF}\u{2BDE0}\u{2BDE1}\u{2BDE2}\u{2BDE3}\u{2BDE4}\u{2BDE5}\u{2BDE6}\u{2BDE7}\u{2BDE8}\u{2BDE9}\u{2BDEA}\u{2BDEB}\u{2BDEC}\u{2BDED}\u{2BDEE}\u{2BDEF}\u{2BDF0}\u{2BDF1}\u{2BDF2}\u{2BDF3}\u{2BDF4}\u{2BDF5}\u{2BDF6}\u{2BDF7}\u{2BDF8}\u{2BDF9}\u{2BDFA}\u{2BDFB}\u{2BDFC}\u{2BDFD}\u{2BDFE}\u{2BDFF}\u{2BE00}\u{2BE01}\u{2BE02}\u{2BE03}\u{2BE04}\u{2BE05}\u{2BE06}\u{2BE07}\u{2BE08}\u{2BE09}\u{2BE0A}\u{2BE0B}\u{2BE0C}\u{2BE0D}\u{2BE0E}\u{2BE0F}\u{2BE10}\u{2BE11}\u{2BE12}\u{2BE13}\u{2BE14}\u{2BE15}\u{2BE16}\u{2BE17}\u{2BE18}\u{2BE19}\u{2BE1A}\u{2BE1B}\u{2BE1C}\u{2BE1D}\u{2BE1E}\u{2BE1F}\u{2BE20}\u{2BE21}\u{2BE22}\u{2BE23}\u{2BE24}\u{2BE25}\u{2BE26}\u{2BE27}\u{2BE28}\u{2BE29}\u{2BE2A}\u{2BE2B}\u{2BE2C}\u{2BE2D}\u{2BE2E}\u{2BE2F}\u{2BE30}\u{2BE31}\u{2BE32}\u{2BE33}\u{2BE34}\u{2BE35}\u{2BE36}\u{2BE37}\u{2BE38}\u{2BE39}\u{2BE3A}\u{2BE3B}\u{2BE3C}\u{2BE3D}\u{2BE3E}\u{2BE3F}\u{2BE40}\u{2BE41}\u{2BE42}\u{2BE43}\u{2BE44}\u{2BE45}\u{2BE46}\u{2BE47}\u{2BE48}\u{2BE49}\u{2BE4A}\u{2BE4B}\u{2BE4C}\u{2BE4D}\u{2BE4E}\u{2BE4F}\u{2BE50}\u{2BE51}\u{2BE52}\u{2BE53}\u{2BE54}\u{2BE55}\u{2BE56}\u{2BE57}\u{2BE58}\u{2BE59}\u{2BE5A}\u{2BE5B}\u{2BE5C}\u{2BE5D}\u{2BE5E}\u{2BE5F}\u{2BE60}\u{2BE61}\u{2BE62}\u{2BE63}\u{2BE64}\u{2BE65}\u{2BE66}\u{2BE67}\u{2BE68}\u{2BE69}\u{2BE6A}\u{2BE6B}\u{2BE6C}\u{2BE6D}\u{2BE6E}\u{2BE6F}\u{2BE70}\u{2BE71}\u{2BE72}\u{2BE73}\u{2BE74}\u{2BE75}\u{2BE76}\u{2BE77}\u{2BE78}\u{2BE79}\u{2BE7A}\u{2BE7B}\u{2BE7C}\u{2BE7D}\u{2BE7E}\u{2BE7F}\u{2BE80}\u{2BE81}\u{2BE82}\u{2BE83}\u{2BE84}\u{2BE85}\u{2BE86}\u{2BE87}\u{2BE88}\u{2BE89}\u{2BE8A}\u{2BE8B}\u{2BE8C}\u{2BE8D}\u{2BE8E}\u{2BE8F}\u{2BE90}\u{2BE91}\u{2BE92}\u{2BE93}\u{2BE94}\u{2BE95}\u{2BE96}\u{2BE97}\u{2BE98}\u{2BE99}\u{2BE9A}\u{2BE9B}\u{2BE9C}\u{2BE9D}\u{2BE9E}\u{2BE9F}\u{2BEA0}\u{2BEA1}\u{2BEA2}\u{2BEA3}\u{2BEA4}\u{2BEA5}\u{2BEA6}\u{2BEA7}\u{2BEA8}\u{2BEA9}\u{2BEAA}\u{2BEAB}\u{2BEAC}\u{2BEAD}\u{2BEAE}\u{2BEAF}\u{2BEB0}\u{2BEB1}\u{2BEB2}\u{2BEB3}\u{2BEB4}\u{2BEB5}\u{2BEB6}\u{2BEB7}\u{2BEB8}\u{2BEB9}\u{2BEBA}\u{2BEBB}\u{2BEBC}\u{2BEBD}\u{2BEBE}\u{2BEBF}\u{2BEC0}\u{2BEC1}\u{2BEC2}\u{2BEC3}\u{2BEC4}\u{2BEC5}\u{2BEC6}\u{2BEC7}\u{2BEC8}\u{2BEC9}\u{2BECA}\u{2BECB}\u{2BECC}\u{2BECD}\u{2BECE}\u{2BECF}\u{2BED0}\u{2BED1}\u{2BED2}\u{2BED3}\u{2BED4}\u{2BED5}\u{2BED6}\u{2BED7}\u{2BED8}\u{2BED9}\u{2BEDA}\u{2BEDB}\u{2BEDC}\u{2BEDD}\u{2BEDE}\u{2BEDF}\u{2BEE0}\u{2BEE1}\u{2BEE2}\u{2BEE3}\u{2BEE4}\u{2BEE5}\u{2BEE6}\u{2BEE7}\u{2BEE8}\u{2BEE9}\u{2BEEA}\u{2BEEB}\u{2BEEC}\u{2BEED}\u{2BEEE}\u{2BEEF}\u{2BEF0}\u{2BEF1}\u{2BEF2}\u{2BEF3}\u{2BEF4}\u{2BEF5}\u{2BEF6}\u{2BEF7}\u{2BEF8}\u{2BEF9}\u{2BEFA}\u{2BEFB}\u{2BEFC}\u{2BEFD}\u{2BEFE}\u{2BEFF}\u{2BF00}\u{2BF01}\u{2BF02}\u{2BF03}\u{2BF04}\u{2BF05}\u{2BF06}\u{2BF07}\u{2BF08}\u{2BF09}\u{2BF0A}\u{2BF0B}\u{2BF0C}\u{2BF0D}\u{2BF0E}\u{2BF0F}\u{2BF10}\u{2BF11}\u{2BF12}\u{2BF13}\u{2BF14}\u{2BF15}\u{2BF16}\u{2BF17}\u{2BF18}\u{2BF19}\u{2BF1A}\u{2BF1B}\u{2BF1C}\u{2BF1D}\u{2BF1E}\u{2BF1F}\u{2BF20}\u{2BF21}\u{2BF22}\u{2BF23}\u{2BF24}\u{2BF25}\u{2BF26}\u{2BF27}\u{2BF28}\u{2BF29}\u{2BF2A}\u{2BF2B}\u{2BF2C}\u{2BF2D}\u{2BF2E}\u{2BF2F}\u{2BF30}\u{2BF31}\u{2BF32}\u{2BF33}\u{2BF34}\u{2BF35}\u{2BF36}\u{2BF37}\u{2BF38}\u{2BF39}\u{2BF3A}\u{2BF3B}\u{2BF3C}\u{2BF3D}\u{2BF3E}\u{2BF3F}\u{2BF40}\u{2BF41}\u{2BF42}\u{2BF43}\u{2BF44}\u{2BF45}\u{2BF46}\u{2BF47}\u{2BF48}\u{2BF49}\u{2BF4A}\u{2BF4B}\u{2BF4C}\u{2BF4D}\u{2BF4E}\u{2BF4F}\u{2BF50}\u{2BF51}\u{2BF52}\u{2BF53}\u{2BF54}\u{2BF55}\u{2BF56}\u{2BF57}\u{2BF58}\u{2BF59}\u{2BF5A}\u{2BF5B}\u{2BF5C}\u{2BF5D}\u{2BF5E}\u{2BF5F}\u{2BF60}\u{2BF61}\u{2BF62}\u{2BF63}\u{2BF64}\u{2BF65}\u{2BF66}\u{2BF67}\u{2BF68}\u{2BF69}\u{2BF6A}\u{2BF6B}\u{2BF6C}\u{2BF6D}\u{2BF6E}\u{2BF6F}\u{2BF70}\u{2BF71}\u{2BF72}\u{2BF73}\u{2BF74}\u{2BF75}\u{2BF76}\u{2BF77}\u{2BF78}\u{2BF79}\u{2BF7A}\u{2BF7B}\u{2BF7C}\u{2BF7D}\u{2BF7E}\u{2BF7F}\u{2BF80}\u{2BF81}\u{2BF82}\u{2BF83}\u{2BF84}\u{2BF85}\u{2BF86}\u{2BF87}\u{2BF88}\u{2BF89}\u{2BF8A}\u{2BF8B}\u{2BF8C}\u{2BF8D}\u{2BF8E}\u{2BF8F}\u{2BF90}\u{2BF91}\u{2BF92}\u{2BF93}\u{2BF94}\u{2BF95}\u{2BF96}\u{2BF97}\u{2BF98}\u{2BF99}\u{2BF9A}\u{2BF9B}\u{2BF9C}\u{2BF9D}\u{2BF9E}\u{2BF9F}\u{2BFA0}\u{2BFA1}\u{2BFA2}\u{2BFA3}\u{2BFA4}\u{2BFA5}\u{2BFA6}\u{2BFA7}\u{2BFA8}\u{2BFA9}\u{2BFAA}\u{2BFAB}\u{2BFAC}\u{2BFAD}\u{2BFAE}\u{2BFAF}\u{2BFB0}\u{2BFB1}\u{2BFB2}\u{2BFB3}\u{2BFB4}\u{2BFB5}\u{2BFB6}\u{2BFB7}\u{2BFB8}\u{2BFB9}\u{2BFBA}\u{2BFBB}\u{2BFBC}\u{2BFBD}\u{2BFBE}\u{2BFBF}\u{2BFC0}\u{2BFC1}\u{2BFC2}\u{2BFC3}\u{2BFC4}\u{2BFC5}\u{2BFC6}\u{2BFC7}\u{2BFC8}\u{2BFC9}\u{2BFCA}\u{2BFCB}\u{2BFCC}\u{2BFCD}\u{2BFCE}\u{2BFCF}\u{2BFD0}\u{2BFD1}\u{2BFD2}\u{2BFD3}\u{2BFD4}\u{2BFD5}\u{2BFD6}\u{2BFD7}\u{2BFD8}\u{2BFD9}\u{2BFDA}\u{2BFDB}\u{2BFDC}\u{2BFDD}\u{2BFDE}\u{2BFDF}\u{2BFE0}\u{2BFE1}\u{2BFE2}\u{2BFE3}\u{2BFE4}\u{2BFE5}\u{2BFE6}\u{2BFE7}\u{2BFE8}\u{2BFE9}\u{2BFEA}\u{2BFEB}\u{2BFEC}\u{2BFED}\u{2BFEE}\u{2BFEF}\u{2BFF0}\u{2BFF1}\u{2BFF2}\u{2BFF3}\u{2BFF4}\u{2BFF5}\u{2BFF6}\u{2BFF7}\u{2BFF8}\u{2BFF9}\u{2BFFA}\u{2BFFB}\u{2BFFC}\u{2BFFD}\u{2BFFE}\u{2BFFF}\u{2C000}\u{2C001}\u{2C002}\u{2C003}\u{2C004}\u{2C005}\u{2C006}\u{2C007}\u{2C008}\u{2C009}\u{2C00A}\u{2C00B}\u{2C00C}\u{2C00D}\u{2C00E}\u{2C00F}\u{2C010}\u{2C011}\u{2C012}\u{2C013}\u{2C014}\u{2C015}\u{2C016}\u{2C017}\u{2C018}\u{2C019}\u{2C01A}\u{2C01B}\u{2C01C}\u{2C01D}\u{2C01E}\u{2C01F}\u{2C020}\u{2C021}\u{2C022}\u{2C023}\u{2C024}\u{2C025}\u{2C026}\u{2C027}\u{2C028}\u{2C029}\u{2C02A}\u{2C02B}\u{2C02C}\u{2C02D}\u{2C02E}\u{2C02F}\u{2C030}\u{2C031}\u{2C032}\u{2C033}\u{2C034}\u{2C035}\u{2C036}\u{2C037}\u{2C038}\u{2C039}\u{2C03A}\u{2C03B}\u{2C03C}\u{2C03D}\u{2C03E}\u{2C03F}\u{2C040}\u{2C041}\u{2C042}\u{2C043}\u{2C044}\u{2C045}\u{2C046}\u{2C047}\u{2C048}\u{2C049}\u{2C04A}\u{2C04B}\u{2C04C}\u{2C04D}\u{2C04E}\u{2C04F}\u{2C050}\u{2C051}\u{2C052}\u{2C053}\u{2C054}\u{2C055}\u{2C056}\u{2C057}\u{2C058}\u{2C059}\u{2C05A}\u{2C05B}\u{2C05C}\u{2C05D}\u{2C05E}\u{2C05F}\u{2C060}\u{2C061}\u{2C062}\u{2C063}\u{2C064}\u{2C065}\u{2C066}\u{2C067}\u{2C068}\u{2C069}\u{2C06A}\u{2C06B}\u{2C06C}\u{2C06D}\u{2C06E}\u{2C06F}\u{2C070}\u{2C071}\u{2C072}\u{2C073}\u{2C074}\u{2C075}\u{2C076}\u{2C077}\u{2C078}\u{2C079}\u{2C07A}\u{2C07B}\u{2C07C}\u{2C07D}\u{2C07E}\u{2C07F}\u{2C080}\u{2C081}\u{2C082}\u{2C083}\u{2C084}\u{2C085}\u{2C086}\u{2C087}\u{2C088}\u{2C089}\u{2C08A}\u{2C08B}\u{2C08C}\u{2C08D}\u{2C08E}\u{2C08F}\u{2C090}\u{2C091}\u{2C092}\u{2C093}\u{2C094}\u{2C095}\u{2C096}\u{2C097}\u{2C098}\u{2C099}\u{2C09A}\u{2C09B}\u{2C09C}\u{2C09D}\u{2C09E}\u{2C09F}\u{2C0A0}\u{2C0A1}\u{2C0A2}\u{2C0A3}\u{2C0A4}\u{2C0A5}\u{2C0A6}\u{2C0A7}\u{2C0A8}\u{2C0A9}\u{2C0AA}\u{2C0AB}\u{2C0AC}\u{2C0AD}\u{2C0AE}\u{2C0AF}\u{2C0B0}\u{2C0B1}\u{2C0B2}\u{2C0B3}\u{2C0B4}\u{2C0B5}\u{2C0B6}\u{2C0B7}\u{2C0B8}\u{2C0B9}\u{2C0BA}\u{2C0BB}\u{2C0BC}\u{2C0BD}\u{2C0BE}\u{2C0BF}\u{2C0C0}\u{2C0C1}\u{2C0C2}\u{2C0C3}\u{2C0C4}\u{2C0C5}\u{2C0C6}\u{2C0C7}\u{2C0C8}\u{2C0C9}\u{2C0CA}\u{2C0CB}\u{2C0CC}\u{2C0CD}\u{2C0CE}\u{2C0CF}\u{2C0D0}\u{2C0D1}\u{2C0D2}\u{2C0D3}\u{2C0D4}\u{2C0D5}\u{2C0D6}\u{2C0D7}\u{2C0D8}\u{2C0D9}\u{2C0DA}\u{2C0DB}\u{2C0DC}\u{2C0DD}\u{2C0DE}\u{2C0DF}\u{2C0E0}\u{2C0E1}\u{2C0E2}\u{2C0E3}\u{2C0E4}\u{2C0E5}\u{2C0E6}\u{2C0E7}\u{2C0E8}\u{2C0E9}\u{2C0EA}\u{2C0EB}\u{2C0EC}\u{2C0ED}\u{2C0EE}\u{2C0EF}\u{2C0F0}\u{2C0F1}\u{2C0F2}\u{2C0F3}\u{2C0F4}\u{2C0F5}\u{2C0F6}\u{2C0F7}\u{2C0F8}\u{2C0F9}\u{2C0FA}\u{2C0FB}\u{2C0FC}\u{2C0FD}\u{2C0FE}\u{2C0FF}\u{2C100}\u{2C101}\u{2C102}\u{2C103}\u{2C104}\u{2C105}\u{2C106}\u{2C107}\u{2C108}\u{2C109}\u{2C10A}\u{2C10B}\u{2C10C}\u{2C10D}\u{2C10E}\u{2C10F}\u{2C110}\u{2C111}\u{2C112}\u{2C113}\u{2C114}\u{2C115}\u{2C116}\u{2C117}\u{2C118}\u{2C119}\u{2C11A}\u{2C11B}\u{2C11C}\u{2C11D}\u{2C11E}\u{2C11F}\u{2C120}\u{2C121}\u{2C122}\u{2C123}\u{2C124}\u{2C125}\u{2C126}\u{2C127}\u{2C128}\u{2C129}\u{2C12A}\u{2C12B}\u{2C12C}\u{2C12D}\u{2C12E}\u{2C12F}\u{2C130}\u{2C131}\u{2C132}\u{2C133}\u{2C134}\u{2C135}\u{2C136}\u{2C137}\u{2C138}\u{2C139}\u{2C13A}\u{2C13B}\u{2C13C}\u{2C13D}\u{2C13E}\u{2C13F}\u{2C140}\u{2C141}\u{2C142}\u{2C143}\u{2C144}\u{2C145}\u{2C146}\u{2C147}\u{2C148}\u{2C149}\u{2C14A}\u{2C14B}\u{2C14C}\u{2C14D}\u{2C14E}\u{2C14F}\u{2C150}\u{2C151}\u{2C152}\u{2C153}\u{2C154}\u{2C155}\u{2C156}\u{2C157}\u{2C158}\u{2C159}\u{2C15A}\u{2C15B}\u{2C15C}\u{2C15D}\u{2C15E}\u{2C15F}\u{2C160}\u{2C161}\u{2C162}\u{2C163}\u{2C164}\u{2C165}\u{2C166}\u{2C167}\u{2C168}\u{2C169}\u{2C16A}\u{2C16B}\u{2C16C}\u{2C16D}\u{2C16E}\u{2C16F}\u{2C170}\u{2C171}\u{2C172}\u{2C173}\u{2C174}\u{2C175}\u{2C176}\u{2C177}\u{2C178}\u{2C179}\u{2C17A}\u{2C17B}\u{2C17C}\u{2C17D}\u{2C17E}\u{2C17F}\u{2C180}\u{2C181}\u{2C182}\u{2C183}\u{2C184}\u{2C185}\u{2C186}\u{2C187}\u{2C188}\u{2C189}\u{2C18A}\u{2C18B}\u{2C18C}\u{2C18D}\u{2C18E}\u{2C18F}\u{2C190}\u{2C191}\u{2C192}\u{2C193}\u{2C194}\u{2C195}\u{2C196}\u{2C197}\u{2C198}\u{2C199}\u{2C19A}\u{2C19B}\u{2C19C}\u{2C19D}\u{2C19E}\u{2C19F}\u{2C1A0}\u{2C1A1}\u{2C1A2}\u{2C1A3}\u{2C1A4}\u{2C1A5}\u{2C1A6}\u{2C1A7}\u{2C1A8}\u{2C1A9}\u{2C1AA}\u{2C1AB}\u{2C1AC}\u{2C1AD}\u{2C1AE}\u{2C1AF}\u{2C1B0}\u{2C1B1}\u{2C1B2}\u{2C1B3}\u{2C1B4}\u{2C1B5}\u{2C1B6}\u{2C1B7}\u{2C1B8}\u{2C1B9}\u{2C1BA}\u{2C1BB}\u{2C1BC}\u{2C1BD}\u{2C1BE}\u{2C1BF}\u{2C1C0}\u{2C1C1}\u{2C1C2}\u{2C1C3}\u{2C1C4}\u{2C1C5}\u{2C1C6}\u{2C1C7}\u{2C1C8}\u{2C1C9}\u{2C1CA}\u{2C1CB}\u{2C1CC}\u{2C1CD}\u{2C1CE}\u{2C1CF}\u{2C1D0}\u{2C1D1}\u{2C1D2}\u{2C1D3}\u{2C1D4}\u{2C1D5}\u{2C1D6}\u{2C1D7}\u{2C1D8}\u{2C1D9}\u{2C1DA}\u{2C1DB}\u{2C1DC}\u{2C1DD}\u{2C1DE}\u{2C1DF}\u{2C1E0}\u{2C1E1}\u{2C1E2}\u{2C1E3}\u{2C1E4}\u{2C1E5}\u{2C1E6}\u{2C1E7}\u{2C1E8}\u{2C1E9}\u{2C1EA}\u{2C1EB}\u{2C1EC}\u{2C1ED}\u{2C1EE}\u{2C1EF}\u{2C1F0}\u{2C1F1}\u{2C1F2}\u{2C1F3}\u{2C1F4}\u{2C1F5}\u{2C1F6}\u{2C1F7}\u{2C1F8}\u{2C1F9}\u{2C1FA}\u{2C1FB}\u{2C1FC}\u{2C1FD}\u{2C1FE}\u{2C1FF}\u{2C200}\u{2C201}\u{2C202}\u{2C203}\u{2C204}\u{2C205}\u{2C206}\u{2C207}\u{2C208}\u{2C209}\u{2C20A}\u{2C20B}\u{2C20C}\u{2C20D}\u{2C20E}\u{2C20F}\u{2C210}\u{2C211}\u{2C212}\u{2C213}\u{2C214}\u{2C215}\u{2C216}\u{2C217}\u{2C218}\u{2C219}\u{2C21A}\u{2C21B}\u{2C21C}\u{2C21D}\u{2C21E}\u{2C21F}\u{2C220}\u{2C221}\u{2C222}\u{2C223}\u{2C224}\u{2C225}\u{2C226}\u{2C227}\u{2C228}\u{2C229}\u{2C22A}\u{2C22B}\u{2C22C}\u{2C22D}\u{2C22E}\u{2C22F}\u{2C230}\u{2C231}\u{2C232}\u{2C233}\u{2C234}\u{2C235}\u{2C236}\u{2C237}\u{2C238}\u{2C239}\u{2C23A}\u{2C23B}\u{2C23C}\u{2C23D}\u{2C23E}\u{2C23F}\u{2C240}\u{2C241}\u{2C242}\u{2C243}\u{2C244}\u{2C245}\u{2C246}\u{2C247}\u{2C248}\u{2C249}\u{2C24A}\u{2C24B}\u{2C24C}\u{2C24D}\u{2C24E}\u{2C24F}\u{2C250}\u{2C251}\u{2C252}\u{2C253}\u{2C254}\u{2C255}\u{2C256}\u{2C257}\u{2C258}\u{2C259}\u{2C25A}\u{2C25B}\u{2C25C}\u{2C25D}\u{2C25E}\u{2C25F}\u{2C260}\u{2C261}\u{2C262}\u{2C263}\u{2C264}\u{2C265}\u{2C266}\u{2C267}\u{2C268}\u{2C269}\u{2C26A}\u{2C26B}\u{2C26C}\u{2C26D}\u{2C26E}\u{2C26F}\u{2C270}\u{2C271}\u{2C272}\u{2C273}\u{2C274}\u{2C275}\u{2C276}\u{2C277}\u{2C278}\u{2C279}\u{2C27A}\u{2C27B}\u{2C27C}\u{2C27D}\u{2C27E}\u{2C27F}\u{2C280}\u{2C281}\u{2C282}\u{2C283}\u{2C284}\u{2C285}\u{2C286}\u{2C287}\u{2C288}\u{2C289}\u{2C28A}\u{2C28B}\u{2C28C}\u{2C28D}\u{2C28E}\u{2C28F}\u{2C290}\u{2C291}\u{2C292}\u{2C293}\u{2C294}\u{2C295}\u{2C296}\u{2C297}\u{2C298}\u{2C299}\u{2C29A}\u{2C29B}\u{2C29C}\u{2C29D}\u{2C29E}\u{2C29F}\u{2C2A0}\u{2C2A1}\u{2C2A2}\u{2C2A3}\u{2C2A4}\u{2C2A5}\u{2C2A6}\u{2C2A7}\u{2C2A8}\u{2C2A9}\u{2C2AA}\u{2C2AB}\u{2C2AC}\u{2C2AD}\u{2C2AE}\u{2C2AF}\u{2C2B0}\u{2C2B1}\u{2C2B2}\u{2C2B3}\u{2C2B4}\u{2C2B5}\u{2C2B6}\u{2C2B7}\u{2C2B8}\u{2C2B9}\u{2C2BA}\u{2C2BB}\u{2C2BC}\u{2C2BD}\u{2C2BE}\u{2C2BF}\u{2C2C0}\u{2C2C1}\u{2C2C2}\u{2C2C3}\u{2C2C4}\u{2C2C5}\u{2C2C6}\u{2C2C7}\u{2C2C8}\u{2C2C9}\u{2C2CA}\u{2C2CB}\u{2C2CC}\u{2C2CD}\u{2C2CE}\u{2C2CF}\u{2C2D0}\u{2C2D1}\u{2C2D2}\u{2C2D3}\u{2C2D4}\u{2C2D5}\u{2C2D6}\u{2C2D7}\u{2C2D8}\u{2C2D9}\u{2C2DA}\u{2C2DB}\u{2C2DC}\u{2C2DD}\u{2C2DE}\u{2C2DF}\u{2C2E0}\u{2C2E1}\u{2C2E2}\u{2C2E3}\u{2C2E4}\u{2C2E5}\u{2C2E6}\u{2C2E7}\u{2C2E8}\u{2C2E9}\u{2C2EA}\u{2C2EB}\u{2C2EC}\u{2C2ED}\u{2C2EE}\u{2C2EF}\u{2C2F0}\u{2C2F1}\u{2C2F2}\u{2C2F3}\u{2C2F4}\u{2C2F5}\u{2C2F6}\u{2C2F7}\u{2C2F8}\u{2C2F9}\u{2C2FA}\u{2C2FB}\u{2C2FC}\u{2C2FD}\u{2C2FE}\u{2C2FF}\u{2C300}\u{2C301}\u{2C302}\u{2C303}\u{2C304}\u{2C305}\u{2C306}\u{2C307}\u{2C308}\u{2C309}\u{2C30A}\u{2C30B}\u{2C30C}\u{2C30D}\u{2C30E}\u{2C30F}\u{2C310}\u{2C311}\u{2C312}\u{2C313}\u{2C314}\u{2C315}\u{2C316}\u{2C317}\u{2C318}\u{2C319}\u{2C31A}\u{2C31B}\u{2C31C}\u{2C31D}\u{2C31E}\u{2C31F}\u{2C320}\u{2C321}\u{2C322}\u{2C323}\u{2C324}\u{2C325}\u{2C326}\u{2C327}\u{2C328}\u{2C329}\u{2C32A}\u{2C32B}\u{2C32C}\u{2C32D}\u{2C32E}\u{2C32F}\u{2C330}\u{2C331}\u{2C332}\u{2C333}\u{2C334}\u{2C335}\u{2C336}\u{2C337}\u{2C338}\u{2C339}\u{2C33A}\u{2C33B}\u{2C33C}\u{2C33D}\u{2C33E}\u{2C33F}\u{2C340}\u{2C341}\u{2C342}\u{2C343}\u{2C344}\u{2C345}\u{2C346}\u{2C347}\u{2C348}\u{2C349}\u{2C34A}\u{2C34B}\u{2C34C}\u{2C34D}\u{2C34E}\u{2C34F}\u{2C350}\u{2C351}\u{2C352}\u{2C353}\u{2C354}\u{2C355}\u{2C356}\u{2C357}\u{2C358}\u{2C359}\u{2C35A}\u{2C35B}\u{2C35C}\u{2C35D}\u{2C35E}\u{2C35F}\u{2C360}\u{2C361}\u{2C362}\u{2C363}\u{2C364}\u{2C365}\u{2C366}\u{2C367}\u{2C368}\u{2C369}\u{2C36A}\u{2C36B}\u{2C36C}\u{2C36D}\u{2C36E}\u{2C36F}\u{2C370}\u{2C371}\u{2C372}\u{2C373}\u{2C374}\u{2C375}\u{2C376}\u{2C377}\u{2C378}\u{2C379}\u{2C37A}\u{2C37B}\u{2C37C}\u{2C37D}\u{2C37E}\u{2C37F}\u{2C380}\u{2C381}\u{2C382}\u{2C383}\u{2C384}\u{2C385}\u{2C386}\u{2C387}\u{2C388}\u{2C389}\u{2C38A}\u{2C38B}\u{2C38C}\u{2C38D}\u{2C38E}\u{2C38F}\u{2C390}\u{2C391}\u{2C392}\u{2C393}\u{2C394}\u{2C395}\u{2C396}\u{2C397}\u{2C398}\u{2C399}\u{2C39A}\u{2C39B}\u{2C39C}\u{2C39D}\u{2C39E}\u{2C39F}\u{2C3A0}\u{2C3A1}\u{2C3A2}\u{2C3A3}\u{2C3A4}\u{2C3A5}\u{2C3A6}\u{2C3A7}\u{2C3A8}\u{2C3A9}\u{2C3AA}\u{2C3AB}\u{2C3AC}\u{2C3AD}\u{2C3AE}\u{2C3AF}\u{2C3B0}\u{2C3B1}\u{2C3B2}\u{2C3B3}\u{2C3B4}\u{2C3B5}\u{2C3B6}\u{2C3B7}\u{2C3B8}\u{2C3B9}\u{2C3BA}\u{2C3BB}\u{2C3BC}\u{2C3BD}\u{2C3BE}\u{2C3BF}\u{2C3C0}\u{2C3C1}\u{2C3C2}\u{2C3C3}\u{2C3C4}\u{2C3C5}\u{2C3C6}\u{2C3C7}\u{2C3C8}\u{2C3C9}\u{2C3CA}\u{2C3CB}\u{2C3CC}\u{2C3CD}\u{2C3CE}\u{2C3CF}\u{2C3D0}\u{2C3D1}\u{2C3D2}\u{2C3D3}\u{2C3D4}\u{2C3D5}\u{2C3D6}\u{2C3D7}\u{2C3D8}\u{2C3D9}\u{2C3DA}\u{2C3DB}\u{2C3DC}\u{2C3DD}\u{2C3DE}\u{2C3DF}\u{2C3E0}\u{2C3E1}\u{2C3E2}\u{2C3E3}\u{2C3E4}\u{2C3E5}\u{2C3E6}\u{2C3E7}\u{2C3E8}\u{2C3E9}\u{2C3EA}\u{2C3EB}\u{2C3EC}\u{2C3ED}\u{2C3EE}\u{2C3EF}\u{2C3F0}\u{2C3F1}\u{2C3F2}\u{2C3F3}\u{2C3F4}\u{2C3F5}\u{2C3F6}\u{2C3F7}\u{2C3F8}\u{2C3F9}\u{2C3FA}\u{2C3FB}\u{2C3FC}\u{2C3FD}\u{2C3FE}\u{2C3FF}\u{2C400}\u{2C401}\u{2C402}\u{2C403}\u{2C404}\u{2C405}\u{2C406}\u{2C407}\u{2C408}\u{2C409}\u{2C40A}\u{2C40B}\u{2C40C}\u{2C40D}\u{2C40E}\u{2C40F}\u{2C410}\u{2C411}\u{2C412}\u{2C413}\u{2C414}\u{2C415}\u{2C416}\u{2C417}\u{2C418}\u{2C419}\u{2C41A}\u{2C41B}\u{2C41C}\u{2C41D}\u{2C41E}\u{2C41F}\u{2C420}\u{2C421}\u{2C422}\u{2C423}\u{2C424}\u{2C425}\u{2C426}\u{2C427}\u{2C428}\u{2C429}\u{2C42A}\u{2C42B}\u{2C42C}\u{2C42D}\u{2C42E}\u{2C42F}\u{2C430}\u{2C431}\u{2C432}\u{2C433}\u{2C434}\u{2C435}\u{2C436}\u{2C437}\u{2C438}\u{2C439}\u{2C43A}\u{2C43B}\u{2C43C}\u{2C43D}\u{2C43E}\u{2C43F}\u{2C440}\u{2C441}\u{2C442}\u{2C443}\u{2C444}\u{2C445}\u{2C446}\u{2C447}\u{2C448}\u{2C449}\u{2C44A}\u{2C44B}\u{2C44C}\u{2C44D}\u{2C44E}\u{2C44F}\u{2C450}\u{2C451}\u{2C452}\u{2C453}\u{2C454}\u{2C455}\u{2C456}\u{2C457}\u{2C458}\u{2C459}\u{2C45A}\u{2C45B}\u{2C45C}\u{2C45D}\u{2C45E}\u{2C45F}\u{2C460}\u{2C461}\u{2C462}\u{2C463}\u{2C464}\u{2C465}\u{2C466}\u{2C467}\u{2C468}\u{2C469}\u{2C46A}\u{2C46B}\u{2C46C}\u{2C46D}\u{2C46E}\u{2C46F}\u{2C470}\u{2C471}\u{2C472}\u{2C473}\u{2C474}\u{2C475}\u{2C476}\u{2C477}\u{2C478}\u{2C479}\u{2C47A}\u{2C47B}\u{2C47C}\u{2C47D}\u{2C47E}\u{2C47F}\u{2C480}\u{2C481}\u{2C482}\u{2C483}\u{2C484}\u{2C485}\u{2C486}\u{2C487}\u{2C488}\u{2C489}\u{2C48A}\u{2C48B}\u{2C48C}\u{2C48D}\u{2C48E}\u{2C48F}\u{2C490}\u{2C491}\u{2C492}\u{2C493}\u{2C494}\u{2C495}\u{2C496}\u{2C497}\u{2C498}\u{2C499}\u{2C49A}\u{2C49B}\u{2C49C}\u{2C49D}\u{2C49E}\u{2C49F}\u{2C4A0}\u{2C4A1}\u{2C4A2}\u{2C4A3}\u{2C4A4}\u{2C4A5}\u{2C4A6}\u{2C4A7}\u{2C4A8}\u{2C4A9}\u{2C4AA}\u{2C4AB}\u{2C4AC}\u{2C4AD}\u{2C4AE}\u{2C4AF}\u{2C4B0}\u{2C4B1}\u{2C4B2}\u{2C4B3}\u{2C4B4}\u{2C4B5}\u{2C4B6}\u{2C4B7}\u{2C4B8}\u{2C4B9}\u{2C4BA}\u{2C4BB}\u{2C4BC}\u{2C4BD}\u{2C4BE}\u{2C4BF}\u{2C4C0}\u{2C4C1}\u{2C4C2}\u{2C4C3}\u{2C4C4}\u{2C4C5}\u{2C4C6}\u{2C4C7}\u{2C4C8}\u{2C4C9}\u{2C4CA}\u{2C4CB}\u{2C4CC}\u{2C4CD}\u{2C4CE}\u{2C4CF}\u{2C4D0}\u{2C4D1}\u{2C4D2}\u{2C4D3}\u{2C4D4}\u{2C4D5}\u{2C4D6}\u{2C4D7}\u{2C4D8}\u{2C4D9}\u{2C4DA}\u{2C4DB}\u{2C4DC}\u{2C4DD}\u{2C4DE}\u{2C4DF}\u{2C4E0}\u{2C4E1}\u{2C4E2}\u{2C4E3}\u{2C4E4}\u{2C4E5}\u{2C4E6}\u{2C4E7}\u{2C4E8}\u{2C4E9}\u{2C4EA}\u{2C4EB}\u{2C4EC}\u{2C4ED}\u{2C4EE}\u{2C4EF}\u{2C4F0}\u{2C4F1}\u{2C4F2}\u{2C4F3}\u{2C4F4}\u{2C4F5}\u{2C4F6}\u{2C4F7}\u{2C4F8}\u{2C4F9}\u{2C4FA}\u{2C4FB}\u{2C4FC}\u{2C4FD}\u{2C4FE}\u{2C4FF}\u{2C500}\u{2C501}\u{2C502}\u{2C503}\u{2C504}\u{2C505}\u{2C506}\u{2C507}\u{2C508}\u{2C509}\u{2C50A}\u{2C50B}\u{2C50C}\u{2C50D}\u{2C50E}\u{2C50F}\u{2C510}\u{2C511}\u{2C512}\u{2C513}\u{2C514}\u{2C515}\u{2C516}\u{2C517}\u{2C518}\u{2C519}\u{2C51A}\u{2C51B}\u{2C51C}\u{2C51D}\u{2C51E}\u{2C51F}\u{2C520}\u{2C521}\u{2C522}\u{2C523}\u{2C524}\u{2C525}\u{2C526}\u{2C527}\u{2C528}\u{2C529}\u{2C52A}\u{2C52B}\u{2C52C}\u{2C52D}\u{2C52E}\u{2C52F}\u{2C530}\u{2C531}\u{2C532}\u{2C533}\u{2C534}\u{2C535}\u{2C536}\u{2C537}\u{2C538}\u{2C539}\u{2C53A}\u{2C53B}\u{2C53C}\u{2C53D}\u{2C53E}\u{2C53F}\u{2C540}\u{2C541}\u{2C542}\u{2C543}\u{2C544}\u{2C545}\u{2C546}\u{2C547}\u{2C548}\u{2C549}\u{2C54A}\u{2C54B}\u{2C54C}\u{2C54D}\u{2C54E}\u{2C54F}\u{2C550}\u{2C551}\u{2C552}\u{2C553}\u{2C554}\u{2C555}\u{2C556}\u{2C557}\u{2C558}\u{2C559}\u{2C55A}\u{2C55B}\u{2C55C}\u{2C55D}\u{2C55E}\u{2C55F}\u{2C560}\u{2C561}\u{2C562}\u{2C563}\u{2C564}\u{2C565}\u{2C566}\u{2C567}\u{2C568}\u{2C569}\u{2C56A}\u{2C56B}\u{2C56C}\u{2C56D}\u{2C56E}\u{2C56F}\u{2C570}\u{2C571}\u{2C572}\u{2C573}\u{2C574}\u{2C575}\u{2C576}\u{2C577}\u{2C578}\u{2C579}\u{2C57A}\u{2C57B}\u{2C57C}\u{2C57D}\u{2C57E}\u{2C57F}\u{2C580}\u{2C581}\u{2C582}\u{2C583}\u{2C584}\u{2C585}\u{2C586}\u{2C587}\u{2C588}\u{2C589}\u{2C58A}\u{2C58B}\u{2C58C}\u{2C58D}\u{2C58E}\u{2C58F}\u{2C590}\u{2C591}\u{2C592}\u{2C593}\u{2C594}\u{2C595}\u{2C596}\u{2C597}\u{2C598}\u{2C599}\u{2C59A}\u{2C59B}\u{2C59C}\u{2C59D}\u{2C59E}\u{2C59F}\u{2C5A0}\u{2C5A1}\u{2C5A2}\u{2C5A3}\u{2C5A4}\u{2C5A5}\u{2C5A6}\u{2C5A7}\u{2C5A8}\u{2C5A9}\u{2C5AA}\u{2C5AB}\u{2C5AC}\u{2C5AD}\u{2C5AE}\u{2C5AF}\u{2C5B0}\u{2C5B1}\u{2C5B2}\u{2C5B3}\u{2C5B4}\u{2C5B5}\u{2C5B6}\u{2C5B7}\u{2C5B8}\u{2C5B9}\u{2C5BA}\u{2C5BB}\u{2C5BC}\u{2C5BD}\u{2C5BE}\u{2C5BF}\u{2C5C0}\u{2C5C1}\u{2C5C2}\u{2C5C3}\u{2C5C4}\u{2C5C5}\u{2C5C6}\u{2C5C7}\u{2C5C8}\u{2C5C9}\u{2C5CA}\u{2C5CB}\u{2C5CC}\u{2C5CD}\u{2C5CE}\u{2C5CF}\u{2C5D0}\u{2C5D1}\u{2C5D2}\u{2C5D3}\u{2C5D4}\u{2C5D5}\u{2C5D6}\u{2C5D7}\u{2C5D8}\u{2C5D9}\u{2C5DA}\u{2C5DB}\u{2C5DC}\u{2C5DD}\u{2C5DE}\u{2C5DF}\u{2C5E0}\u{2C5E1}\u{2C5E2}\u{2C5E3}\u{2C5E4}\u{2C5E5}\u{2C5E6}\u{2C5E7}\u{2C5E8}\u{2C5E9}\u{2C5EA}\u{2C5EB}\u{2C5EC}\u{2C5ED}\u{2C5EE}\u{2C5EF}\u{2C5F0}\u{2C5F1}\u{2C5F2}\u{2C5F3}\u{2C5F4}\u{2C5F5}\u{2C5F6}\u{2C5F7}\u{2C5F8}\u{2C5F9}\u{2C5FA}\u{2C5FB}\u{2C5FC}\u{2C5FD}\u{2C5FE}\u{2C5FF}\u{2C600}\u{2C601}\u{2C602}\u{2C603}\u{2C604}\u{2C605}\u{2C606}\u{2C607}\u{2C608}\u{2C609}\u{2C60A}\u{2C60B}\u{2C60C}\u{2C60D}\u{2C60E}\u{2C60F}\u{2C610}\u{2C611}\u{2C612}\u{2C613}\u{2C614}\u{2C615}\u{2C616}\u{2C617}\u{2C618}\u{2C619}\u{2C61A}\u{2C61B}\u{2C61C}\u{2C61D}\u{2C61E}\u{2C61F}\u{2C620}\u{2C621}\u{2C622}\u{2C623}\u{2C624}\u{2C625}\u{2C626}\u{2C627}\u{2C628}\u{2C629}\u{2C62A}\u{2C62B}\u{2C62C}\u{2C62D}\u{2C62E}\u{2C62F}\u{2C630}\u{2C631}\u{2C632}\u{2C633}\u{2C634}\u{2C635}\u{2C636}\u{2C637}\u{2C638}\u{2C639}\u{2C63A}\u{2C63B}\u{2C63C}\u{2C63D}\u{2C63E}\u{2C63F}\u{2C640}\u{2C641}\u{2C642}\u{2C643}\u{2C644}\u{2C645}\u{2C646}\u{2C647}\u{2C648}\u{2C649}\u{2C64A}\u{2C64B}\u{2C64C}\u{2C64D}\u{2C64E}\u{2C64F}\u{2C650}\u{2C651}\u{2C652}\u{2C653}\u{2C654}\u{2C655}\u{2C656}\u{2C657}\u{2C658}\u{2C659}\u{2C65A}\u{2C65B}\u{2C65C}\u{2C65D}\u{2C65E}\u{2C65F}\u{2C660}\u{2C661}\u{2C662}\u{2C663}\u{2C664}\u{2C665}\u{2C666}\u{2C667}\u{2C668}\u{2C669}\u{2C66A}\u{2C66B}\u{2C66C}\u{2C66D}\u{2C66E}\u{2C66F}\u{2C670}\u{2C671}\u{2C672}\u{2C673}\u{2C674}\u{2C675}\u{2C676}\u{2C677}\u{2C678}\u{2C679}\u{2C67A}\u{2C67B}\u{2C67C}\u{2C67D}\u{2C67E}\u{2C67F}\u{2C680}\u{2C681}\u{2C682}\u{2C683}\u{2C684}\u{2C685}\u{2C686}\u{2C687}\u{2C688}\u{2C689}\u{2C68A}\u{2C68B}\u{2C68C}\u{2C68D}\u{2C68E}\u{2C68F}\u{2C690}\u{2C691}\u{2C692}\u{2C693}\u{2C694}\u{2C695}\u{2C696}\u{2C697}\u{2C698}\u{2C699}\u{2C69A}\u{2C69B}\u{2C69C}\u{2C69D}\u{2C69E}\u{2C69F}\u{2C6A0}\u{2C6A1}\u{2C6A2}\u{2C6A3}\u{2C6A4}\u{2C6A5}\u{2C6A6}\u{2C6A7}\u{2C6A8}\u{2C6A9}\u{2C6AA}\u{2C6AB}\u{2C6AC}\u{2C6AD}\u{2C6AE}\u{2C6AF}\u{2C6B0}\u{2C6B1}\u{2C6B2}\u{2C6B3}\u{2C6B4}\u{2C6B5}\u{2C6B6}\u{2C6B7}\u{2C6B8}\u{2C6B9}\u{2C6BA}\u{2C6BB}\u{2C6BC}\u{2C6BD}\u{2C6BE}\u{2C6BF}\u{2C6C0}\u{2C6C1}\u{2C6C2}\u{2C6C3}\u{2C6C4}\u{2C6C5}\u{2C6C6}\u{2C6C7}\u{2C6C8}\u{2C6C9}\u{2C6CA}\u{2C6CB}\u{2C6CC}\u{2C6CD}\u{2C6CE}\u{2C6CF}\u{2C6D0}\u{2C6D1}\u{2C6D2}\u{2C6D3}\u{2C6D4}\u{2C6D5}\u{2C6D6}\u{2C6D7}\u{2C6D8}\u{2C6D9}\u{2C6DA}\u{2C6DB}\u{2C6DC}\u{2C6DD}\u{2C6DE}\u{2C6DF}\u{2C6E0}\u{2C6E1}\u{2C6E2}\u{2C6E3}\u{2C6E4}\u{2C6E5}\u{2C6E6}\u{2C6E7}\u{2C6E8}\u{2C6E9}\u{2C6EA}\u{2C6EB}\u{2C6EC}\u{2C6ED}\u{2C6EE}\u{2C6EF}\u{2C6F0}\u{2C6F1}\u{2C6F2}\u{2C6F3}\u{2C6F4}\u{2C6F5}\u{2C6F6}\u{2C6F7}\u{2C6F8}\u{2C6F9}\u{2C6FA}\u{2C6FB}\u{2C6FC}\u{2C6FD}\u{2C6FE}\u{2C6FF}\u{2C700}\u{2C701}\u{2C702}\u{2C703}\u{2C704}\u{2C705}\u{2C706}\u{2C707}\u{2C708}\u{2C709}\u{2C70A}\u{2C70B}\u{2C70C}\u{2C70D}\u{2C70E}\u{2C70F}\u{2C710}\u{2C711}\u{2C712}\u{2C713}\u{2C714}\u{2C715}\u{2C716}\u{2C717}\u{2C718}\u{2C719}\u{2C71A}\u{2C71B}\u{2C71C}\u{2C71D}\u{2C71E}\u{2C71F}\u{2C720}\u{2C721}\u{2C722}\u{2C723}\u{2C724}\u{2C725}\u{2C726}\u{2C727}\u{2C728}\u{2C729}\u{2C72A}\u{2C72B}\u{2C72C}\u{2C72D}\u{2C72E}\u{2C72F}\u{2C730}\u{2C731}\u{2C732}\u{2C733}\u{2C734}\u{2C735}\u{2C736}\u{2C737}\u{2C738}\u{2C739}\u{2C73A}\u{2C73B}\u{2C73C}\u{2C73D}\u{2C73E}\u{2C73F}\u{2C740}\u{2C741}\u{2C742}\u{2C743}\u{2C744}\u{2C745}\u{2C746}\u{2C747}\u{2C748}\u{2C749}\u{2C74A}\u{2C74B}\u{2C74C}\u{2C74D}\u{2C74E}\u{2C74F}\u{2C750}\u{2C751}\u{2C752}\u{2C753}\u{2C754}\u{2C755}\u{2C756}\u{2C757}\u{2C758}\u{2C759}\u{2C75A}\u{2C75B}\u{2C75C}\u{2C75D}\u{2C75E}\u{2C75F}\u{2C760}\u{2C761}\u{2C762}\u{2C763}\u{2C764}\u{2C765}\u{2C766}\u{2C767}\u{2C768}\u{2C769}\u{2C76A}\u{2C76B}\u{2C76C}\u{2C76D}\u{2C76E}\u{2C76F}\u{2C770}\u{2C771}\u{2C772}\u{2C773}\u{2C774}\u{2C775}\u{2C776}\u{2C777}\u{2C778}\u{2C779}\u{2C77A}\u{2C77B}\u{2C77C}\u{2C77D}\u{2C77E}\u{2C77F}\u{2C780}\u{2C781}\u{2C782}\u{2C783}\u{2C784}\u{2C785}\u{2C786}\u{2C787}\u{2C788}\u{2C789}\u{2C78A}\u{2C78B}\u{2C78C}\u{2C78D}\u{2C78E}\u{2C78F}\u{2C790}\u{2C791}\u{2C792}\u{2C793}\u{2C794}\u{2C795}\u{2C796}\u{2C797}\u{2C798}\u{2C799}\u{2C79A}\u{2C79B}\u{2C79C}\u{2C79D}\u{2C79E}\u{2C79F}\u{2C7A0}\u{2C7A1}\u{2C7A2}\u{2C7A3}\u{2C7A4}\u{2C7A5}\u{2C7A6}\u{2C7A7}\u{2C7A8}\u{2C7A9}\u{2C7AA}\u{2C7AB}\u{2C7AC}\u{2C7AD}\u{2C7AE}\u{2C7AF}\u{2C7B0}\u{2C7B1}\u{2C7B2}\u{2C7B3}\u{2C7B4}\u{2C7B5}\u{2C7B6}\u{2C7B7}\u{2C7B8}\u{2C7B9}\u{2C7BA}\u{2C7BB}\u{2C7BC}\u{2C7BD}\u{2C7BE}\u{2C7BF}\u{2C7C0}\u{2C7C1}\u{2C7C2}\u{2C7C3}\u{2C7C4}\u{2C7C5}\u{2C7C6}\u{2C7C7}\u{2C7C8}\u{2C7C9}\u{2C7CA}\u{2C7CB}\u{2C7CC}\u{2C7CD}\u{2C7CE}\u{2C7CF}\u{2C7D0}\u{2C7D1}\u{2C7D2}\u{2C7D3}\u{2C7D4}\u{2C7D5}\u{2C7D6}\u{2C7D7}\u{2C7D8}\u{2C7D9}\u{2C7DA}\u{2C7DB}\u{2C7DC}\u{2C7DD}\u{2C7DE}\u{2C7DF}\u{2C7E0}\u{2C7E1}\u{2C7E2}\u{2C7E3}\u{2C7E4}\u{2C7E5}\u{2C7E6}\u{2C7E7}\u{2C7E8}\u{2C7E9}\u{2C7EA}\u{2C7EB}\u{2C7EC}\u{2C7ED}\u{2C7EE}\u{2C7EF}\u{2C7F0}\u{2C7F1}\u{2C7F2}\u{2C7F3}\u{2C7F4}\u{2C7F5}\u{2C7F6}\u{2C7F7}\u{2C7F8}\u{2C7F9}\u{2C7FA}\u{2C7FB}\u{2C7FC}\u{2C7FD}\u{2C7FE}\u{2C7FF}\u{2C800}\u{2C801}\u{2C802}\u{2C803}\u{2C804}\u{2C805}\u{2C806}\u{2C807}\u{2C808}\u{2C809}\u{2C80A}\u{2C80B}\u{2C80C}\u{2C80D}\u{2C80E}\u{2C80F}\u{2C810}\u{2C811}\u{2C812}\u{2C813}\u{2C814}\u{2C815}\u{2C816}\u{2C817}\u{2C818}\u{2C819}\u{2C81A}\u{2C81B}\u{2C81C}\u{2C81D}\u{2C81E}\u{2C81F}\u{2C820}\u{2C821}\u{2C822}\u{2C823}\u{2C824}\u{2C825}\u{2C826}\u{2C827}\u{2C828}\u{2C829}\u{2C82A}\u{2C82B}\u{2C82C}\u{2C82D}\u{2C82E}\u{2C82F}\u{2C830}\u{2C831}\u{2C832}\u{2C833}\u{2C834}\u{2C835}\u{2C836}\u{2C837}\u{2C838}\u{2C839}\u{2C83A}\u{2C83B}\u{2C83C}\u{2C83D}\u{2C83E}\u{2C83F}\u{2C840}\u{2C841}\u{2C842}\u{2C843}\u{2C844}\u{2C845}\u{2C846}\u{2C847}\u{2C848}\u{2C849}\u{2C84A}\u{2C84B}\u{2C84C}\u{2C84D}\u{2C84E}\u{2C84F}\u{2C850}\u{2C851}\u{2C852}\u{2C853}\u{2C854}\u{2C855}\u{2C856}\u{2C857}\u{2C858}\u{2C859}\u{2C85A}\u{2C85B}\u{2C85C}\u{2C85D}\u{2C85E}\u{2C85F}\u{2C860}\u{2C861}\u{2C862}\u{2C863}\u{2C864}\u{2C865}\u{2C866}\u{2C867}\u{2C868}\u{2C869}\u{2C86A}\u{2C86B}\u{2C86C}\u{2C86D}\u{2C86E}\u{2C86F}\u{2C870}\u{2C871}\u{2C872}\u{2C873}\u{2C874}\u{2C875}\u{2C876}\u{2C877}\u{2C878}\u{2C879}\u{2C87A}\u{2C87B}\u{2C87C}\u{2C87D}\u{2C87E}\u{2C87F}\u{2C880}\u{2C881}\u{2C882}\u{2C883}\u{2C884}\u{2C885}\u{2C886}\u{2C887}\u{2C888}\u{2C889}\u{2C88A}\u{2C88B}\u{2C88C}\u{2C88D}\u{2C88E}\u{2C88F}\u{2C890}\u{2C891}\u{2C892}\u{2C893}\u{2C894}\u{2C895}\u{2C896}\u{2C897}\u{2C898}\u{2C899}\u{2C89A}\u{2C89B}\u{2C89C}\u{2C89D}\u{2C89E}\u{2C89F}\u{2C8A0}\u{2C8A1}\u{2C8A2}\u{2C8A3}\u{2C8A4}\u{2C8A5}\u{2C8A6}\u{2C8A7}\u{2C8A8}\u{2C8A9}\u{2C8AA}\u{2C8AB}\u{2C8AC}\u{2C8AD}\u{2C8AE}\u{2C8AF}\u{2C8B0}\u{2C8B1}\u{2C8B2}\u{2C8B3}\u{2C8B4}\u{2C8B5}\u{2C8B6}\u{2C8B7}\u{2C8B8}\u{2C8B9}\u{2C8BA}\u{2C8BB}\u{2C8BC}\u{2C8BD}\u{2C8BE}\u{2C8BF}\u{2C8C0}\u{2C8C1}\u{2C8C2}\u{2C8C3}\u{2C8C4}\u{2C8C5}\u{2C8C6}\u{2C8C7}\u{2C8C8}\u{2C8C9}\u{2C8CA}\u{2C8CB}\u{2C8CC}\u{2C8CD}\u{2C8CE}\u{2C8CF}\u{2C8D0}\u{2C8D1}\u{2C8D2}\u{2C8D3}\u{2C8D4}\u{2C8D5}\u{2C8D6}\u{2C8D7}\u{2C8D8}\u{2C8D9}\u{2C8DA}\u{2C8DB}\u{2C8DC}\u{2C8DD}\u{2C8DE}\u{2C8DF}\u{2C8E0}\u{2C8E1}\u{2C8E2}\u{2C8E3}\u{2C8E4}\u{2C8E5}\u{2C8E6}\u{2C8E7}\u{2C8E8}\u{2C8E9}\u{2C8EA}\u{2C8EB}\u{2C8EC}\u{2C8ED}\u{2C8EE}\u{2C8EF}\u{2C8F0}\u{2C8F1}\u{2C8F2}\u{2C8F3}\u{2C8F4}\u{2C8F5}\u{2C8F6}\u{2C8F7}\u{2C8F8}\u{2C8F9}\u{2C8FA}\u{2C8FB}\u{2C8FC}\u{2C8FD}\u{2C8FE}\u{2C8FF}\u{2C900}\u{2C901}\u{2C902}\u{2C903}\u{2C904}\u{2C905}\u{2C906}\u{2C907}\u{2C908}\u{2C909}\u{2C90A}\u{2C90B}\u{2C90C}\u{2C90D}\u{2C90E}\u{2C90F}\u{2C910}\u{2C911}\u{2C912}\u{2C913}\u{2C914}\u{2C915}\u{2C916}\u{2C917}\u{2C918}\u{2C919}\u{2C91A}\u{2C91B}\u{2C91C}\u{2C91D}\u{2C91E}\u{2C91F}\u{2C920}\u{2C921}\u{2C922}\u{2C923}\u{2C924}\u{2C925}\u{2C926}\u{2C927}\u{2C928}\u{2C929}\u{2C92A}\u{2C92B}\u{2C92C}\u{2C92D}\u{2C92E}\u{2C92F}\u{2C930}\u{2C931}\u{2C932}\u{2C933}\u{2C934}\u{2C935}\u{2C936}\u{2C937}\u{2C938}\u{2C939}\u{2C93A}\u{2C93B}\u{2C93C}\u{2C93D}\u{2C93E}\u{2C93F}\u{2C940}\u{2C941}\u{2C942}\u{2C943}\u{2C944}\u{2C945}\u{2C946}\u{2C947}\u{2C948}\u{2C949}\u{2C94A}\u{2C94B}\u{2C94C}\u{2C94D}\u{2C94E}\u{2C94F}\u{2C950}\u{2C951}\u{2C952}\u{2C953}\u{2C954}\u{2C955}\u{2C956}\u{2C957}\u{2C958}\u{2C959}\u{2C95A}\u{2C95B}\u{2C95C}\u{2C95D}\u{2C95E}\u{2C95F}\u{2C960}\u{2C961}\u{2C962}\u{2C963}\u{2C964}\u{2C965}\u{2C966}\u{2C967}\u{2C968}\u{2C969}\u{2C96A}\u{2C96B}\u{2C96C}\u{2C96D}\u{2C96E}\u{2C96F}\u{2C970}\u{2C971}\u{2C972}\u{2C973}\u{2C974}\u{2C975}\u{2C976}\u{2C977}\u{2C978}\u{2C979}\u{2C97A}\u{2C97B}\u{2C97C}\u{2C97D}\u{2C97E}\u{2C97F}\u{2C980}\u{2C981}\u{2C982}\u{2C983}\u{2C984}\u{2C985}\u{2C986}\u{2C987}\u{2C988}\u{2C989}\u{2C98A}\u{2C98B}\u{2C98C}\u{2C98D}\u{2C98E}\u{2C98F}\u{2C990}\u{2C991}\u{2C992}\u{2C993}\u{2C994}\u{2C995}\u{2C996}\u{2C997}\u{2C998}\u{2C999}\u{2C99A}\u{2C99B}\u{2C99C}\u{2C99D}\u{2C99E}\u{2C99F}\u{2C9A0}\u{2C9A1}\u{2C9A2}\u{2C9A3}\u{2C9A4}\u{2C9A5}\u{2C9A6}\u{2C9A7}\u{2C9A8}\u{2C9A9}\u{2C9AA}\u{2C9AB}\u{2C9AC}\u{2C9AD}\u{2C9AE}\u{2C9AF}\u{2C9B0}\u{2C9B1}\u{2C9B2}\u{2C9B3}\u{2C9B4}\u{2C9B5}\u{2C9B6}\u{2C9B7}\u{2C9B8}\u{2C9B9}\u{2C9BA}\u{2C9BB}\u{2C9BC}\u{2C9BD}\u{2C9BE}\u{2C9BF}\u{2C9C0}\u{2C9C1}\u{2C9C2}\u{2C9C3}\u{2C9C4}\u{2C9C5}\u{2C9C6}\u{2C9C7}\u{2C9C8}\u{2C9C9}\u{2C9CA}\u{2C9CB}\u{2C9CC}\u{2C9CD}\u{2C9CE}\u{2C9CF}\u{2C9D0}\u{2C9D1}\u{2C9D2}\u{2C9D3}\u{2C9D4}\u{2C9D5}\u{2C9D6}\u{2C9D7}\u{2C9D8}\u{2C9D9}\u{2C9DA}\u{2C9DB}\u{2C9DC}\u{2C9DD}\u{2C9DE}\u{2C9DF}\u{2C9E0}\u{2C9E1}\u{2C9E2}\u{2C9E3}\u{2C9E4}\u{2C9E5}\u{2C9E6}\u{2C9E7}\u{2C9E8}\u{2C9E9}\u{2C9EA}\u{2C9EB}\u{2C9EC}\u{2C9ED}\u{2C9EE}\u{2C9EF}\u{2C9F0}\u{2C9F1}\u{2C9F2}\u{2C9F3}\u{2C9F4}\u{2C9F5}\u{2C9F6}\u{2C9F7}\u{2C9F8}\u{2C9F9}\u{2C9FA}\u{2C9FB}\u{2C9FC}\u{2C9FD}\u{2C9FE}\u{2C9FF}\u{2CA00}\u{2CA01}\u{2CA02}\u{2CA03}\u{2CA04}\u{2CA05}\u{2CA06}\u{2CA07}\u{2CA08}\u{2CA09}\u{2CA0A}\u{2CA0B}\u{2CA0C}\u{2CA0D}\u{2CA0E}\u{2CA0F}\u{2CA10}\u{2CA11}\u{2CA12}\u{2CA13}\u{2CA14}\u{2CA15}\u{2CA16}\u{2CA17}\u{2CA18}\u{2CA19}\u{2CA1A}\u{2CA1B}\u{2CA1C}\u{2CA1D}\u{2CA1E}\u{2CA1F}\u{2CA20}\u{2CA21}\u{2CA22}\u{2CA23}\u{2CA24}\u{2CA25}\u{2CA26}\u{2CA27}\u{2CA28}\u{2CA29}\u{2CA2A}\u{2CA2B}\u{2CA2C}\u{2CA2D}\u{2CA2E}\u{2CA2F}\u{2CA30}\u{2CA31}\u{2CA32}\u{2CA33}\u{2CA34}\u{2CA35}\u{2CA36}\u{2CA37}\u{2CA38}\u{2CA39}\u{2CA3A}\u{2CA3B}\u{2CA3C}\u{2CA3D}\u{2CA3E}\u{2CA3F}\u{2CA40}\u{2CA41}\u{2CA42}\u{2CA43}\u{2CA44}\u{2CA45}\u{2CA46}\u{2CA47}\u{2CA48}\u{2CA49}\u{2CA4A}\u{2CA4B}\u{2CA4C}\u{2CA4D}\u{2CA4E}\u{2CA4F}\u{2CA50}\u{2CA51}\u{2CA52}\u{2CA53}\u{2CA54}\u{2CA55}\u{2CA56}\u{2CA57}\u{2CA58}\u{2CA59}\u{2CA5A}\u{2CA5B}\u{2CA5C}\u{2CA5D}\u{2CA5E}\u{2CA5F}\u{2CA60}\u{2CA61}\u{2CA62}\u{2CA63}\u{2CA64}\u{2CA65}\u{2CA66}\u{2CA67}\u{2CA68}\u{2CA69}\u{2CA6A}\u{2CA6B}\u{2CA6C}\u{2CA6D}\u{2CA6E}\u{2CA6F}\u{2CA70}\u{2CA71}\u{2CA72}\u{2CA73}\u{2CA74}\u{2CA75}\u{2CA76}\u{2CA77}\u{2CA78}\u{2CA79}\u{2CA7A}\u{2CA7B}\u{2CA7C}\u{2CA7D}\u{2CA7E}\u{2CA7F}\u{2CA80}\u{2CA81}\u{2CA82}\u{2CA83}\u{2CA84}\u{2CA85}\u{2CA86}\u{2CA87}\u{2CA88}\u{2CA89}\u{2CA8A}\u{2CA8B}\u{2CA8C}\u{2CA8D}\u{2CA8E}\u{2CA8F}\u{2CA90}\u{2CA91}\u{2CA92}\u{2CA93}\u{2CA94}\u{2CA95}\u{2CA96}\u{2CA97}\u{2CA98}\u{2CA99}\u{2CA9A}\u{2CA9B}\u{2CA9C}\u{2CA9D}\u{2CA9E}\u{2CA9F}\u{2CAA0}\u{2CAA1}\u{2CAA2}\u{2CAA3}\u{2CAA4}\u{2CAA5}\u{2CAA6}\u{2CAA7}\u{2CAA8}\u{2CAA9}\u{2CAAA}\u{2CAAB}\u{2CAAC}\u{2CAAD}\u{2CAAE}\u{2CAAF}\u{2CAB0}\u{2CAB1}\u{2CAB2}\u{2CAB3}\u{2CAB4}\u{2CAB5}\u{2CAB6}\u{2CAB7}\u{2CAB8}\u{2CAB9}\u{2CABA}\u{2CABB}\u{2CABC}\u{2CABD}\u{2CABE}\u{2CABF}\u{2CAC0}\u{2CAC1}\u{2CAC2}\u{2CAC3}\u{2CAC4}\u{2CAC5}\u{2CAC6}\u{2CAC7}\u{2CAC8}\u{2CAC9}\u{2CACA}\u{2CACB}\u{2CACC}\u{2CACD}\u{2CACE}\u{2CACF}\u{2CAD0}\u{2CAD1}\u{2CAD2}\u{2CAD3}\u{2CAD4}\u{2CAD5}\u{2CAD6}\u{2CAD7}\u{2CAD8}\u{2CAD9}\u{2CADA}\u{2CADB}\u{2CADC}\u{2CADD}\u{2CADE}\u{2CADF}\u{2CAE0}\u{2CAE1}\u{2CAE2}\u{2CAE3}\u{2CAE4}\u{2CAE5}\u{2CAE6}\u{2CAE7}\u{2CAE8}\u{2CAE9}\u{2CAEA}\u{2CAEB}\u{2CAEC}\u{2CAED}\u{2CAEE}\u{2CAEF}\u{2CAF0}\u{2CAF1}\u{2CAF2}\u{2CAF3}\u{2CAF4}\u{2CAF5}\u{2CAF6}\u{2CAF7}\u{2CAF8}\u{2CAF9}\u{2CAFA}\u{2CAFB}\u{2CAFC}\u{2CAFD}\u{2CAFE}\u{2CAFF}\u{2CB00}\u{2CB01}\u{2CB02}\u{2CB03}\u{2CB04}\u{2CB05}\u{2CB06}\u{2CB07}\u{2CB08}\u{2CB09}\u{2CB0A}\u{2CB0B}\u{2CB0C}\u{2CB0D}\u{2CB0E}\u{2CB0F}\u{2CB10}\u{2CB11}\u{2CB12}\u{2CB13}\u{2CB14}\u{2CB15}\u{2CB16}\u{2CB17}\u{2CB18}\u{2CB19}\u{2CB1A}\u{2CB1B}\u{2CB1C}\u{2CB1D}\u{2CB1E}\u{2CB1F}\u{2CB20}\u{2CB21}\u{2CB22}\u{2CB23}\u{2CB24}\u{2CB25}\u{2CB26}\u{2CB27}\u{2CB28}\u{2CB29}\u{2CB2A}\u{2CB2B}\u{2CB2C}\u{2CB2D}\u{2CB2E}\u{2CB2F}\u{2CB30}\u{2CB31}\u{2CB32}\u{2CB33}\u{2CB34}\u{2CB35}\u{2CB36}\u{2CB37}\u{2CB38}\u{2CB39}\u{2CB3A}\u{2CB3B}\u{2CB3C}\u{2CB3D}\u{2CB3E}\u{2CB3F}\u{2CB40}\u{2CB41}\u{2CB42}\u{2CB43}\u{2CB44}\u{2CB45}\u{2CB46}\u{2CB47}\u{2CB48}\u{2CB49}\u{2CB4A}\u{2CB4B}\u{2CB4C}\u{2CB4D}\u{2CB4E}\u{2CB4F}\u{2CB50}\u{2CB51}\u{2CB52}\u{2CB53}\u{2CB54}\u{2CB55}\u{2CB56}\u{2CB57}\u{2CB58}\u{2CB59}\u{2CB5A}\u{2CB5B}\u{2CB5C}\u{2CB5D}\u{2CB5E}\u{2CB5F}\u{2CB60}\u{2CB61}\u{2CB62}\u{2CB63}\u{2CB64}\u{2CB65}\u{2CB66}\u{2CB67}\u{2CB68}\u{2CB69}\u{2CB6A}\u{2CB6B}\u{2CB6C}\u{2CB6D}\u{2CB6E}\u{2CB6F}\u{2CB70}\u{2CB71}\u{2CB72}\u{2CB73}\u{2CB74}\u{2CB75}\u{2CB76}\u{2CB77}\u{2CB78}\u{2CB79}\u{2CB7A}\u{2CB7B}\u{2CB7C}\u{2CB7D}\u{2CB7E}\u{2CB7F}\u{2CB80}\u{2CB81}\u{2CB82}\u{2CB83}\u{2CB84}\u{2CB85}\u{2CB86}\u{2CB87}\u{2CB88}\u{2CB89}\u{2CB8A}\u{2CB8B}\u{2CB8C}\u{2CB8D}\u{2CB8E}\u{2CB8F}\u{2CB90}\u{2CB91}\u{2CB92}\u{2CB93}\u{2CB94}\u{2CB95}\u{2CB96}\u{2CB97}\u{2CB98}\u{2CB99}\u{2CB9A}\u{2CB9B}\u{2CB9C}\u{2CB9D}\u{2CB9E}\u{2CB9F}\u{2CBA0}\u{2CBA1}\u{2CBA2}\u{2CBA3}\u{2CBA4}\u{2CBA5}\u{2CBA6}\u{2CBA7}\u{2CBA8}\u{2CBA9}\u{2CBAA}\u{2CBAB}\u{2CBAC}\u{2CBAD}\u{2CBAE}\u{2CBAF}\u{2CBB0}\u{2CBB1}\u{2CBB2}\u{2CBB3}\u{2CBB4}\u{2CBB5}\u{2CBB6}\u{2CBB7}\u{2CBB8}\u{2CBB9}\u{2CBBA}\u{2CBBB}\u{2CBBC}\u{2CBBD}\u{2CBBE}\u{2CBBF}\u{2CBC0}\u{2CBC1}\u{2CBC2}\u{2CBC3}\u{2CBC4}\u{2CBC5}\u{2CBC6}\u{2CBC7}\u{2CBC8}\u{2CBC9}\u{2CBCA}\u{2CBCB}\u{2CBCC}\u{2CBCD}\u{2CBCE}\u{2CBCF}\u{2CBD0}\u{2CBD1}\u{2CBD2}\u{2CBD3}\u{2CBD4}\u{2CBD5}\u{2CBD6}\u{2CBD7}\u{2CBD8}\u{2CBD9}\u{2CBDA}\u{2CBDB}\u{2CBDC}\u{2CBDD}\u{2CBDE}\u{2CBDF}\u{2CBE0}\u{2CBE1}\u{2CBE2}\u{2CBE3}\u{2CBE4}\u{2CBE5}\u{2CBE6}\u{2CBE7}\u{2CBE8}\u{2CBE9}\u{2CBEA}\u{2CBEB}\u{2CBEC}\u{2CBED}\u{2CBEE}\u{2CBEF}\u{2CBF0}\u{2CBF1}\u{2CBF2}\u{2CBF3}\u{2CBF4}\u{2CBF5}\u{2CBF6}\u{2CBF7}\u{2CBF8}\u{2CBF9}\u{2CBFA}\u{2CBFB}\u{2CBFC}\u{2CBFD}\u{2CBFE}\u{2CBFF}\u{2CC00}\u{2CC01}\u{2CC02}\u{2CC03}\u{2CC04}\u{2CC05}\u{2CC06}\u{2CC07}\u{2CC08}\u{2CC09}\u{2CC0A}\u{2CC0B}\u{2CC0C}\u{2CC0D}\u{2CC0E}\u{2CC0F}\u{2CC10}\u{2CC11}\u{2CC12}\u{2CC13}\u{2CC14}\u{2CC15}\u{2CC16}\u{2CC17}\u{2CC18}\u{2CC19}\u{2CC1A}\u{2CC1B}\u{2CC1C}\u{2CC1D}\u{2CC1E}\u{2CC1F}\u{2CC20}\u{2CC21}\u{2CC22}\u{2CC23}\u{2CC24}\u{2CC25}\u{2CC26}\u{2CC27}\u{2CC28}\u{2CC29}\u{2CC2A}\u{2CC2B}\u{2CC2C}\u{2CC2D}\u{2CC2E}\u{2CC2F}\u{2CC30}\u{2CC31}\u{2CC32}\u{2CC33}\u{2CC34}\u{2CC35}\u{2CC36}\u{2CC37}\u{2CC38}\u{2CC39}\u{2CC3A}\u{2CC3B}\u{2CC3C}\u{2CC3D}\u{2CC3E}\u{2CC3F}\u{2CC40}\u{2CC41}\u{2CC42}\u{2CC43}\u{2CC44}\u{2CC45}\u{2CC46}\u{2CC47}\u{2CC48}\u{2CC49}\u{2CC4A}\u{2CC4B}\u{2CC4C}\u{2CC4D}\u{2CC4E}\u{2CC4F}\u{2CC50}\u{2CC51}\u{2CC52}\u{2CC53}\u{2CC54}\u{2CC55}\u{2CC56}\u{2CC57}\u{2CC58}\u{2CC59}\u{2CC5A}\u{2CC5B}\u{2CC5C}\u{2CC5D}\u{2CC5E}\u{2CC5F}\u{2CC60}\u{2CC61}\u{2CC62}\u{2CC63}\u{2CC64}\u{2CC65}\u{2CC66}\u{2CC67}\u{2CC68}\u{2CC69}\u{2CC6A}\u{2CC6B}\u{2CC6C}\u{2CC6D}\u{2CC6E}\u{2CC6F}\u{2CC70}\u{2CC71}\u{2CC72}\u{2CC73}\u{2CC74}\u{2CC75}\u{2CC76}\u{2CC77}\u{2CC78}\u{2CC79}\u{2CC7A}\u{2CC7B}\u{2CC7C}\u{2CC7D}\u{2CC7E}\u{2CC7F}\u{2CC80}\u{2CC81}\u{2CC82}\u{2CC83}\u{2CC84}\u{2CC85}\u{2CC86}\u{2CC87}\u{2CC88}\u{2CC89}\u{2CC8A}\u{2CC8B}\u{2CC8C}\u{2CC8D}\u{2CC8E}\u{2CC8F}\u{2CC90}\u{2CC91}\u{2CC92}\u{2CC93}\u{2CC94}\u{2CC95}\u{2CC96}\u{2CC97}\u{2CC98}\u{2CC99}\u{2CC9A}\u{2CC9B}\u{2CC9C}\u{2CC9D}\u{2CC9E}\u{2CC9F}\u{2CCA0}\u{2CCA1}\u{2CCA2}\u{2CCA3}\u{2CCA4}\u{2CCA5}\u{2CCA6}\u{2CCA7}\u{2CCA8}\u{2CCA9}\u{2CCAA}\u{2CCAB}\u{2CCAC}\u{2CCAD}\u{2CCAE}\u{2CCAF}\u{2CCB0}\u{2CCB1}\u{2CCB2}\u{2CCB3}\u{2CCB4}\u{2CCB5}\u{2CCB6}\u{2CCB7}\u{2CCB8}\u{2CCB9}\u{2CCBA}\u{2CCBB}\u{2CCBC}\u{2CCBD}\u{2CCBE}\u{2CCBF}\u{2CCC0}\u{2CCC1}\u{2CCC2}\u{2CCC3}\u{2CCC4}\u{2CCC5}\u{2CCC6}\u{2CCC7}\u{2CCC8}\u{2CCC9}\u{2CCCA}\u{2CCCB}\u{2CCCC}\u{2CCCD}\u{2CCCE}\u{2CCCF}\u{2CCD0}\u{2CCD1}\u{2CCD2}\u{2CCD3}\u{2CCD4}\u{2CCD5}\u{2CCD6}\u{2CCD7}\u{2CCD8}\u{2CCD9}\u{2CCDA}\u{2CCDB}\u{2CCDC}\u{2CCDD}\u{2CCDE}\u{2CCDF}\u{2CCE0}\u{2CCE1}\u{2CCE2}\u{2CCE3}\u{2CCE4}\u{2CCE5}\u{2CCE6}\u{2CCE7}\u{2CCE8}\u{2CCE9}\u{2CCEA}\u{2CCEB}\u{2CCEC}\u{2CCED}\u{2CCEE}\u{2CCEF}\u{2CCF0}\u{2CCF1}\u{2CCF2}\u{2CCF3}\u{2CCF4}\u{2CCF5}\u{2CCF6}\u{2CCF7}\u{2CCF8}\u{2CCF9}\u{2CCFA}\u{2CCFB}\u{2CCFC}\u{2CCFD}\u{2CCFE}\u{2CCFF}\u{2CD00}\u{2CD01}\u{2CD02}\u{2CD03}\u{2CD04}\u{2CD05}\u{2CD06}\u{2CD07}\u{2CD08}\u{2CD09}\u{2CD0A}\u{2CD0B}\u{2CD0C}\u{2CD0D}\u{2CD0E}\u{2CD0F}\u{2CD10}\u{2CD11}\u{2CD12}\u{2CD13}\u{2CD14}\u{2CD15}\u{2CD16}\u{2CD17}\u{2CD18}\u{2CD19}\u{2CD1A}\u{2CD1B}\u{2CD1C}\u{2CD1D}\u{2CD1E}\u{2CD1F}\u{2CD20}\u{2CD21}\u{2CD22}\u{2CD23}\u{2CD24}\u{2CD25}\u{2CD26}\u{2CD27}\u{2CD28}\u{2CD29}\u{2CD2A}\u{2CD2B}\u{2CD2C}\u{2CD2D}\u{2CD2E}\u{2CD2F}\u{2CD30}\u{2CD31}\u{2CD32}\u{2CD33}\u{2CD34}\u{2CD35}\u{2CD36}\u{2CD37}\u{2CD38}\u{2CD39}\u{2CD3A}\u{2CD3B}\u{2CD3C}\u{2CD3D}\u{2CD3E}\u{2CD3F}\u{2CD40}\u{2CD41}\u{2CD42}\u{2CD43}\u{2CD44}\u{2CD45}\u{2CD46}\u{2CD47}\u{2CD48}\u{2CD49}\u{2CD4A}\u{2CD4B}\u{2CD4C}\u{2CD4D}\u{2CD4E}\u{2CD4F}\u{2CD50}\u{2CD51}\u{2CD52}\u{2CD53}\u{2CD54}\u{2CD55}\u{2CD56}\u{2CD57}\u{2CD58}\u{2CD59}\u{2CD5A}\u{2CD5B}\u{2CD5C}\u{2CD5D}\u{2CD5E}\u{2CD5F}\u{2CD60}\u{2CD61}\u{2CD62}\u{2CD63}\u{2CD64}\u{2CD65}\u{2CD66}\u{2CD67}\u{2CD68}\u{2CD69}\u{2CD6A}\u{2CD6B}\u{2CD6C}\u{2CD6D}\u{2CD6E}\u{2CD6F}\u{2CD70}\u{2CD71}\u{2CD72}\u{2CD73}\u{2CD74}\u{2CD75}\u{2CD76}\u{2CD77}\u{2CD78}\u{2CD79}\u{2CD7A}\u{2CD7B}\u{2CD7C}\u{2CD7D}\u{2CD7E}\u{2CD7F}\u{2CD80}\u{2CD81}\u{2CD82}\u{2CD83}\u{2CD84}\u{2CD85}\u{2CD86}\u{2CD87}\u{2CD88}\u{2CD89}\u{2CD8A}\u{2CD8B}\u{2CD8C}\u{2CD8D}\u{2CD8E}\u{2CD8F}\u{2CD90}\u{2CD91}\u{2CD92}\u{2CD93}\u{2CD94}\u{2CD95}\u{2CD96}\u{2CD97}\u{2CD98}\u{2CD99}\u{2CD9A}\u{2CD9B}\u{2CD9C}\u{2CD9D}\u{2CD9E}\u{2CD9F}\u{2CDA0}\u{2CDA1}\u{2CDA2}\u{2CDA3}\u{2CDA4}\u{2CDA5}\u{2CDA6}\u{2CDA7}\u{2CDA8}\u{2CDA9}\u{2CDAA}\u{2CDAB}\u{2CDAC}\u{2CDAD}\u{2CDAE}\u{2CDAF}\u{2CDB0}\u{2CDB1}\u{2CDB2}\u{2CDB3}\u{2CDB4}\u{2CDB5}\u{2CDB6}\u{2CDB7}\u{2CDB8}\u{2CDB9}\u{2CDBA}\u{2CDBB}\u{2CDBC}\u{2CDBD}\u{2CDBE}\u{2CDBF}\u{2CDC0}\u{2CDC1}\u{2CDC2}\u{2CDC3}\u{2CDC4}\u{2CDC5}\u{2CDC6}\u{2CDC7}\u{2CDC8}\u{2CDC9}\u{2CDCA}\u{2CDCB}\u{2CDCC}\u{2CDCD}\u{2CDCE}\u{2CDCF}\u{2CDD0}\u{2CDD1}\u{2CDD2}\u{2CDD3}\u{2CDD4}\u{2CDD5}\u{2CDD6}\u{2CDD7}\u{2CDD8}\u{2CDD9}\u{2CDDA}\u{2CDDB}\u{2CDDC}\u{2CDDD}\u{2CDDE}\u{2CDDF}\u{2CDE0}\u{2CDE1}\u{2CDE2}\u{2CDE3}\u{2CDE4}\u{2CDE5}\u{2CDE6}\u{2CDE7}\u{2CDE8}\u{2CDE9}\u{2CDEA}\u{2CDEB}\u{2CDEC}\u{2CDED}\u{2CDEE}\u{2CDEF}\u{2CDF0}\u{2CDF1}\u{2CDF2}\u{2CDF3}\u{2CDF4}\u{2CDF5}\u{2CDF6}\u{2CDF7}\u{2CDF8}\u{2CDF9}\u{2CDFA}\u{2CDFB}\u{2CDFC}\u{2CDFD}\u{2CDFE}\u{2CDFF}\u{2CE00}\u{2CE01}\u{2CE02}\u{2CE03}\u{2CE04}\u{2CE05}\u{2CE06}\u{2CE07}\u{2CE08}\u{2CE09}\u{2CE0A}\u{2CE0B}\u{2CE0C}\u{2CE0D}\u{2CE0E}\u{2CE0F}\u{2CE10}\u{2CE11}\u{2CE12}\u{2CE13}\u{2CE14}\u{2CE15}\u{2CE16}\u{2CE17}\u{2CE18}\u{2CE19}\u{2CE1A}\u{2CE1B}\u{2CE1C}\u{2CE1D}\u{2CE1E}\u{2CE1F}\u{2CE20}\u{2CE21}\u{2CE22}\u{2CE23}\u{2CE24}\u{2CE25}\u{2CE26}\u{2CE27}\u{2CE28}\u{2CE29}\u{2CE2A}\u{2CE2B}\u{2CE2C}\u{2CE2D}\u{2CE2E}\u{2CE2F}\u{2CE30}\u{2CE31}\u{2CE32}\u{2CE33}\u{2CE34}\u{2CE35}\u{2CE36}\u{2CE37}\u{2CE38}\u{2CE39}\u{2CE3A}\u{2CE3B}\u{2CE3C}\u{2CE3D}\u{2CE3E}\u{2CE3F}\u{2CE40}\u{2CE41}\u{2CE42}\u{2CE43}\u{2CE44}\u{2CE45}\u{2CE46}\u{2CE47}\u{2CE48}\u{2CE49}\u{2CE4A}\u{2CE4B}\u{2CE4C}\u{2CE4D}\u{2CE4E}\u{2CE4F}\u{2CE50}\u{2CE51}\u{2CE52}\u{2CE53}\u{2CE54}\u{2CE55}\u{2CE56}\u{2CE57}\u{2CE58}\u{2CE59}\u{2CE5A}\u{2CE5B}\u{2CE5C}\u{2CE5D}\u{2CE5E}\u{2CE5F}\u{2CE60}\u{2CE61}\u{2CE62}\u{2CE63}\u{2CE64}\u{2CE65}\u{2CE66}\u{2CE67}\u{2CE68}\u{2CE69}\u{2CE6A}\u{2CE6B}\u{2CE6C}\u{2CE6D}\u{2CE6E}\u{2CE6F}\u{2CE70}\u{2CE71}\u{2CE72}\u{2CE73}\u{2CE74}\u{2CE75}\u{2CE76}\u{2CE77}\u{2CE78}\u{2CE79}\u{2CE7A}\u{2CE7B}\u{2CE7C}\u{2CE7D}\u{2CE7E}\u{2CE7F}\u{2CE80}\u{2CE81}\u{2CE82}\u{2CE83}\u{2CE84}\u{2CE85}\u{2CE86}\u{2CE87}\u{2CE88}\u{2CE89}\u{2CE8A}\u{2CE8B}\u{2CE8C}\u{2CE8D}\u{2CE8E}\u{2CE8F}\u{2CE90}\u{2CE91}\u{2CE92}\u{2CE93}\u{2CE94}\u{2CE95}\u{2CE96}\u{2CE97}\u{2CE98}\u{2CE99}\u{2CE9A}\u{2CE9B}\u{2CE9C}\u{2CE9D}\u{2CE9E}\u{2CE9F}\u{2CEA0}\u{2CEA1}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-class.js new file mode 100644 index 000000000000..572110fbac0d --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v8.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ࢳࢴૹౚൟᏵᏸᏹᏺᏻᏼᏽᦰᦱᦲᦳᦴᦵᦶᦷᦸᦹᦺᦻᦼᦽᦾᦿᧀᧈᧉ鿍鿎鿏鿐鿑鿒鿓鿔鿕ꞏꞲꞳꞴꞵꞶꞷꣽꭠꭡꭢꭣꭰꭱꭲꭳꭴꭵꭶꭷꭸꭹꭺꭻꭼꭽꭾꭿꮀꮁꮂꮃꮄꮅꮆꮇꮈꮉꮊꮋꮌꮍꮎꮏꮐꮑꮒꮓꮔꮕꮖꮗꮘꮙꮚꮛꮜꮝꮞꮟꮠꮡꮢꮣꮤꮥꮦꮧꮨꮩꮪꮫꮬꮭꮮꮯꮰꮱꮲꮳꮴꮵꮶꮷꮸꮹꮺꮻꮼꮽꮾꮿ𐣠𐣡𐣢𐣣𐣤𐣥𐣦𐣧𐣨𐣩𐣪𐣫𐣬𐣭𐣮𐣯𐣰𐣱𐣲𐣴𐣵𐲀𐲁𐲂𐲃𐲄𐲅𐲆𐲇𐲈𐲉𐲊𐲋𐲌𐲍𐲎𐲏𐲐𐲑𐲒𐲓𐲔𐲕𐲖𐲗𐲘𐲙𐲚𐲛𐲜𐲝𐲞𐲟𐲠𐲡𐲢𐲣𐲤𐲥𐲦𐲧𐲨𐲩𐲪𐲫𐲬𐲭𐲮𐲯𐲰𐲱𐲲𐳀𐳁𐳂𐳃𐳄𐳅𐳆𐳇𐳈𐳉𐳊𐳋𐳌𐳍𐳎𐳏𐳐𐳑𐳒𐳓𐳔𐳕𐳖𐳗𐳘𐳙𐳚𐳛𐳜𐳝𐳞𐳟𐳠𐳡𐳢𐳣𐳤𐳥𐳦𐳧𐳨𐳩𐳪𐳫𐳬𐳭𐳮𐳯𐳰𐳱𐳲𑇜𑊀𑊁𑊂𑊃𑊄𑊅𑊆𑊈𑊊𑊋𑊌𑊍𑊏𑊐𑊑𑊒𑊓𑊔𑊕𑊖𑊗𑊘𑊙𑊚𑊛𑊜𑊝𑊟𑊠𑊡𑊢𑊣𑊤𑊥𑊦𑊧𑊨𑍐𑗘𑗙𑗚𑗛𑜀𑜁𑜂𑜃𑜄𑜅𑜆𑜇𑜈𑜉𑜊𑜋𑜌𑜍𑜎𑜏𑜐𑜑𑜒𑜓𑜔𑜕𑜖𑜗𑜘𑜙𒎙𒒀𒒁𒒂𒒃𒒄𒒅𒒆𒒇𒒈𒒉𒒊𒒋𒒌𒒍𒒎𒒏𒒐𒒑𒒒𒒓𒒔𒒕𒒖𒒗𒒘𒒙𒒚𒒛𒒜𒒝𒒞𒒟𒒠𒒡𒒢𒒣𒒤𒒥𒒦𒒧𒒨𒒩𒒪𒒫𒒬𒒭𒒮𒒯𒒰𒒱𒒲𒒳𒒴𒒵𒒶𒒷𒒸𒒹𒒺𒒻𒒼𒒽𒒾𒒿𒓀𒓁𒓂𒓃𒓄𒓅𒓆𒓇𒓈𒓉𒓊𒓋𒓌𒓍𒓎𒓏𒓐𒓑𒓒𒓓𒓔𒓕𒓖𒓗𒓘𒓙𒓚𒓛𒓜𒓝𒓞𒓟𒓠𒓡𒓢𒓣𒓤𒓥𒓦𒓧𒓨𒓩𒓪𒓫𒓬𒓭𒓮𒓯𒓰𒓱𒓲𒓳𒓴𒓵𒓶𒓷𒓸𒓹𒓺𒓻𒓼𒓽𒓾𒓿𒔀𒔁𒔂𒔃𒔄𒔅𒔆𒔇𒔈𒔉𒔊𒔋𒔌𒔍𒔎𒔏𒔐𒔑𒔒𒔓𒔔𒔕𒔖𒔗𒔘𒔙𒔚𒔛𒔜𒔝𒔞𒔟𒔠𒔡𒔢𒔣𒔤𒔥𒔦𒔧𒔨𒔩𒔪𒔫𒔬𒔭𒔮𒔯𒔰𒔱𒔲𒔳𒔴𒔵𒔶𒔷𒔸𒔹𒔺𒔻𒔼𒔽𒔾𒔿𒕀𒕁𒕂𒕃𔐀𔐁𔐂𔐃𔐄𔐅𔐆𔐇𔐈𔐉𔐊𔐋𔐌𔐍𔐎𔐏𔐐𔐑𔐒𔐓𔐔𔐕𔐖𔐗𔐘𔐙𔐚𔐛𔐜𔐝𔐞𔐟𔐠𔐡𔐢𔐣𔐤𔐥𔐦𔐧𔐨𔐩𔐪𔐫𔐬𔐭𔐮𔐯𔐰𔐱𔐲𔐳𔐴𔐵𔐶𔐷𔐸𔐹𔐺𔐻𔐼𔐽𔐾𔐿𔑀𔑁𔑂𔑃𔑄𔑅𔑆𔑇𔑈𔑉𔑊𔑋𔑌𔑍𔑎𔑏𔑐𔑑𔑒𔑓𔑔𔑕𔑖𔑗𔑘𔑙𔑚𔑛𔑜𔑝𔑞𔑟𔑠𔑡𔑢𔑣𔑤𔑥𔑦𔑧𔑨𔑩𔑪𔑫𔑬𔑭𔑮𔑯𔑰𔑱𔑲𔑳𔑴𔑵𔑶𔑷𔑸𔑹𔑺𔑻𔑼𔑽𔑾𔑿𔒀𔒁𔒂𔒃𔒄𔒅𔒆𔒇𔒈𔒉𔒊𔒋𔒌𔒍𔒎𔒏𔒐𔒑𔒒𔒓𔒔𔒕𔒖𔒗𔒘𔒙𔒚𔒛𔒜𔒝𔒞𔒟𔒠𔒡𔒢𔒣𔒤𔒥𔒦𔒧𔒨𔒩𔒪𔒫𔒬𔒭𔒮𔒯𔒰𔒱𔒲𔒳𔒴𔒵𔒶𔒷𔒸𔒹𔒺𔒻𔒼𔒽𔒾𔒿𔓀𔓁𔓂𔓃𔓄𔓅𔓆𔓇𔓈𔓉𔓊𔓋𔓌𔓍𔓎𔓏𔓐𔓑𔓒𔓓𔓔𔓕𔓖𔓗𔓘𔓙𔓚𔓛𔓜𔓝𔓞𔓟𔓠𔓡𔓢𔓣𔓤𔓥𔓦𔓧𔓨𔓩𔓪𔓫𔓬𔓭𔓮𔓯𔓰𔓱𔓲𔓳𔓴𔓵𔓶𔓷𔓸𔓹𔓺𔓻𔓼𔓽𔓾𔓿𔔀𔔁𔔂𔔃𔔄𔔅𔔆𔔇𔔈𔔉𔔊𔔋𔔌𔔍𔔎𔔏𔔐𔔑𔔒𔔓𔔔𔔕𔔖𔔗𔔘𔔙𔔚𔔛𔔜𔔝𔔞𔔟𔔠𔔡𔔢𔔣𔔤𔔥𔔦𔔧𔔨𔔩𔔪𔔫𔔬𔔭𔔮𔔯𔔰𔔱𔔲𔔳𔔴𔔵𔔶𔔷𔔸𔔹𔔺𔔻𔔼𔔽𔔾𔔿𔕀𔕁𔕂𔕃𔕄𔕅𔕆𔕇𔕈𔕉𔕊𔕋𔕌𔕍𔕎𔕏𔕐𔕑𔕒𔕓𔕔𔕕𔕖𔕗𔕘𔕙𔕚𔕛𔕜𔕝𔕞𔕟𔕠𔕡𔕢𔕣𔕤𔕥𔕦𔕧𔕨𔕩𔕪𔕫𔕬𔕭𔕮𔕯𔕰𔕱𔕲𔕳𔕴𔕵𔕶𔕷𔕸𔕹𔕺𔕻𔕼𔕽𔕾𔕿𔖀𔖁𔖂𔖃𔖄𔖅𔖆𔖇𔖈𔖉𔖊𔖋𔖌𔖍𔖎𔖏𔖐𔖑𔖒𔖓𔖔𔖕𔖖𔖗𔖘𔖙𔖚𔖛𔖜𔖝𔖞𔖟𔖠𔖡𔖢𔖣𔖤𔖥𔖦𔖧𔖨𔖩𔖪𔖫𔖬𔖭𔖮𔖯𔖰𔖱𔖲𔖳𔖴𔖵𔖶𔖷𔖸𔖹𔖺𔖻𔖼𔖽𔖾𔖿𔗀𔗁𔗂𔗃𔗄𔗅𔗆𔗇𔗈𔗉𔗊𔗋𔗌𔗍𔗎𔗏𔗐𔗑𔗒𔗓𔗔𔗕𔗖𔗗𔗘𔗙𔗚𔗛𔗜𔗝𔗞𔗟𔗠𔗡𔗢𔗣𔗤𔗥𔗦𔗧𔗨𔗩𔗪𔗫𔗬𔗭𔗮𔗯𔗰𔗱𔗲𔗳𔗴𔗵𔗶𔗷𔗸𔗹𔗺𔗻𔗼𔗽𔗾𔗿𔘀𔘁𔘂𔘃𔘄𔘅𔘆𔘇𔘈𔘉𔘊𔘋𔘌𔘍𔘎𔘏𔘐𔘑𔘒𔘓𔘔𔘕𔘖𔘗𔘘𔘙𔘚𔘛𔘜𔘝𔘞𔘟𔘠𔘡𔘢𔘣𔘤𔘥𔘦𔘧𔘨𔘩𔘪𔘫𔘬𔘭𔘮𔘯𔘰𔘱𔘲𔘳𔘴𔘵𔘶𔘷𔘸𔘹𔘺𔘻𔘼𔘽𔘾𔘿𔙀𔙁𔙂𔙃𔙄𔙅𔙆𫠠𫠡𫠢𫠣𫠤𫠥𫠦𫠧𫠨𫠩𫠪𫠫𫠬𫠭𫠮𫠯𫠰𫠱𫠲𫠳𫠴𫠵𫠶𫠷𫠸𫠹𫠺𫠻𫠼𫠽𫠾𫠿𫡀𫡁𫡂𫡃𫡄𫡅𫡆𫡇𫡈𫡉𫡊𫡋𫡌𫡍𫡎𫡏𫡐𫡑𫡒𫡓𫡔𫡕𫡖𫡗𫡘𫡙𫡚𫡛𫡜𫡝𫡞𫡟𫡠𫡡𫡢𫡣𫡤𫡥𫡦𫡧𫡨𫡩𫡪𫡫𫡬𫡭𫡮𫡯𫡰𫡱𫡲𫡳𫡴𫡵𫡶𫡷𫡸𫡹𫡺𫡻𫡼𫡽𫡾𫡿𫢀𫢁𫢂𫢃𫢄𫢅𫢆𫢇𫢈𫢉𫢊𫢋𫢌𫢍𫢎𫢏𫢐𫢑𫢒𫢓𫢔𫢕𫢖𫢗𫢘𫢙𫢚𫢛𫢜𫢝𫢞𫢟𫢠𫢡𫢢𫢣𫢤𫢥𫢦𫢧𫢨𫢩𫢪𫢫𫢬𫢭𫢮𫢯𫢰𫢱𫢲𫢳𫢴𫢵𫢶𫢷𫢸𫢹𫢺𫢻𫢼𫢽𫢾𫢿𫣀𫣁𫣂𫣃𫣄𫣅𫣆𫣇𫣈𫣉𫣊𫣋𫣌𫣍𫣎𫣏𫣐𫣑𫣒𫣓𫣔𫣕𫣖𫣗𫣘𫣙𫣚𫣛𫣜𫣝𫣞𫣟𫣠𫣡𫣢𫣣𫣤𫣥𫣦𫣧𫣨𫣩𫣪𫣫𫣬𫣭𫣮𫣯𫣰𫣱𫣲𫣳𫣴𫣵𫣶𫣷𫣸𫣹𫣺𫣻𫣼𫣽𫣾𫣿𫤀𫤁𫤂𫤃𫤄𫤅𫤆𫤇𫤈𫤉𫤊𫤋𫤌𫤍𫤎𫤏𫤐𫤑𫤒𫤓𫤔𫤕𫤖𫤗𫤘𫤙𫤚𫤛𫤜𫤝𫤞𫤟𫤠𫤡𫤢𫤣𫤤𫤥𫤦𫤧𫤨𫤩𫤪𫤫𫤬𫤭𫤮𫤯𫤰𫤱𫤲𫤳𫤴𫤵𫤶𫤷𫤸𫤹𫤺𫤻𫤼𫤽𫤾𫤿𫥀𫥁𫥂𫥃𫥄𫥅𫥆𫥇𫥈𫥉𫥊𫥋𫥌𫥍𫥎𫥏𫥐𫥑𫥒𫥓𫥔𫥕𫥖𫥗𫥘𫥙𫥚𫥛𫥜𫥝𫥞𫥟𫥠𫥡𫥢𫥣𫥤𫥥𫥦𫥧𫥨𫥩𫥪𫥫𫥬𫥭𫥮𫥯𫥰𫥱𫥲𫥳𫥴𫥵𫥶𫥷𫥸𫥹𫥺𫥻𫥼𫥽𫥾𫥿𫦀𫦁𫦂𫦃𫦄𫦅𫦆𫦇𫦈𫦉𫦊𫦋𫦌𫦍𫦎𫦏𫦐𫦑𫦒𫦓𫦔𫦕𫦖𫦗𫦘𫦙𫦚𫦛𫦜𫦝𫦞𫦟𫦠𫦡𫦢𫦣𫦤𫦥𫦦𫦧𫦨𫦩𫦪𫦫𫦬𫦭𫦮𫦯𫦰𫦱𫦲𫦳𫦴𫦵𫦶𫦷𫦸𫦹𫦺𫦻𫦼𫦽𫦾𫦿𫧀𫧁𫧂𫧃𫧄𫧅𫧆𫧇𫧈𫧉𫧊𫧋𫧌𫧍𫧎𫧏𫧐𫧑𫧒𫧓𫧔𫧕𫧖𫧗𫧘𫧙𫧚𫧛𫧜𫧝𫧞𫧟𫧠𫧡𫧢𫧣𫧤𫧥𫧦𫧧𫧨𫧩𫧪𫧫𫧬𫧭𫧮𫧯𫧰𫧱𫧲𫧳𫧴𫧵𫧶𫧷𫧸𫧹𫧺𫧻𫧼𫧽𫧾𫧿𫨀𫨁𫨂𫨃𫨄𫨅𫨆𫨇𫨈𫨉𫨊𫨋𫨌𫨍𫨎𫨏𫨐𫨑𫨒𫨓𫨔𫨕𫨖𫨗𫨘𫨙𫨚𫨛𫨜𫨝𫨞𫨟𫨠𫨡𫨢𫨣𫨤𫨥𫨦𫨧𫨨𫨩𫨪𫨫𫨬𫨭𫨮𫨯𫨰𫨱𫨲𫨳𫨴𫨵𫨶𫨷𫨸𫨹𫨺𫨻𫨼𫨽𫨾𫨿𫩀𫩁𫩂𫩃𫩄𫩅𫩆𫩇𫩈𫩉𫩊𫩋𫩌𫩍𫩎𫩏𫩐𫩑𫩒𫩓𫩔𫩕𫩖𫩗𫩘𫩙𫩚𫩛𫩜𫩝𫩞𫩟𫩠𫩡𫩢𫩣𫩤𫩥𫩦𫩧𫩨𫩩𫩪𫩫𫩬𫩭𫩮𫩯𫩰𫩱𫩲𫩳𫩴𫩵𫩶𫩷𫩸𫩹𫩺𫩻𫩼𫩽𫩾𫩿𫪀𫪁𫪂𫪃𫪄𫪅𫪆𫪇𫪈𫪉𫪊𫪋𫪌𫪍𫪎𫪏𫪐𫪑𫪒𫪓𫪔𫪕𫪖𫪗𫪘𫪙𫪚𫪛𫪜𫪝𫪞𫪟𫪠𫪡𫪢𫪣𫪤𫪥𫪦𫪧𫪨𫪩𫪪𫪫𫪬𫪭𫪮𫪯𫪰𫪱𫪲𫪳𫪴𫪵𫪶𫪷𫪸𫪹𫪺𫪻𫪼𫪽𫪾𫪿𫫀𫫁𫫂𫫃𫫄𫫅𫫆𫫇𫫈𫫉𫫊𫫋𫫌𫫍𫫎𫫏𫫐𫫑𫫒𫫓𫫔𫫕𫫖𫫗𫫘𫫙𫫚𫫛𫫜𫫝𫫞𫫟𫫠𫫡𫫢𫫣𫫤𫫥𫫦𫫧𫫨𫫩𫫪𫫫𫫬𫫭𫫮𫫯𫫰𫫱𫫲𫫳𫫴𫫵𫫶𫫷𫫸𫫹𫫺𫫻𫫼𫫽𫫾𫫿𫬀𫬁𫬂𫬃𫬄𫬅𫬆𫬇𫬈𫬉𫬊𫬋𫬌𫬍𫬎𫬏𫬐𫬑𫬒𫬓𫬔𫬕𫬖𫬗𫬘𫬙𫬚𫬛𫬜𫬝𫬞𫬟𫬠𫬡𫬢𫬣𫬤𫬥𫬦𫬧𫬨𫬩𫬪𫬫𫬬𫬭𫬮𫬯𫬰𫬱𫬲𫬳𫬴𫬵𫬶𫬷𫬸𫬹𫬺𫬻𫬼𫬽𫬾𫬿𫭀𫭁𫭂𫭃𫭄𫭅𫭆𫭇𫭈𫭉𫭊𫭋𫭌𫭍𫭎𫭏𫭐𫭑𫭒𫭓𫭔𫭕𫭖𫭗𫭘𫭙𫭚𫭛𫭜𫭝𫭞𫭟𫭠𫭡𫭢𫭣𫭤𫭥𫭦𫭧𫭨𫭩𫭪𫭫𫭬𫭭𫭮𫭯𫭰𫭱𫭲𫭳𫭴𫭵𫭶𫭷𫭸𫭹𫭺𫭻𫭼𫭽𫭾𫭿𫮀𫮁𫮂𫮃𫮄𫮅𫮆𫮇𫮈𫮉𫮊𫮋𫮌𫮍𫮎𫮏𫮐𫮑𫮒𫮓𫮔𫮕𫮖𫮗𫮘𫮙𫮚𫮛𫮜𫮝𫮞𫮟𫮠𫮡𫮢𫮣𫮤𫮥𫮦𫮧𫮨𫮩𫮪𫮫𫮬𫮭𫮮𫮯𫮰𫮱𫮲𫮳𫮴𫮵𫮶𫮷𫮸𫮹𫮺𫮻𫮼𫮽𫮾𫮿𫯀𫯁𫯂𫯃𫯄𫯅𫯆𫯇𫯈𫯉𫯊𫯋𫯌𫯍𫯎𫯏𫯐𫯑𫯒𫯓𫯔𫯕𫯖𫯗𫯘𫯙𫯚𫯛𫯜𫯝𫯞𫯟𫯠𫯡𫯢𫯣𫯤𫯥𫯦𫯧𫯨𫯩𫯪𫯫𫯬𫯭𫯮𫯯𫯰𫯱𫯲𫯳𫯴𫯵𫯶𫯷𫯸𫯹𫯺𫯻𫯼𫯽𫯾𫯿𫰀𫰁𫰂𫰃𫰄𫰅𫰆𫰇𫰈𫰉𫰊𫰋𫰌𫰍𫰎𫰏𫰐𫰑𫰒𫰓𫰔𫰕𫰖𫰗𫰘𫰙𫰚𫰛𫰜𫰝𫰞𫰟𫰠𫰡𫰢𫰣𫰤𫰥𫰦𫰧𫰨𫰩𫰪𫰫𫰬𫰭𫰮𫰯𫰰𫰱𫰲𫰳𫰴𫰵𫰶𫰷𫰸𫰹𫰺𫰻𫰼𫰽𫰾𫰿𫱀𫱁𫱂𫱃𫱄𫱅𫱆𫱇𫱈𫱉𫱊𫱋𫱌𫱍𫱎𫱏𫱐𫱑𫱒𫱓𫱔𫱕𫱖𫱗𫱘𫱙𫱚𫱛𫱜𫱝𫱞𫱟𫱠𫱡𫱢𫱣𫱤𫱥𫱦𫱧𫱨𫱩𫱪𫱫𫱬𫱭𫱮𫱯𫱰𫱱𫱲𫱳𫱴𫱵𫱶𫱷𫱸𫱹𫱺𫱻𫱼𫱽𫱾𫱿𫲀𫲁𫲂𫲃𫲄𫲅𫲆𫲇𫲈𫲉𫲊𫲋𫲌𫲍𫲎𫲏𫲐𫲑𫲒𫲓𫲔𫲕𫲖𫲗𫲘𫲙𫲚𫲛𫲜𫲝𫲞𫲟𫲠𫲡𫲢𫲣𫲤𫲥𫲦𫲧𫲨𫲩𫲪𫲫𫲬𫲭𫲮𫲯𫲰𫲱𫲲𫲳𫲴𫲵𫲶𫲷𫲸𫲹𫲺𫲻𫲼𫲽𫲾𫲿𫳀𫳁𫳂𫳃𫳄𫳅𫳆𫳇𫳈𫳉𫳊𫳋𫳌𫳍𫳎𫳏𫳐𫳑𫳒𫳓𫳔𫳕𫳖𫳗𫳘𫳙𫳚𫳛𫳜𫳝𫳞𫳟𫳠𫳡𫳢𫳣𫳤𫳥𫳦𫳧𫳨𫳩𫳪𫳫𫳬𫳭𫳮𫳯𫳰𫳱𫳲𫳳𫳴𫳵𫳶𫳷𫳸𫳹𫳺𫳻𫳼𫳽𫳾𫳿𫴀𫴁𫴂𫴃𫴄𫴅𫴆𫴇𫴈𫴉𫴊𫴋𫴌𫴍𫴎𫴏𫴐𫴑𫴒𫴓𫴔𫴕𫴖𫴗𫴘𫴙𫴚𫴛𫴜𫴝𫴞𫴟𫴠𫴡𫴢𫴣𫴤𫴥𫴦𫴧𫴨𫴩𫴪𫴫𫴬𫴭𫴮𫴯𫴰𫴱𫴲𫴳𫴴𫴵𫴶𫴷𫴸𫴹𫴺𫴻𫴼𫴽𫴾𫴿𫵀𫵁𫵂𫵃𫵄𫵅𫵆𫵇𫵈𫵉𫵊𫵋𫵌𫵍𫵎𫵏𫵐𫵑𫵒𫵓𫵔𫵕𫵖𫵗𫵘𫵙𫵚𫵛𫵜𫵝𫵞𫵟𫵠𫵡𫵢𫵣𫵤𫵥𫵦𫵧𫵨𫵩𫵪𫵫𫵬𫵭𫵮𫵯𫵰𫵱𫵲𫵳𫵴𫵵𫵶𫵷𫵸𫵹𫵺𫵻𫵼𫵽𫵾𫵿𫶀𫶁𫶂𫶃𫶄𫶅𫶆𫶇𫶈𫶉𫶊𫶋𫶌𫶍𫶎𫶏𫶐𫶑𫶒𫶓𫶔𫶕𫶖𫶗𫶘𫶙𫶚𫶛𫶜𫶝𫶞𫶟𫶠𫶡𫶢𫶣𫶤𫶥𫶦𫶧𫶨𫶩𫶪𫶫𫶬𫶭𫶮𫶯𫶰𫶱𫶲𫶳𫶴𫶵𫶶𫶷𫶸𫶹𫶺𫶻𫶼𫶽𫶾𫶿𫷀𫷁𫷂𫷃𫷄𫷅𫷆𫷇𫷈𫷉𫷊𫷋𫷌𫷍𫷎𫷏𫷐𫷑𫷒𫷓𫷔𫷕𫷖𫷗𫷘𫷙𫷚𫷛𫷜𫷝𫷞𫷟𫷠𫷡𫷢𫷣𫷤𫷥𫷦𫷧𫷨𫷩𫷪𫷫𫷬𫷭𫷮𫷯𫷰𫷱𫷲𫷳𫷴𫷵𫷶𫷷𫷸𫷹𫷺𫷻𫷼𫷽𫷾𫷿𫸀𫸁𫸂𫸃𫸄𫸅𫸆𫸇𫸈𫸉𫸊𫸋𫸌𫸍𫸎𫸏𫸐𫸑𫸒𫸓𫸔𫸕𫸖𫸗𫸘𫸙𫸚𫸛𫸜𫸝𫸞𫸟𫸠𫸡𫸢𫸣𫸤𫸥𫸦𫸧𫸨𫸩𫸪𫸫𫸬𫸭𫸮𫸯𫸰𫸱𫸲𫸳𫸴𫸵𫸶𫸷𫸸𫸹𫸺𫸻𫸼𫸽𫸾𫸿𫹀𫹁𫹂𫹃𫹄𫹅𫹆𫹇𫹈𫹉𫹊𫹋𫹌𫹍𫹎𫹏𫹐𫹑𫹒𫹓𫹔𫹕𫹖𫹗𫹘𫹙𫹚𫹛𫹜𫹝𫹞𫹟𫹠𫹡𫹢𫹣𫹤𫹥𫹦𫹧𫹨𫹩𫹪𫹫𫹬𫹭𫹮𫹯𫹰𫹱𫹲𫹳𫹴𫹵𫹶𫹷𫹸𫹹𫹺𫹻𫹼𫹽𫹾𫹿𫺀𫺁𫺂𫺃𫺄𫺅𫺆𫺇𫺈𫺉𫺊𫺋𫺌𫺍𫺎𫺏𫺐𫺑𫺒𫺓𫺔𫺕𫺖𫺗𫺘𫺙𫺚𫺛𫺜𫺝𫺞𫺟𫺠𫺡𫺢𫺣𫺤𫺥𫺦𫺧𫺨𫺩𫺪𫺫𫺬𫺭𫺮𫺯𫺰𫺱𫺲𫺳𫺴𫺵𫺶𫺷𫺸𫺹𫺺𫺻𫺼𫺽𫺾𫺿𫻀𫻁𫻂𫻃𫻄𫻅𫻆𫻇𫻈𫻉𫻊𫻋𫻌𫻍𫻎𫻏𫻐𫻑𫻒𫻓𫻔𫻕𫻖𫻗𫻘𫻙𫻚𫻛𫻜𫻝𫻞𫻟𫻠𫻡𫻢𫻣𫻤𫻥𫻦𫻧𫻨𫻩𫻪𫻫𫻬𫻭𫻮𫻯𫻰𫻱𫻲𫻳𫻴𫻵𫻶𫻷𫻸𫻹𫻺𫻻𫻼𫻽𫻾𫻿𫼀𫼁𫼂𫼃𫼄𫼅𫼆𫼇𫼈𫼉𫼊𫼋𫼌𫼍𫼎𫼏𫼐𫼑𫼒𫼓𫼔𫼕𫼖𫼗𫼘𫼙𫼚𫼛𫼜𫼝𫼞𫼟𫼠𫼡𫼢𫼣𫼤𫼥𫼦𫼧𫼨𫼩𫼪𫼫𫼬𫼭𫼮𫼯𫼰𫼱𫼲𫼳𫼴𫼵𫼶𫼷𫼸𫼹𫼺𫼻𫼼𫼽𫼾𫼿𫽀𫽁𫽂𫽃𫽄𫽅𫽆𫽇𫽈𫽉𫽊𫽋𫽌𫽍𫽎𫽏𫽐𫽑𫽒𫽓𫽔𫽕𫽖𫽗𫽘𫽙𫽚𫽛𫽜𫽝𫽞𫽟𫽠𫽡𫽢𫽣𫽤𫽥𫽦𫽧𫽨𫽩𫽪𫽫𫽬𫽭𫽮𫽯𫽰𫽱𫽲𫽳𫽴𫽵𫽶𫽷𫽸𫽹𫽺𫽻𫽼𫽽𫽾𫽿𫾀𫾁𫾂𫾃𫾄𫾅𫾆𫾇𫾈𫾉𫾊𫾋𫾌𫾍𫾎𫾏𫾐𫾑𫾒𫾓𫾔𫾕𫾖𫾗𫾘𫾙𫾚𫾛𫾜𫾝𫾞𫾟𫾠𫾡𫾢𫾣𫾤𫾥𫾦𫾧𫾨𫾩𫾪𫾫𫾬𫾭𫾮𫾯𫾰𫾱𫾲𫾳𫾴𫾵𫾶𫾷𫾸𫾹𫾺𫾻𫾼𫾽𫾾𫾿𫿀𫿁𫿂𫿃𫿄𫿅𫿆𫿇𫿈𫿉𫿊𫿋𫿌𫿍𫿎𫿏𫿐𫿑𫿒𫿓𫿔𫿕𫿖𫿗𫿘𫿙𫿚𫿛𫿜𫿝𫿞𫿟𫿠𫿡𫿢𫿣𫿤𫿥𫿦𫿧𫿨𫿩𫿪𫿫𫿬𫿭𫿮𫿯𫿰𫿱𫿲𫿳𫿴𫿵𫿶𫿷𫿸𫿹𫿺𫿻𫿼𫿽𫿾𫿿𬀀𬀁𬀂𬀃𬀄𬀅𬀆𬀇𬀈𬀉𬀊𬀋𬀌𬀍𬀎𬀏𬀐𬀑𬀒𬀓𬀔𬀕𬀖𬀗𬀘𬀙𬀚𬀛𬀜𬀝𬀞𬀟𬀠𬀡𬀢𬀣𬀤𬀥𬀦𬀧𬀨𬀩𬀪𬀫𬀬𬀭𬀮𬀯𬀰𬀱𬀲𬀳𬀴𬀵𬀶𬀷𬀸𬀹𬀺𬀻𬀼𬀽𬀾𬀿𬁀𬁁𬁂𬁃𬁄𬁅𬁆𬁇𬁈𬁉𬁊𬁋𬁌𬁍𬁎𬁏𬁐𬁑𬁒𬁓𬁔𬁕𬁖𬁗𬁘𬁙𬁚𬁛𬁜𬁝𬁞𬁟𬁠𬁡𬁢𬁣𬁤𬁥𬁦𬁧𬁨𬁩𬁪𬁫𬁬𬁭𬁮𬁯𬁰𬁱𬁲𬁳𬁴𬁵𬁶𬁷𬁸𬁹𬁺𬁻𬁼𬁽𬁾𬁿𬂀𬂁𬂂𬂃𬂄𬂅𬂆𬂇𬂈𬂉𬂊𬂋𬂌𬂍𬂎𬂏𬂐𬂑𬂒𬂓𬂔𬂕𬂖𬂗𬂘𬂙𬂚𬂛𬂜𬂝𬂞𬂟𬂠𬂡𬂢𬂣𬂤𬂥𬂦𬂧𬂨𬂩𬂪𬂫𬂬𬂭𬂮𬂯𬂰𬂱𬂲𬂳𬂴𬂵𬂶𬂷𬂸𬂹𬂺𬂻𬂼𬂽𬂾𬂿𬃀𬃁𬃂𬃃𬃄𬃅𬃆𬃇𬃈𬃉𬃊𬃋𬃌𬃍𬃎𬃏𬃐𬃑𬃒𬃓𬃔𬃕𬃖𬃗𬃘𬃙𬃚𬃛𬃜𬃝𬃞𬃟𬃠𬃡𬃢𬃣𬃤𬃥𬃦𬃧𬃨𬃩𬃪𬃫𬃬𬃭𬃮𬃯𬃰𬃱𬃲𬃳𬃴𬃵𬃶𬃷𬃸𬃹𬃺𬃻𬃼𬃽𬃾𬃿𬄀𬄁𬄂𬄃𬄄𬄅𬄆𬄇𬄈𬄉𬄊𬄋𬄌𬄍𬄎𬄏𬄐𬄑𬄒𬄓𬄔𬄕𬄖𬄗𬄘𬄙𬄚𬄛𬄜𬄝𬄞𬄟𬄠𬄡𬄢𬄣𬄤𬄥𬄦𬄧𬄨𬄩𬄪𬄫𬄬𬄭𬄮𬄯𬄰𬄱𬄲𬄳𬄴𬄵𬄶𬄷𬄸𬄹𬄺𬄻𬄼𬄽𬄾𬄿𬅀𬅁𬅂𬅃𬅄𬅅𬅆𬅇𬅈𬅉𬅊𬅋𬅌𬅍𬅎𬅏𬅐𬅑𬅒𬅓𬅔𬅕𬅖𬅗𬅘𬅙𬅚𬅛𬅜𬅝𬅞𬅟𬅠𬅡𬅢𬅣𬅤𬅥𬅦𬅧𬅨𬅩𬅪𬅫𬅬𬅭𬅮𬅯𬅰𬅱𬅲𬅳𬅴𬅵𬅶𬅷𬅸𬅹𬅺𬅻𬅼𬅽𬅾𬅿𬆀𬆁𬆂𬆃𬆄𬆅𬆆𬆇𬆈𬆉𬆊𬆋𬆌𬆍𬆎𬆏𬆐𬆑𬆒𬆓𬆔𬆕𬆖𬆗𬆘𬆙𬆚𬆛𬆜𬆝𬆞𬆟𬆠𬆡𬆢𬆣𬆤𬆥𬆦𬆧𬆨𬆩𬆪𬆫𬆬𬆭𬆮𬆯𬆰𬆱𬆲𬆳𬆴𬆵𬆶𬆷𬆸𬆹𬆺𬆻𬆼𬆽𬆾𬆿𬇀𬇁𬇂𬇃𬇄𬇅𬇆𬇇𬇈𬇉𬇊𬇋𬇌𬇍𬇎𬇏𬇐𬇑𬇒𬇓𬇔𬇕𬇖𬇗𬇘𬇙𬇚𬇛𬇜𬇝𬇞𬇟𬇠𬇡𬇢𬇣𬇤𬇥𬇦𬇧𬇨𬇩𬇪𬇫𬇬𬇭𬇮𬇯𬇰𬇱𬇲𬇳𬇴𬇵𬇶𬇷𬇸𬇹𬇺𬇻𬇼𬇽𬇾𬇿𬈀𬈁𬈂𬈃𬈄𬈅𬈆𬈇𬈈𬈉𬈊𬈋𬈌𬈍𬈎𬈏𬈐𬈑𬈒𬈓𬈔𬈕𬈖𬈗𬈘𬈙𬈚𬈛𬈜𬈝𬈞𬈟𬈠𬈡𬈢𬈣𬈤𬈥𬈦𬈧𬈨𬈩𬈪𬈫𬈬𬈭𬈮𬈯𬈰𬈱𬈲𬈳𬈴𬈵𬈶𬈷𬈸𬈹𬈺𬈻𬈼𬈽𬈾𬈿𬉀𬉁𬉂𬉃𬉄𬉅𬉆𬉇𬉈𬉉𬉊𬉋𬉌𬉍𬉎𬉏𬉐𬉑𬉒𬉓𬉔𬉕𬉖𬉗𬉘𬉙𬉚𬉛𬉜𬉝𬉞𬉟𬉠𬉡𬉢𬉣𬉤𬉥𬉦𬉧𬉨𬉩𬉪𬉫𬉬𬉭𬉮𬉯𬉰𬉱𬉲𬉳𬉴𬉵𬉶𬉷𬉸𬉹𬉺𬉻𬉼𬉽𬉾𬉿𬊀𬊁𬊂𬊃𬊄𬊅𬊆𬊇𬊈𬊉𬊊𬊋𬊌𬊍𬊎𬊏𬊐𬊑𬊒𬊓𬊔𬊕𬊖𬊗𬊘𬊙𬊚𬊛𬊜𬊝𬊞𬊟𬊠𬊡𬊢𬊣𬊤𬊥𬊦𬊧𬊨𬊩𬊪𬊫𬊬𬊭𬊮𬊯𬊰𬊱𬊲𬊳𬊴𬊵𬊶𬊷𬊸𬊹𬊺𬊻𬊼𬊽𬊾𬊿𬋀𬋁𬋂𬋃𬋄𬋅𬋆𬋇𬋈𬋉𬋊𬋋𬋌𬋍𬋎𬋏𬋐𬋑𬋒𬋓𬋔𬋕𬋖𬋗𬋘𬋙𬋚𬋛𬋜𬋝𬋞𬋟𬋠𬋡𬋢𬋣𬋤𬋥𬋦𬋧𬋨𬋩𬋪𬋫𬋬𬋭𬋮𬋯𬋰𬋱𬋲𬋳𬋴𬋵𬋶𬋷𬋸𬋹𬋺𬋻𬋼𬋽𬋾𬋿𬌀𬌁𬌂𬌃𬌄𬌅𬌆𬌇𬌈𬌉𬌊𬌋𬌌𬌍𬌎𬌏𬌐𬌑𬌒𬌓𬌔𬌕𬌖𬌗𬌘𬌙𬌚𬌛𬌜𬌝𬌞𬌟𬌠𬌡𬌢𬌣𬌤𬌥𬌦𬌧𬌨𬌩𬌪𬌫𬌬𬌭𬌮𬌯𬌰𬌱𬌲𬌳𬌴𬌵𬌶𬌷𬌸𬌹𬌺𬌻𬌼𬌽𬌾𬌿𬍀𬍁𬍂𬍃𬍄𬍅𬍆𬍇𬍈𬍉𬍊𬍋𬍌𬍍𬍎𬍏𬍐𬍑𬍒𬍓𬍔𬍕𬍖𬍗𬍘𬍙𬍚𬍛𬍜𬍝𬍞𬍟𬍠𬍡𬍢𬍣𬍤𬍥𬍦𬍧𬍨𬍩𬍪𬍫𬍬𬍭𬍮𬍯𬍰𬍱𬍲𬍳𬍴𬍵𬍶𬍷𬍸𬍹𬍺𬍻𬍼𬍽𬍾𬍿𬎀𬎁𬎂𬎃𬎄𬎅𬎆𬎇𬎈𬎉𬎊𬎋𬎌𬎍𬎎𬎏𬎐𬎑𬎒𬎓𬎔𬎕𬎖𬎗𬎘𬎙𬎚𬎛𬎜𬎝𬎞𬎟𬎠𬎡𬎢𬎣𬎤𬎥𬎦𬎧𬎨𬎩𬎪𬎫𬎬𬎭𬎮𬎯𬎰𬎱𬎲𬎳𬎴𬎵𬎶𬎷𬎸𬎹𬎺𬎻𬎼𬎽𬎾𬎿𬏀𬏁𬏂𬏃𬏄𬏅𬏆𬏇𬏈𬏉𬏊𬏋𬏌𬏍𬏎𬏏𬏐𬏑𬏒𬏓𬏔𬏕𬏖𬏗𬏘𬏙𬏚𬏛𬏜𬏝𬏞𬏟𬏠𬏡𬏢𬏣𬏤𬏥𬏦𬏧𬏨𬏩𬏪𬏫𬏬𬏭𬏮𬏯𬏰𬏱𬏲𬏳𬏴𬏵𬏶𬏷𬏸𬏹𬏺𬏻𬏼𬏽𬏾𬏿𬐀𬐁𬐂𬐃𬐄𬐅𬐆𬐇𬐈𬐉𬐊𬐋𬐌𬐍𬐎𬐏𬐐𬐑𬐒𬐓𬐔𬐕𬐖𬐗𬐘𬐙𬐚𬐛𬐜𬐝𬐞𬐟𬐠𬐡𬐢𬐣𬐤𬐥𬐦𬐧𬐨𬐩𬐪𬐫𬐬𬐭𬐮𬐯𬐰𬐱𬐲𬐳𬐴𬐵𬐶𬐷𬐸𬐹𬐺𬐻𬐼𬐽𬐾𬐿𬑀𬑁𬑂𬑃𬑄𬑅𬑆𬑇𬑈𬑉𬑊𬑋𬑌𬑍𬑎𬑏𬑐𬑑𬑒𬑓𬑔𬑕𬑖𬑗𬑘𬑙𬑚𬑛𬑜𬑝𬑞𬑟𬑠𬑡𬑢𬑣𬑤𬑥𬑦𬑧𬑨𬑩𬑪𬑫𬑬𬑭𬑮𬑯𬑰𬑱𬑲𬑳𬑴𬑵𬑶𬑷𬑸𬑹𬑺𬑻𬑼𬑽𬑾𬑿𬒀𬒁𬒂𬒃𬒄𬒅𬒆𬒇𬒈𬒉𬒊𬒋𬒌𬒍𬒎𬒏𬒐𬒑𬒒𬒓𬒔𬒕𬒖𬒗𬒘𬒙𬒚𬒛𬒜𬒝𬒞𬒟𬒠𬒡𬒢𬒣𬒤𬒥𬒦𬒧𬒨𬒩𬒪𬒫𬒬𬒭𬒮𬒯𬒰𬒱𬒲𬒳𬒴𬒵𬒶𬒷𬒸𬒹𬒺𬒻𬒼𬒽𬒾𬒿𬓀𬓁𬓂𬓃𬓄𬓅𬓆𬓇𬓈𬓉𬓊𬓋𬓌𬓍𬓎𬓏𬓐𬓑𬓒𬓓𬓔𬓕𬓖𬓗𬓘𬓙𬓚𬓛𬓜𬓝𬓞𬓟𬓠𬓡𬓢𬓣𬓤𬓥𬓦𬓧𬓨𬓩𬓪𬓫𬓬𬓭𬓮𬓯𬓰𬓱𬓲𬓳𬓴𬓵𬓶𬓷𬓸𬓹𬓺𬓻𬓼𬓽𬓾𬓿𬔀𬔁𬔂𬔃𬔄𬔅𬔆𬔇𬔈𬔉𬔊𬔋𬔌𬔍𬔎𬔏𬔐𬔑𬔒𬔓𬔔𬔕𬔖𬔗𬔘𬔙𬔚𬔛𬔜𬔝𬔞𬔟𬔠𬔡𬔢𬔣𬔤𬔥𬔦𬔧𬔨𬔩𬔪𬔫𬔬𬔭𬔮𬔯𬔰𬔱𬔲𬔳𬔴𬔵𬔶𬔷𬔸𬔹𬔺𬔻𬔼𬔽𬔾𬔿𬕀𬕁𬕂𬕃𬕄𬕅𬕆𬕇𬕈𬕉𬕊𬕋𬕌𬕍𬕎𬕏𬕐𬕑𬕒𬕓𬕔𬕕𬕖𬕗𬕘𬕙𬕚𬕛𬕜𬕝𬕞𬕟𬕠𬕡𬕢𬕣𬕤𬕥𬕦𬕧𬕨𬕩𬕪𬕫𬕬𬕭𬕮𬕯𬕰𬕱𬕲𬕳𬕴𬕵𬕶𬕷𬕸𬕹𬕺𬕻𬕼𬕽𬕾𬕿𬖀𬖁𬖂𬖃𬖄𬖅𬖆𬖇𬖈𬖉𬖊𬖋𬖌𬖍𬖎𬖏𬖐𬖑𬖒𬖓𬖔𬖕𬖖𬖗𬖘𬖙𬖚𬖛𬖜𬖝𬖞𬖟𬖠𬖡𬖢𬖣𬖤𬖥𬖦𬖧𬖨𬖩𬖪𬖫𬖬𬖭𬖮𬖯𬖰𬖱𬖲𬖳𬖴𬖵𬖶𬖷𬖸𬖹𬖺𬖻𬖼𬖽𬖾𬖿𬗀𬗁𬗂𬗃𬗄𬗅𬗆𬗇𬗈𬗉𬗊𬗋𬗌𬗍𬗎𬗏𬗐𬗑𬗒𬗓𬗔𬗕𬗖𬗗𬗘𬗙𬗚𬗛𬗜𬗝𬗞𬗟𬗠𬗡𬗢𬗣𬗤𬗥𬗦𬗧𬗨𬗩𬗪𬗫𬗬𬗭𬗮𬗯𬗰𬗱𬗲𬗳𬗴𬗵𬗶𬗷𬗸𬗹𬗺𬗻𬗼𬗽𬗾𬗿𬘀𬘁𬘂𬘃𬘄𬘅𬘆𬘇𬘈𬘉𬘊𬘋𬘌𬘍𬘎𬘏𬘐𬘑𬘒𬘓𬘔𬘕𬘖𬘗𬘘𬘙𬘚𬘛𬘜𬘝𬘞𬘟𬘠𬘡𬘢𬘣𬘤𬘥𬘦𬘧𬘨𬘩𬘪𬘫𬘬𬘭𬘮𬘯𬘰𬘱𬘲𬘳𬘴𬘵𬘶𬘷𬘸𬘹𬘺𬘻𬘼𬘽𬘾𬘿𬙀𬙁𬙂𬙃𬙄𬙅𬙆𬙇𬙈𬙉𬙊𬙋𬙌𬙍𬙎𬙏𬙐𬙑𬙒𬙓𬙔𬙕𬙖𬙗𬙘𬙙𬙚𬙛𬙜𬙝𬙞𬙟𬙠𬙡𬙢𬙣𬙤𬙥𬙦𬙧𬙨𬙩𬙪𬙫𬙬𬙭𬙮𬙯𬙰𬙱𬙲𬙳𬙴𬙵𬙶𬙷𬙸𬙹𬙺𬙻𬙼𬙽𬙾𬙿𬚀𬚁𬚂𬚃𬚄𬚅𬚆𬚇𬚈𬚉𬚊𬚋𬚌𬚍𬚎𬚏𬚐𬚑𬚒𬚓𬚔𬚕𬚖𬚗𬚘𬚙𬚚𬚛𬚜𬚝𬚞𬚟𬚠𬚡𬚢𬚣𬚤𬚥𬚦𬚧𬚨𬚩𬚪𬚫𬚬𬚭𬚮𬚯𬚰𬚱𬚲𬚳𬚴𬚵𬚶𬚷𬚸𬚹𬚺𬚻𬚼𬚽𬚾𬚿𬛀𬛁𬛂𬛃𬛄𬛅𬛆𬛇𬛈𬛉𬛊𬛋𬛌𬛍𬛎𬛏𬛐𬛑𬛒𬛓𬛔𬛕𬛖𬛗𬛘𬛙𬛚𬛛𬛜𬛝𬛞𬛟𬛠𬛡𬛢𬛣𬛤𬛥𬛦𬛧𬛨𬛩𬛪𬛫𬛬𬛭𬛮𬛯𬛰𬛱𬛲𬛳𬛴𬛵𬛶𬛷𬛸𬛹𬛺𬛻𬛼𬛽𬛾𬛿𬜀𬜁𬜂𬜃𬜄𬜅𬜆𬜇𬜈𬜉𬜊𬜋𬜌𬜍𬜎𬜏𬜐𬜑𬜒𬜓𬜔𬜕𬜖𬜗𬜘𬜙𬜚𬜛𬜜𬜝𬜞𬜟𬜠𬜡𬜢𬜣𬜤𬜥𬜦𬜧𬜨𬜩𬜪𬜫𬜬𬜭𬜮𬜯𬜰𬜱𬜲𬜳𬜴𬜵𬜶𬜷𬜸𬜹𬜺𬜻𬜼𬜽𬜾𬜿𬝀𬝁𬝂𬝃𬝄𬝅𬝆𬝇𬝈𬝉𬝊𬝋𬝌𬝍𬝎𬝏𬝐𬝑𬝒𬝓𬝔𬝕𬝖𬝗𬝘𬝙𬝚𬝛𬝜𬝝𬝞𬝟𬝠𬝡𬝢𬝣𬝤𬝥𬝦𬝧𬝨𬝩𬝪𬝫𬝬𬝭𬝮𬝯𬝰𬝱𬝲𬝳𬝴𬝵𬝶𬝷𬝸𬝹𬝺𬝻𬝼𬝽𬝾𬝿𬞀𬞁𬞂𬞃𬞄𬞅𬞆𬞇𬞈𬞉𬞊𬞋𬞌𬞍𬞎𬞏𬞐𬞑𬞒𬞓𬞔𬞕𬞖𬞗𬞘𬞙𬞚𬞛𬞜𬞝𬞞𬞟𬞠𬞡𬞢𬞣𬞤𬞥𬞦𬞧𬞨𬞩𬞪𬞫𬞬𬞭𬞮𬞯𬞰𬞱𬞲𬞳𬞴𬞵𬞶𬞷𬞸𬞹𬞺𬞻𬞼𬞽𬞾𬞿𬟀𬟁𬟂𬟃𬟄𬟅𬟆𬟇𬟈𬟉𬟊𬟋𬟌𬟍𬟎𬟏𬟐𬟑𬟒𬟓𬟔𬟕𬟖𬟗𬟘𬟙𬟚𬟛𬟜𬟝𬟞𬟟𬟠𬟡𬟢𬟣𬟤𬟥𬟦𬟧𬟨𬟩𬟪𬟫𬟬𬟭𬟮𬟯𬟰𬟱𬟲𬟳𬟴𬟵𬟶𬟷𬟸𬟹𬟺𬟻𬟼𬟽𬟾𬟿𬠀𬠁𬠂𬠃𬠄𬠅𬠆𬠇𬠈𬠉𬠊𬠋𬠌𬠍𬠎𬠏𬠐𬠑𬠒𬠓𬠔𬠕𬠖𬠗𬠘𬠙𬠚𬠛𬠜𬠝𬠞𬠟𬠠𬠡𬠢𬠣𬠤𬠥𬠦𬠧𬠨𬠩𬠪𬠫𬠬𬠭𬠮𬠯𬠰𬠱𬠲𬠳𬠴𬠵𬠶𬠷𬠸𬠹𬠺𬠻𬠼𬠽𬠾𬠿𬡀𬡁𬡂𬡃𬡄𬡅𬡆𬡇𬡈𬡉𬡊𬡋𬡌𬡍𬡎𬡏𬡐𬡑𬡒𬡓𬡔𬡕𬡖𬡗𬡘𬡙𬡚𬡛𬡜𬡝𬡞𬡟𬡠𬡡𬡢𬡣𬡤𬡥𬡦𬡧𬡨𬡩𬡪𬡫𬡬𬡭𬡮𬡯𬡰𬡱𬡲𬡳𬡴𬡵𬡶𬡷𬡸𬡹𬡺𬡻𬡼𬡽𬡾𬡿𬢀𬢁𬢂𬢃𬢄𬢅𬢆𬢇𬢈𬢉𬢊𬢋𬢌𬢍𬢎𬢏𬢐𬢑𬢒𬢓𬢔𬢕𬢖𬢗𬢘𬢙𬢚𬢛𬢜𬢝𬢞𬢟𬢠𬢡𬢢𬢣𬢤𬢥𬢦𬢧𬢨𬢩𬢪𬢫𬢬𬢭𬢮𬢯𬢰𬢱𬢲𬢳𬢴𬢵𬢶𬢷𬢸𬢹𬢺𬢻𬢼𬢽𬢾𬢿𬣀𬣁𬣂𬣃𬣄𬣅𬣆𬣇𬣈𬣉𬣊𬣋𬣌𬣍𬣎𬣏𬣐𬣑𬣒𬣓𬣔𬣕𬣖𬣗𬣘𬣙𬣚𬣛𬣜𬣝𬣞𬣟𬣠𬣡𬣢𬣣𬣤𬣥𬣦𬣧𬣨𬣩𬣪𬣫𬣬𬣭𬣮𬣯𬣰𬣱𬣲𬣳𬣴𬣵𬣶𬣷𬣸𬣹𬣺𬣻𬣼𬣽𬣾𬣿𬤀𬤁𬤂𬤃𬤄𬤅𬤆𬤇𬤈𬤉𬤊𬤋𬤌𬤍𬤎𬤏𬤐𬤑𬤒𬤓𬤔𬤕𬤖𬤗𬤘𬤙𬤚𬤛𬤜𬤝𬤞𬤟𬤠𬤡𬤢𬤣𬤤𬤥𬤦𬤧𬤨𬤩𬤪𬤫𬤬𬤭𬤮𬤯𬤰𬤱𬤲𬤳𬤴𬤵𬤶𬤷𬤸𬤹𬤺𬤻𬤼𬤽𬤾𬤿𬥀𬥁𬥂𬥃𬥄𬥅𬥆𬥇𬥈𬥉𬥊𬥋𬥌𬥍𬥎𬥏𬥐𬥑𬥒𬥓𬥔𬥕𬥖𬥗𬥘𬥙𬥚𬥛𬥜𬥝𬥞𬥟𬥠𬥡𬥢𬥣𬥤𬥥𬥦𬥧𬥨𬥩𬥪𬥫𬥬𬥭𬥮𬥯𬥰𬥱𬥲𬥳𬥴𬥵𬥶𬥷𬥸𬥹𬥺𬥻𬥼𬥽𬥾𬥿𬦀𬦁𬦂𬦃𬦄𬦅𬦆𬦇𬦈𬦉𬦊𬦋𬦌𬦍𬦎𬦏𬦐𬦑𬦒𬦓𬦔𬦕𬦖𬦗𬦘𬦙𬦚𬦛𬦜𬦝𬦞𬦟𬦠𬦡𬦢𬦣𬦤𬦥𬦦𬦧𬦨𬦩𬦪𬦫𬦬𬦭𬦮𬦯𬦰𬦱𬦲𬦳𬦴𬦵𬦶𬦷𬦸𬦹𬦺𬦻𬦼𬦽𬦾𬦿𬧀𬧁𬧂𬧃𬧄𬧅𬧆𬧇𬧈𬧉𬧊𬧋𬧌𬧍𬧎𬧏𬧐𬧑𬧒𬧓𬧔𬧕𬧖𬧗𬧘𬧙𬧚𬧛𬧜𬧝𬧞𬧟𬧠𬧡𬧢𬧣𬧤𬧥𬧦𬧧𬧨𬧩𬧪𬧫𬧬𬧭𬧮𬧯𬧰𬧱𬧲𬧳𬧴𬧵𬧶𬧷𬧸𬧹𬧺𬧻𬧼𬧽𬧾𬧿𬨀𬨁𬨂𬨃𬨄𬨅𬨆𬨇𬨈𬨉𬨊𬨋𬨌𬨍𬨎𬨏𬨐𬨑𬨒𬨓𬨔𬨕𬨖𬨗𬨘𬨙𬨚𬨛𬨜𬨝𬨞𬨟𬨠𬨡𬨢𬨣𬨤𬨥𬨦𬨧𬨨𬨩𬨪𬨫𬨬𬨭𬨮𬨯𬨰𬨱𬨲𬨳𬨴𬨵𬨶𬨷𬨸𬨹𬨺𬨻𬨼𬨽𬨾𬨿𬩀𬩁𬩂𬩃𬩄𬩅𬩆𬩇𬩈𬩉𬩊𬩋𬩌𬩍𬩎𬩏𬩐𬩑𬩒𬩓𬩔𬩕𬩖𬩗𬩘𬩙𬩚𬩛𬩜𬩝𬩞𬩟𬩠𬩡𬩢𬩣𬩤𬩥𬩦𬩧𬩨𬩩𬩪𬩫𬩬𬩭𬩮𬩯𬩰𬩱𬩲𬩳𬩴𬩵𬩶𬩷𬩸𬩹𬩺𬩻𬩼𬩽𬩾𬩿𬪀𬪁𬪂𬪃𬪄𬪅𬪆𬪇𬪈𬪉𬪊𬪋𬪌𬪍𬪎𬪏𬪐𬪑𬪒𬪓𬪔𬪕𬪖𬪗𬪘𬪙𬪚𬪛𬪜𬪝𬪞𬪟𬪠𬪡𬪢𬪣𬪤𬪥𬪦𬪧𬪨𬪩𬪪𬪫𬪬𬪭𬪮𬪯𬪰𬪱𬪲𬪳𬪴𬪵𬪶𬪷𬪸𬪹𬪺𬪻𬪼𬪽𬪾𬪿𬫀𬫁𬫂𬫃𬫄𬫅𬫆𬫇𬫈𬫉𬫊𬫋𬫌𬫍𬫎𬫏𬫐𬫑𬫒𬫓𬫔𬫕𬫖𬫗𬫘𬫙𬫚𬫛𬫜𬫝𬫞𬫟𬫠𬫡𬫢𬫣𬫤𬫥𬫦𬫧𬫨𬫩𬫪𬫫𬫬𬫭𬫮𬫯𬫰𬫱𬫲𬫳𬫴𬫵𬫶𬫷𬫸𬫹𬫺𬫻𬫼𬫽𬫾𬫿𬬀𬬁𬬂𬬃𬬄𬬅𬬆𬬇𬬈𬬉𬬊𬬋𬬌𬬍𬬎𬬏𬬐𬬑𬬒𬬓𬬔𬬕𬬖𬬗𬬘𬬙𬬚𬬛𬬜𬬝𬬞𬬟𬬠𬬡𬬢𬬣𬬤𬬥𬬦𬬧𬬨𬬩𬬪𬬫𬬬𬬭𬬮𬬯𬬰𬬱𬬲𬬳𬬴𬬵𬬶𬬷𬬸𬬹𬬺𬬻𬬼𬬽𬬾𬬿𬭀𬭁𬭂𬭃𬭄𬭅𬭆𬭇𬭈𬭉𬭊𬭋𬭌𬭍𬭎𬭏𬭐𬭑𬭒𬭓𬭔𬭕𬭖𬭗𬭘𬭙𬭚𬭛𬭜𬭝𬭞𬭟𬭠𬭡𬭢𬭣𬭤𬭥𬭦𬭧𬭨𬭩𬭪𬭫𬭬𬭭𬭮𬭯𬭰𬭱𬭲𬭳𬭴𬭵𬭶𬭷𬭸𬭹𬭺𬭻𬭼𬭽𬭾𬭿𬮀𬮁𬮂𬮃𬮄𬮅𬮆𬮇𬮈𬮉𬮊𬮋𬮌𬮍𬮎𬮏𬮐𬮑𬮒𬮓𬮔𬮕𬮖𬮗𬮘𬮙𬮚𬮛𬮜𬮝𬮞𬮟𬮠𬮡𬮢𬮣𬮤𬮥𬮦𬮧𬮨𬮩𬮪𬮫𬮬𬮭𬮮𬮯𬮰𬮱𬮲𬮳𬮴𬮵𬮶𬮷𬮸𬮹𬮺𬮻𬮼𬮽𬮾𬮿𬯀𬯁𬯂𬯃𬯄𬯅𬯆𬯇𬯈𬯉𬯊𬯋𬯌𬯍𬯎𬯏𬯐𬯑𬯒𬯓𬯔𬯕𬯖𬯗𬯘𬯙𬯚𬯛𬯜𬯝𬯞𬯟𬯠𬯡𬯢𬯣𬯤𬯥𬯦𬯧𬯨𬯩𬯪𬯫𬯬𬯭𬯮𬯯𬯰𬯱𬯲𬯳𬯴𬯵𬯶𬯷𬯸𬯹𬯺𬯻𬯼𬯽𬯾𬯿𬰀𬰁𬰂𬰃𬰄𬰅𬰆𬰇𬰈𬰉𬰊𬰋𬰌𬰍𬰎𬰏𬰐𬰑𬰒𬰓𬰔𬰕𬰖𬰗𬰘𬰙𬰚𬰛𬰜𬰝𬰞𬰟𬰠𬰡𬰢𬰣𬰤𬰥𬰦𬰧𬰨𬰩𬰪𬰫𬰬𬰭𬰮𬰯𬰰𬰱𬰲𬰳𬰴𬰵𬰶𬰷𬰸𬰹𬰺𬰻𬰼𬰽𬰾𬰿𬱀𬱁𬱂𬱃𬱄𬱅𬱆𬱇𬱈𬱉𬱊𬱋𬱌𬱍𬱎𬱏𬱐𬱑𬱒𬱓𬱔𬱕𬱖𬱗𬱘𬱙𬱚𬱛𬱜𬱝𬱞𬱟𬱠𬱡𬱢𬱣𬱤𬱥𬱦𬱧𬱨𬱩𬱪𬱫𬱬𬱭𬱮𬱯𬱰𬱱𬱲𬱳𬱴𬱵𬱶𬱷𬱸𬱹𬱺𬱻𬱼𬱽𬱾𬱿𬲀𬲁𬲂𬲃𬲄𬲅𬲆𬲇𬲈𬲉𬲊𬲋𬲌𬲍𬲎𬲏𬲐𬲑𬲒𬲓𬲔𬲕𬲖𬲗𬲘𬲙𬲚𬲛𬲜𬲝𬲞𬲟𬲠𬲡𬲢𬲣𬲤𬲥𬲦𬲧𬲨𬲩𬲪𬲫𬲬𬲭𬲮𬲯𬲰𬲱𬲲𬲳𬲴𬲵𬲶𬲷𬲸𬲹𬲺𬲻𬲼𬲽𬲾𬲿𬳀𬳁𬳂𬳃𬳄𬳅𬳆𬳇𬳈𬳉𬳊𬳋𬳌𬳍𬳎𬳏𬳐𬳑𬳒𬳓𬳔𬳕𬳖𬳗𬳘𬳙𬳚𬳛𬳜𬳝𬳞𬳟𬳠𬳡𬳢𬳣𬳤𬳥𬳦𬳧𬳨𬳩𬳪𬳫𬳬𬳭𬳮𬳯𬳰𬳱𬳲𬳳𬳴𬳵𬳶𬳷𬳸𬳹𬳺𬳻𬳼𬳽𬳾𬳿𬴀𬴁𬴂𬴃𬴄𬴅𬴆𬴇𬴈𬴉𬴊𬴋𬴌𬴍𬴎𬴏𬴐𬴑𬴒𬴓𬴔𬴕𬴖𬴗𬴘𬴙𬴚𬴛𬴜𬴝𬴞𬴟𬴠𬴡𬴢𬴣𬴤𬴥𬴦𬴧𬴨𬴩𬴪𬴫𬴬𬴭𬴮𬴯𬴰𬴱𬴲𬴳𬴴𬴵𬴶𬴷𬴸𬴹𬴺𬴻𬴼𬴽𬴾𬴿𬵀𬵁𬵂𬵃𬵄𬵅𬵆𬵇𬵈𬵉𬵊𬵋𬵌𬵍𬵎𬵏𬵐𬵑𬵒𬵓𬵔𬵕𬵖𬵗𬵘𬵙𬵚𬵛𬵜𬵝𬵞𬵟𬵠𬵡𬵢𬵣𬵤𬵥𬵦𬵧𬵨𬵩𬵪𬵫𬵬𬵭𬵮𬵯𬵰𬵱𬵲𬵳𬵴𬵵𬵶𬵷𬵸𬵹𬵺𬵻𬵼𬵽𬵾𬵿𬶀𬶁𬶂𬶃𬶄𬶅𬶆𬶇𬶈𬶉𬶊𬶋𬶌𬶍𬶎𬶏𬶐𬶑𬶒𬶓𬶔𬶕𬶖𬶗𬶘𬶙𬶚𬶛𬶜𬶝𬶞𬶟𬶠𬶡𬶢𬶣𬶤𬶥𬶦𬶧𬶨𬶩𬶪𬶫𬶬𬶭𬶮𬶯𬶰𬶱𬶲𬶳𬶴𬶵𬶶𬶷𬶸𬶹𬶺𬶻𬶼𬶽𬶾𬶿𬷀𬷁𬷂𬷃𬷄𬷅𬷆𬷇𬷈𬷉𬷊𬷋𬷌𬷍𬷎𬷏𬷐𬷑𬷒𬷓𬷔𬷕𬷖𬷗𬷘𬷙𬷚𬷛𬷜𬷝𬷞𬷟𬷠𬷡𬷢𬷣𬷤𬷥𬷦𬷧𬷨𬷩𬷪𬷫𬷬𬷭𬷮𬷯𬷰𬷱𬷲𬷳𬷴𬷵𬷶𬷷𬷸𬷹𬷺𬷻𬷼𬷽𬷾𬷿𬸀𬸁𬸂𬸃𬸄𬸅𬸆𬸇𬸈𬸉𬸊𬸋𬸌𬸍𬸎𬸏𬸐𬸑𬸒𬸓𬸔𬸕𬸖𬸗𬸘𬸙𬸚𬸛𬸜𬸝𬸞𬸟𬸠𬸡𬸢𬸣𬸤𬸥𬸦𬸧𬸨𬸩𬸪𬸫𬸬𬸭𬸮𬸯𬸰𬸱𬸲𬸳𬸴𬸵𬸶𬸷𬸸𬸹𬸺𬸻𬸼𬸽𬸾𬸿𬹀𬹁𬹂𬹃𬹄𬹅𬹆𬹇𬹈𬹉𬹊𬹋𬹌𬹍𬹎𬹏𬹐𬹑𬹒𬹓𬹔𬹕𬹖𬹗𬹘𬹙𬹚𬹛𬹜𬹝𬹞𬹟𬹠𬹡𬹢𬹣𬹤𬹥𬹦𬹧𬹨𬹩𬹪𬹫𬹬𬹭𬹮𬹯𬹰𬹱𬹲𬹳𬹴𬹵𬹶𬹷𬹸𬹹𬹺𬹻𬹼𬹽𬹾𬹿𬺀𬺁𬺂𬺃𬺄𬺅𬺆𬺇𬺈𬺉𬺊𬺋𬺌𬺍𬺎𬺏𬺐𬺑𬺒𬺓𬺔𬺕𬺖𬺗𬺘𬺙𬺚𬺛𬺜𬺝𬺞𬺟𬺠𬺡; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-escaped.js index fbdf9360c75d..c8bddca9cb18 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-8.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-8.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-8.0.0.js index 1e5956403c52..5f2e237fc131 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-8.0.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-8.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-class-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-class-escaped.js new file mode 100644 index 000000000000..4075bfa19724 --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-class-escaped.js @@ -0,0 +1,22 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v9.0.0 ID_Start characters are accepted as + identifier start characters in escaped form, i.e. + - \uXXXX or \u{XXXX} for BMP symbols + - \u{XXXXXX} for astral symbols + in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #\u08B6\u08B7\u08B8\u08B9\u08BA\u08BB\u08BC\u08BD\u0C80\u0D54\u0D55\u0D56\u1C80\u1C81\u1C82\u1C83\u1C84\u1C85\u1C86\u1C87\u1C88\uA7AE\u{104B0}\u{104B1}\u{104B2}\u{104B3}\u{104B4}\u{104B5}\u{104B6}\u{104B7}\u{104B8}\u{104B9}\u{104BA}\u{104BB}\u{104BC}\u{104BD}\u{104BE}\u{104BF}\u{104C0}\u{104C1}\u{104C2}\u{104C3}\u{104C4}\u{104C5}\u{104C6}\u{104C7}\u{104C8}\u{104C9}\u{104CA}\u{104CB}\u{104CC}\u{104CD}\u{104CE}\u{104CF}\u{104D0}\u{104D1}\u{104D2}\u{104D3}\u{104D8}\u{104D9}\u{104DA}\u{104DB}\u{104DC}\u{104DD}\u{104DE}\u{104DF}\u{104E0}\u{104E1}\u{104E2}\u{104E3}\u{104E4}\u{104E5}\u{104E6}\u{104E7}\u{104E8}\u{104E9}\u{104EA}\u{104EB}\u{104EC}\u{104ED}\u{104EE}\u{104EF}\u{104F0}\u{104F1}\u{104F2}\u{104F3}\u{104F4}\u{104F5}\u{104F6}\u{104F7}\u{104F8}\u{104F9}\u{104FA}\u{104FB}\u{11400}\u{11401}\u{11402}\u{11403}\u{11404}\u{11405}\u{11406}\u{11407}\u{11408}\u{11409}\u{1140A}\u{1140B}\u{1140C}\u{1140D}\u{1140E}\u{1140F}\u{11410}\u{11411}\u{11412}\u{11413}\u{11414}\u{11415}\u{11416}\u{11417}\u{11418}\u{11419}\u{1141A}\u{1141B}\u{1141C}\u{1141D}\u{1141E}\u{1141F}\u{11420}\u{11421}\u{11422}\u{11423}\u{11424}\u{11425}\u{11426}\u{11427}\u{11428}\u{11429}\u{1142A}\u{1142B}\u{1142C}\u{1142D}\u{1142E}\u{1142F}\u{11430}\u{11431}\u{11432}\u{11433}\u{11434}\u{11447}\u{11448}\u{11449}\u{1144A}\u{11C00}\u{11C01}\u{11C02}\u{11C03}\u{11C04}\u{11C05}\u{11C06}\u{11C07}\u{11C08}\u{11C0A}\u{11C0B}\u{11C0C}\u{11C0D}\u{11C0E}\u{11C0F}\u{11C10}\u{11C11}\u{11C12}\u{11C13}\u{11C14}\u{11C15}\u{11C16}\u{11C17}\u{11C18}\u{11C19}\u{11C1A}\u{11C1B}\u{11C1C}\u{11C1D}\u{11C1E}\u{11C1F}\u{11C20}\u{11C21}\u{11C22}\u{11C23}\u{11C24}\u{11C25}\u{11C26}\u{11C27}\u{11C28}\u{11C29}\u{11C2A}\u{11C2B}\u{11C2C}\u{11C2D}\u{11C2E}\u{11C40}\u{11C72}\u{11C73}\u{11C74}\u{11C75}\u{11C76}\u{11C77}\u{11C78}\u{11C79}\u{11C7A}\u{11C7B}\u{11C7C}\u{11C7D}\u{11C7E}\u{11C7F}\u{11C80}\u{11C81}\u{11C82}\u{11C83}\u{11C84}\u{11C85}\u{11C86}\u{11C87}\u{11C88}\u{11C89}\u{11C8A}\u{11C8B}\u{11C8C}\u{11C8D}\u{11C8E}\u{11C8F}\u{16FE0}\u{17000}\u{17001}\u{17002}\u{17003}\u{17004}\u{17005}\u{17006}\u{17007}\u{17008}\u{17009}\u{1700A}\u{1700B}\u{1700C}\u{1700D}\u{1700E}\u{1700F}\u{17010}\u{17011}\u{17012}\u{17013}\u{17014}\u{17015}\u{17016}\u{17017}\u{17018}\u{17019}\u{1701A}\u{1701B}\u{1701C}\u{1701D}\u{1701E}\u{1701F}\u{17020}\u{17021}\u{17022}\u{17023}\u{17024}\u{17025}\u{17026}\u{17027}\u{17028}\u{17029}\u{1702A}\u{1702B}\u{1702C}\u{1702D}\u{1702E}\u{1702F}\u{17030}\u{17031}\u{17032}\u{17033}\u{17034}\u{17035}\u{17036}\u{17037}\u{17038}\u{17039}\u{1703A}\u{1703B}\u{1703C}\u{1703D}\u{1703E}\u{1703F}\u{17040}\u{17041}\u{17042}\u{17043}\u{17044}\u{17045}\u{17046}\u{17047}\u{17048}\u{17049}\u{1704A}\u{1704B}\u{1704C}\u{1704D}\u{1704E}\u{1704F}\u{17050}\u{17051}\u{17052}\u{17053}\u{17054}\u{17055}\u{17056}\u{17057}\u{17058}\u{17059}\u{1705A}\u{1705B}\u{1705C}\u{1705D}\u{1705E}\u{1705F}\u{17060}\u{17061}\u{17062}\u{17063}\u{17064}\u{17065}\u{17066}\u{17067}\u{17068}\u{17069}\u{1706A}\u{1706B}\u{1706C}\u{1706D}\u{1706E}\u{1706F}\u{17070}\u{17071}\u{17072}\u{17073}\u{17074}\u{17075}\u{17076}\u{17077}\u{17078}\u{17079}\u{1707A}\u{1707B}\u{1707C}\u{1707D}\u{1707E}\u{1707F}\u{17080}\u{17081}\u{17082}\u{17083}\u{17084}\u{17085}\u{17086}\u{17087}\u{17088}\u{17089}\u{1708A}\u{1708B}\u{1708C}\u{1708D}\u{1708E}\u{1708F}\u{17090}\u{17091}\u{17092}\u{17093}\u{17094}\u{17095}\u{17096}\u{17097}\u{17098}\u{17099}\u{1709A}\u{1709B}\u{1709C}\u{1709D}\u{1709E}\u{1709F}\u{170A0}\u{170A1}\u{170A2}\u{170A3}\u{170A4}\u{170A5}\u{170A6}\u{170A7}\u{170A8}\u{170A9}\u{170AA}\u{170AB}\u{170AC}\u{170AD}\u{170AE}\u{170AF}\u{170B0}\u{170B1}\u{170B2}\u{170B3}\u{170B4}\u{170B5}\u{170B6}\u{170B7}\u{170B8}\u{170B9}\u{170BA}\u{170BB}\u{170BC}\u{170BD}\u{170BE}\u{170BF}\u{170C0}\u{170C1}\u{170C2}\u{170C3}\u{170C4}\u{170C5}\u{170C6}\u{170C7}\u{170C8}\u{170C9}\u{170CA}\u{170CB}\u{170CC}\u{170CD}\u{170CE}\u{170CF}\u{170D0}\u{170D1}\u{170D2}\u{170D3}\u{170D4}\u{170D5}\u{170D6}\u{170D7}\u{170D8}\u{170D9}\u{170DA}\u{170DB}\u{170DC}\u{170DD}\u{170DE}\u{170DF}\u{170E0}\u{170E1}\u{170E2}\u{170E3}\u{170E4}\u{170E5}\u{170E6}\u{170E7}\u{170E8}\u{170E9}\u{170EA}\u{170EB}\u{170EC}\u{170ED}\u{170EE}\u{170EF}\u{170F0}\u{170F1}\u{170F2}\u{170F3}\u{170F4}\u{170F5}\u{170F6}\u{170F7}\u{170F8}\u{170F9}\u{170FA}\u{170FB}\u{170FC}\u{170FD}\u{170FE}\u{170FF}\u{17100}\u{17101}\u{17102}\u{17103}\u{17104}\u{17105}\u{17106}\u{17107}\u{17108}\u{17109}\u{1710A}\u{1710B}\u{1710C}\u{1710D}\u{1710E}\u{1710F}\u{17110}\u{17111}\u{17112}\u{17113}\u{17114}\u{17115}\u{17116}\u{17117}\u{17118}\u{17119}\u{1711A}\u{1711B}\u{1711C}\u{1711D}\u{1711E}\u{1711F}\u{17120}\u{17121}\u{17122}\u{17123}\u{17124}\u{17125}\u{17126}\u{17127}\u{17128}\u{17129}\u{1712A}\u{1712B}\u{1712C}\u{1712D}\u{1712E}\u{1712F}\u{17130}\u{17131}\u{17132}\u{17133}\u{17134}\u{17135}\u{17136}\u{17137}\u{17138}\u{17139}\u{1713A}\u{1713B}\u{1713C}\u{1713D}\u{1713E}\u{1713F}\u{17140}\u{17141}\u{17142}\u{17143}\u{17144}\u{17145}\u{17146}\u{17147}\u{17148}\u{17149}\u{1714A}\u{1714B}\u{1714C}\u{1714D}\u{1714E}\u{1714F}\u{17150}\u{17151}\u{17152}\u{17153}\u{17154}\u{17155}\u{17156}\u{17157}\u{17158}\u{17159}\u{1715A}\u{1715B}\u{1715C}\u{1715D}\u{1715E}\u{1715F}\u{17160}\u{17161}\u{17162}\u{17163}\u{17164}\u{17165}\u{17166}\u{17167}\u{17168}\u{17169}\u{1716A}\u{1716B}\u{1716C}\u{1716D}\u{1716E}\u{1716F}\u{17170}\u{17171}\u{17172}\u{17173}\u{17174}\u{17175}\u{17176}\u{17177}\u{17178}\u{17179}\u{1717A}\u{1717B}\u{1717C}\u{1717D}\u{1717E}\u{1717F}\u{17180}\u{17181}\u{17182}\u{17183}\u{17184}\u{17185}\u{17186}\u{17187}\u{17188}\u{17189}\u{1718A}\u{1718B}\u{1718C}\u{1718D}\u{1718E}\u{1718F}\u{17190}\u{17191}\u{17192}\u{17193}\u{17194}\u{17195}\u{17196}\u{17197}\u{17198}\u{17199}\u{1719A}\u{1719B}\u{1719C}\u{1719D}\u{1719E}\u{1719F}\u{171A0}\u{171A1}\u{171A2}\u{171A3}\u{171A4}\u{171A5}\u{171A6}\u{171A7}\u{171A8}\u{171A9}\u{171AA}\u{171AB}\u{171AC}\u{171AD}\u{171AE}\u{171AF}\u{171B0}\u{171B1}\u{171B2}\u{171B3}\u{171B4}\u{171B5}\u{171B6}\u{171B7}\u{171B8}\u{171B9}\u{171BA}\u{171BB}\u{171BC}\u{171BD}\u{171BE}\u{171BF}\u{171C0}\u{171C1}\u{171C2}\u{171C3}\u{171C4}\u{171C5}\u{171C6}\u{171C7}\u{171C8}\u{171C9}\u{171CA}\u{171CB}\u{171CC}\u{171CD}\u{171CE}\u{171CF}\u{171D0}\u{171D1}\u{171D2}\u{171D3}\u{171D4}\u{171D5}\u{171D6}\u{171D7}\u{171D8}\u{171D9}\u{171DA}\u{171DB}\u{171DC}\u{171DD}\u{171DE}\u{171DF}\u{171E0}\u{171E1}\u{171E2}\u{171E3}\u{171E4}\u{171E5}\u{171E6}\u{171E7}\u{171E8}\u{171E9}\u{171EA}\u{171EB}\u{171EC}\u{171ED}\u{171EE}\u{171EF}\u{171F0}\u{171F1}\u{171F2}\u{171F3}\u{171F4}\u{171F5}\u{171F6}\u{171F7}\u{171F8}\u{171F9}\u{171FA}\u{171FB}\u{171FC}\u{171FD}\u{171FE}\u{171FF}\u{17200}\u{17201}\u{17202}\u{17203}\u{17204}\u{17205}\u{17206}\u{17207}\u{17208}\u{17209}\u{1720A}\u{1720B}\u{1720C}\u{1720D}\u{1720E}\u{1720F}\u{17210}\u{17211}\u{17212}\u{17213}\u{17214}\u{17215}\u{17216}\u{17217}\u{17218}\u{17219}\u{1721A}\u{1721B}\u{1721C}\u{1721D}\u{1721E}\u{1721F}\u{17220}\u{17221}\u{17222}\u{17223}\u{17224}\u{17225}\u{17226}\u{17227}\u{17228}\u{17229}\u{1722A}\u{1722B}\u{1722C}\u{1722D}\u{1722E}\u{1722F}\u{17230}\u{17231}\u{17232}\u{17233}\u{17234}\u{17235}\u{17236}\u{17237}\u{17238}\u{17239}\u{1723A}\u{1723B}\u{1723C}\u{1723D}\u{1723E}\u{1723F}\u{17240}\u{17241}\u{17242}\u{17243}\u{17244}\u{17245}\u{17246}\u{17247}\u{17248}\u{17249}\u{1724A}\u{1724B}\u{1724C}\u{1724D}\u{1724E}\u{1724F}\u{17250}\u{17251}\u{17252}\u{17253}\u{17254}\u{17255}\u{17256}\u{17257}\u{17258}\u{17259}\u{1725A}\u{1725B}\u{1725C}\u{1725D}\u{1725E}\u{1725F}\u{17260}\u{17261}\u{17262}\u{17263}\u{17264}\u{17265}\u{17266}\u{17267}\u{17268}\u{17269}\u{1726A}\u{1726B}\u{1726C}\u{1726D}\u{1726E}\u{1726F}\u{17270}\u{17271}\u{17272}\u{17273}\u{17274}\u{17275}\u{17276}\u{17277}\u{17278}\u{17279}\u{1727A}\u{1727B}\u{1727C}\u{1727D}\u{1727E}\u{1727F}\u{17280}\u{17281}\u{17282}\u{17283}\u{17284}\u{17285}\u{17286}\u{17287}\u{17288}\u{17289}\u{1728A}\u{1728B}\u{1728C}\u{1728D}\u{1728E}\u{1728F}\u{17290}\u{17291}\u{17292}\u{17293}\u{17294}\u{17295}\u{17296}\u{17297}\u{17298}\u{17299}\u{1729A}\u{1729B}\u{1729C}\u{1729D}\u{1729E}\u{1729F}\u{172A0}\u{172A1}\u{172A2}\u{172A3}\u{172A4}\u{172A5}\u{172A6}\u{172A7}\u{172A8}\u{172A9}\u{172AA}\u{172AB}\u{172AC}\u{172AD}\u{172AE}\u{172AF}\u{172B0}\u{172B1}\u{172B2}\u{172B3}\u{172B4}\u{172B5}\u{172B6}\u{172B7}\u{172B8}\u{172B9}\u{172BA}\u{172BB}\u{172BC}\u{172BD}\u{172BE}\u{172BF}\u{172C0}\u{172C1}\u{172C2}\u{172C3}\u{172C4}\u{172C5}\u{172C6}\u{172C7}\u{172C8}\u{172C9}\u{172CA}\u{172CB}\u{172CC}\u{172CD}\u{172CE}\u{172CF}\u{172D0}\u{172D1}\u{172D2}\u{172D3}\u{172D4}\u{172D5}\u{172D6}\u{172D7}\u{172D8}\u{172D9}\u{172DA}\u{172DB}\u{172DC}\u{172DD}\u{172DE}\u{172DF}\u{172E0}\u{172E1}\u{172E2}\u{172E3}\u{172E4}\u{172E5}\u{172E6}\u{172E7}\u{172E8}\u{172E9}\u{172EA}\u{172EB}\u{172EC}\u{172ED}\u{172EE}\u{172EF}\u{172F0}\u{172F1}\u{172F2}\u{172F3}\u{172F4}\u{172F5}\u{172F6}\u{172F7}\u{172F8}\u{172F9}\u{172FA}\u{172FB}\u{172FC}\u{172FD}\u{172FE}\u{172FF}\u{17300}\u{17301}\u{17302}\u{17303}\u{17304}\u{17305}\u{17306}\u{17307}\u{17308}\u{17309}\u{1730A}\u{1730B}\u{1730C}\u{1730D}\u{1730E}\u{1730F}\u{17310}\u{17311}\u{17312}\u{17313}\u{17314}\u{17315}\u{17316}\u{17317}\u{17318}\u{17319}\u{1731A}\u{1731B}\u{1731C}\u{1731D}\u{1731E}\u{1731F}\u{17320}\u{17321}\u{17322}\u{17323}\u{17324}\u{17325}\u{17326}\u{17327}\u{17328}\u{17329}\u{1732A}\u{1732B}\u{1732C}\u{1732D}\u{1732E}\u{1732F}\u{17330}\u{17331}\u{17332}\u{17333}\u{17334}\u{17335}\u{17336}\u{17337}\u{17338}\u{17339}\u{1733A}\u{1733B}\u{1733C}\u{1733D}\u{1733E}\u{1733F}\u{17340}\u{17341}\u{17342}\u{17343}\u{17344}\u{17345}\u{17346}\u{17347}\u{17348}\u{17349}\u{1734A}\u{1734B}\u{1734C}\u{1734D}\u{1734E}\u{1734F}\u{17350}\u{17351}\u{17352}\u{17353}\u{17354}\u{17355}\u{17356}\u{17357}\u{17358}\u{17359}\u{1735A}\u{1735B}\u{1735C}\u{1735D}\u{1735E}\u{1735F}\u{17360}\u{17361}\u{17362}\u{17363}\u{17364}\u{17365}\u{17366}\u{17367}\u{17368}\u{17369}\u{1736A}\u{1736B}\u{1736C}\u{1736D}\u{1736E}\u{1736F}\u{17370}\u{17371}\u{17372}\u{17373}\u{17374}\u{17375}\u{17376}\u{17377}\u{17378}\u{17379}\u{1737A}\u{1737B}\u{1737C}\u{1737D}\u{1737E}\u{1737F}\u{17380}\u{17381}\u{17382}\u{17383}\u{17384}\u{17385}\u{17386}\u{17387}\u{17388}\u{17389}\u{1738A}\u{1738B}\u{1738C}\u{1738D}\u{1738E}\u{1738F}\u{17390}\u{17391}\u{17392}\u{17393}\u{17394}\u{17395}\u{17396}\u{17397}\u{17398}\u{17399}\u{1739A}\u{1739B}\u{1739C}\u{1739D}\u{1739E}\u{1739F}\u{173A0}\u{173A1}\u{173A2}\u{173A3}\u{173A4}\u{173A5}\u{173A6}\u{173A7}\u{173A8}\u{173A9}\u{173AA}\u{173AB}\u{173AC}\u{173AD}\u{173AE}\u{173AF}\u{173B0}\u{173B1}\u{173B2}\u{173B3}\u{173B4}\u{173B5}\u{173B6}\u{173B7}\u{173B8}\u{173B9}\u{173BA}\u{173BB}\u{173BC}\u{173BD}\u{173BE}\u{173BF}\u{173C0}\u{173C1}\u{173C2}\u{173C3}\u{173C4}\u{173C5}\u{173C6}\u{173C7}\u{173C8}\u{173C9}\u{173CA}\u{173CB}\u{173CC}\u{173CD}\u{173CE}\u{173CF}\u{173D0}\u{173D1}\u{173D2}\u{173D3}\u{173D4}\u{173D5}\u{173D6}\u{173D7}\u{173D8}\u{173D9}\u{173DA}\u{173DB}\u{173DC}\u{173DD}\u{173DE}\u{173DF}\u{173E0}\u{173E1}\u{173E2}\u{173E3}\u{173E4}\u{173E5}\u{173E6}\u{173E7}\u{173E8}\u{173E9}\u{173EA}\u{173EB}\u{173EC}\u{173ED}\u{173EE}\u{173EF}\u{173F0}\u{173F1}\u{173F2}\u{173F3}\u{173F4}\u{173F5}\u{173F6}\u{173F7}\u{173F8}\u{173F9}\u{173FA}\u{173FB}\u{173FC}\u{173FD}\u{173FE}\u{173FF}\u{17400}\u{17401}\u{17402}\u{17403}\u{17404}\u{17405}\u{17406}\u{17407}\u{17408}\u{17409}\u{1740A}\u{1740B}\u{1740C}\u{1740D}\u{1740E}\u{1740F}\u{17410}\u{17411}\u{17412}\u{17413}\u{17414}\u{17415}\u{17416}\u{17417}\u{17418}\u{17419}\u{1741A}\u{1741B}\u{1741C}\u{1741D}\u{1741E}\u{1741F}\u{17420}\u{17421}\u{17422}\u{17423}\u{17424}\u{17425}\u{17426}\u{17427}\u{17428}\u{17429}\u{1742A}\u{1742B}\u{1742C}\u{1742D}\u{1742E}\u{1742F}\u{17430}\u{17431}\u{17432}\u{17433}\u{17434}\u{17435}\u{17436}\u{17437}\u{17438}\u{17439}\u{1743A}\u{1743B}\u{1743C}\u{1743D}\u{1743E}\u{1743F}\u{17440}\u{17441}\u{17442}\u{17443}\u{17444}\u{17445}\u{17446}\u{17447}\u{17448}\u{17449}\u{1744A}\u{1744B}\u{1744C}\u{1744D}\u{1744E}\u{1744F}\u{17450}\u{17451}\u{17452}\u{17453}\u{17454}\u{17455}\u{17456}\u{17457}\u{17458}\u{17459}\u{1745A}\u{1745B}\u{1745C}\u{1745D}\u{1745E}\u{1745F}\u{17460}\u{17461}\u{17462}\u{17463}\u{17464}\u{17465}\u{17466}\u{17467}\u{17468}\u{17469}\u{1746A}\u{1746B}\u{1746C}\u{1746D}\u{1746E}\u{1746F}\u{17470}\u{17471}\u{17472}\u{17473}\u{17474}\u{17475}\u{17476}\u{17477}\u{17478}\u{17479}\u{1747A}\u{1747B}\u{1747C}\u{1747D}\u{1747E}\u{1747F}\u{17480}\u{17481}\u{17482}\u{17483}\u{17484}\u{17485}\u{17486}\u{17487}\u{17488}\u{17489}\u{1748A}\u{1748B}\u{1748C}\u{1748D}\u{1748E}\u{1748F}\u{17490}\u{17491}\u{17492}\u{17493}\u{17494}\u{17495}\u{17496}\u{17497}\u{17498}\u{17499}\u{1749A}\u{1749B}\u{1749C}\u{1749D}\u{1749E}\u{1749F}\u{174A0}\u{174A1}\u{174A2}\u{174A3}\u{174A4}\u{174A5}\u{174A6}\u{174A7}\u{174A8}\u{174A9}\u{174AA}\u{174AB}\u{174AC}\u{174AD}\u{174AE}\u{174AF}\u{174B0}\u{174B1}\u{174B2}\u{174B3}\u{174B4}\u{174B5}\u{174B6}\u{174B7}\u{174B8}\u{174B9}\u{174BA}\u{174BB}\u{174BC}\u{174BD}\u{174BE}\u{174BF}\u{174C0}\u{174C1}\u{174C2}\u{174C3}\u{174C4}\u{174C5}\u{174C6}\u{174C7}\u{174C8}\u{174C9}\u{174CA}\u{174CB}\u{174CC}\u{174CD}\u{174CE}\u{174CF}\u{174D0}\u{174D1}\u{174D2}\u{174D3}\u{174D4}\u{174D5}\u{174D6}\u{174D7}\u{174D8}\u{174D9}\u{174DA}\u{174DB}\u{174DC}\u{174DD}\u{174DE}\u{174DF}\u{174E0}\u{174E1}\u{174E2}\u{174E3}\u{174E4}\u{174E5}\u{174E6}\u{174E7}\u{174E8}\u{174E9}\u{174EA}\u{174EB}\u{174EC}\u{174ED}\u{174EE}\u{174EF}\u{174F0}\u{174F1}\u{174F2}\u{174F3}\u{174F4}\u{174F5}\u{174F6}\u{174F7}\u{174F8}\u{174F9}\u{174FA}\u{174FB}\u{174FC}\u{174FD}\u{174FE}\u{174FF}\u{17500}\u{17501}\u{17502}\u{17503}\u{17504}\u{17505}\u{17506}\u{17507}\u{17508}\u{17509}\u{1750A}\u{1750B}\u{1750C}\u{1750D}\u{1750E}\u{1750F}\u{17510}\u{17511}\u{17512}\u{17513}\u{17514}\u{17515}\u{17516}\u{17517}\u{17518}\u{17519}\u{1751A}\u{1751B}\u{1751C}\u{1751D}\u{1751E}\u{1751F}\u{17520}\u{17521}\u{17522}\u{17523}\u{17524}\u{17525}\u{17526}\u{17527}\u{17528}\u{17529}\u{1752A}\u{1752B}\u{1752C}\u{1752D}\u{1752E}\u{1752F}\u{17530}\u{17531}\u{17532}\u{17533}\u{17534}\u{17535}\u{17536}\u{17537}\u{17538}\u{17539}\u{1753A}\u{1753B}\u{1753C}\u{1753D}\u{1753E}\u{1753F}\u{17540}\u{17541}\u{17542}\u{17543}\u{17544}\u{17545}\u{17546}\u{17547}\u{17548}\u{17549}\u{1754A}\u{1754B}\u{1754C}\u{1754D}\u{1754E}\u{1754F}\u{17550}\u{17551}\u{17552}\u{17553}\u{17554}\u{17555}\u{17556}\u{17557}\u{17558}\u{17559}\u{1755A}\u{1755B}\u{1755C}\u{1755D}\u{1755E}\u{1755F}\u{17560}\u{17561}\u{17562}\u{17563}\u{17564}\u{17565}\u{17566}\u{17567}\u{17568}\u{17569}\u{1756A}\u{1756B}\u{1756C}\u{1756D}\u{1756E}\u{1756F}\u{17570}\u{17571}\u{17572}\u{17573}\u{17574}\u{17575}\u{17576}\u{17577}\u{17578}\u{17579}\u{1757A}\u{1757B}\u{1757C}\u{1757D}\u{1757E}\u{1757F}\u{17580}\u{17581}\u{17582}\u{17583}\u{17584}\u{17585}\u{17586}\u{17587}\u{17588}\u{17589}\u{1758A}\u{1758B}\u{1758C}\u{1758D}\u{1758E}\u{1758F}\u{17590}\u{17591}\u{17592}\u{17593}\u{17594}\u{17595}\u{17596}\u{17597}\u{17598}\u{17599}\u{1759A}\u{1759B}\u{1759C}\u{1759D}\u{1759E}\u{1759F}\u{175A0}\u{175A1}\u{175A2}\u{175A3}\u{175A4}\u{175A5}\u{175A6}\u{175A7}\u{175A8}\u{175A9}\u{175AA}\u{175AB}\u{175AC}\u{175AD}\u{175AE}\u{175AF}\u{175B0}\u{175B1}\u{175B2}\u{175B3}\u{175B4}\u{175B5}\u{175B6}\u{175B7}\u{175B8}\u{175B9}\u{175BA}\u{175BB}\u{175BC}\u{175BD}\u{175BE}\u{175BF}\u{175C0}\u{175C1}\u{175C2}\u{175C3}\u{175C4}\u{175C5}\u{175C6}\u{175C7}\u{175C8}\u{175C9}\u{175CA}\u{175CB}\u{175CC}\u{175CD}\u{175CE}\u{175CF}\u{175D0}\u{175D1}\u{175D2}\u{175D3}\u{175D4}\u{175D5}\u{175D6}\u{175D7}\u{175D8}\u{175D9}\u{175DA}\u{175DB}\u{175DC}\u{175DD}\u{175DE}\u{175DF}\u{175E0}\u{175E1}\u{175E2}\u{175E3}\u{175E4}\u{175E5}\u{175E6}\u{175E7}\u{175E8}\u{175E9}\u{175EA}\u{175EB}\u{175EC}\u{175ED}\u{175EE}\u{175EF}\u{175F0}\u{175F1}\u{175F2}\u{175F3}\u{175F4}\u{175F5}\u{175F6}\u{175F7}\u{175F8}\u{175F9}\u{175FA}\u{175FB}\u{175FC}\u{175FD}\u{175FE}\u{175FF}\u{17600}\u{17601}\u{17602}\u{17603}\u{17604}\u{17605}\u{17606}\u{17607}\u{17608}\u{17609}\u{1760A}\u{1760B}\u{1760C}\u{1760D}\u{1760E}\u{1760F}\u{17610}\u{17611}\u{17612}\u{17613}\u{17614}\u{17615}\u{17616}\u{17617}\u{17618}\u{17619}\u{1761A}\u{1761B}\u{1761C}\u{1761D}\u{1761E}\u{1761F}\u{17620}\u{17621}\u{17622}\u{17623}\u{17624}\u{17625}\u{17626}\u{17627}\u{17628}\u{17629}\u{1762A}\u{1762B}\u{1762C}\u{1762D}\u{1762E}\u{1762F}\u{17630}\u{17631}\u{17632}\u{17633}\u{17634}\u{17635}\u{17636}\u{17637}\u{17638}\u{17639}\u{1763A}\u{1763B}\u{1763C}\u{1763D}\u{1763E}\u{1763F}\u{17640}\u{17641}\u{17642}\u{17643}\u{17644}\u{17645}\u{17646}\u{17647}\u{17648}\u{17649}\u{1764A}\u{1764B}\u{1764C}\u{1764D}\u{1764E}\u{1764F}\u{17650}\u{17651}\u{17652}\u{17653}\u{17654}\u{17655}\u{17656}\u{17657}\u{17658}\u{17659}\u{1765A}\u{1765B}\u{1765C}\u{1765D}\u{1765E}\u{1765F}\u{17660}\u{17661}\u{17662}\u{17663}\u{17664}\u{17665}\u{17666}\u{17667}\u{17668}\u{17669}\u{1766A}\u{1766B}\u{1766C}\u{1766D}\u{1766E}\u{1766F}\u{17670}\u{17671}\u{17672}\u{17673}\u{17674}\u{17675}\u{17676}\u{17677}\u{17678}\u{17679}\u{1767A}\u{1767B}\u{1767C}\u{1767D}\u{1767E}\u{1767F}\u{17680}\u{17681}\u{17682}\u{17683}\u{17684}\u{17685}\u{17686}\u{17687}\u{17688}\u{17689}\u{1768A}\u{1768B}\u{1768C}\u{1768D}\u{1768E}\u{1768F}\u{17690}\u{17691}\u{17692}\u{17693}\u{17694}\u{17695}\u{17696}\u{17697}\u{17698}\u{17699}\u{1769A}\u{1769B}\u{1769C}\u{1769D}\u{1769E}\u{1769F}\u{176A0}\u{176A1}\u{176A2}\u{176A3}\u{176A4}\u{176A5}\u{176A6}\u{176A7}\u{176A8}\u{176A9}\u{176AA}\u{176AB}\u{176AC}\u{176AD}\u{176AE}\u{176AF}\u{176B0}\u{176B1}\u{176B2}\u{176B3}\u{176B4}\u{176B5}\u{176B6}\u{176B7}\u{176B8}\u{176B9}\u{176BA}\u{176BB}\u{176BC}\u{176BD}\u{176BE}\u{176BF}\u{176C0}\u{176C1}\u{176C2}\u{176C3}\u{176C4}\u{176C5}\u{176C6}\u{176C7}\u{176C8}\u{176C9}\u{176CA}\u{176CB}\u{176CC}\u{176CD}\u{176CE}\u{176CF}\u{176D0}\u{176D1}\u{176D2}\u{176D3}\u{176D4}\u{176D5}\u{176D6}\u{176D7}\u{176D8}\u{176D9}\u{176DA}\u{176DB}\u{176DC}\u{176DD}\u{176DE}\u{176DF}\u{176E0}\u{176E1}\u{176E2}\u{176E3}\u{176E4}\u{176E5}\u{176E6}\u{176E7}\u{176E8}\u{176E9}\u{176EA}\u{176EB}\u{176EC}\u{176ED}\u{176EE}\u{176EF}\u{176F0}\u{176F1}\u{176F2}\u{176F3}\u{176F4}\u{176F5}\u{176F6}\u{176F7}\u{176F8}\u{176F9}\u{176FA}\u{176FB}\u{176FC}\u{176FD}\u{176FE}\u{176FF}\u{17700}\u{17701}\u{17702}\u{17703}\u{17704}\u{17705}\u{17706}\u{17707}\u{17708}\u{17709}\u{1770A}\u{1770B}\u{1770C}\u{1770D}\u{1770E}\u{1770F}\u{17710}\u{17711}\u{17712}\u{17713}\u{17714}\u{17715}\u{17716}\u{17717}\u{17718}\u{17719}\u{1771A}\u{1771B}\u{1771C}\u{1771D}\u{1771E}\u{1771F}\u{17720}\u{17721}\u{17722}\u{17723}\u{17724}\u{17725}\u{17726}\u{17727}\u{17728}\u{17729}\u{1772A}\u{1772B}\u{1772C}\u{1772D}\u{1772E}\u{1772F}\u{17730}\u{17731}\u{17732}\u{17733}\u{17734}\u{17735}\u{17736}\u{17737}\u{17738}\u{17739}\u{1773A}\u{1773B}\u{1773C}\u{1773D}\u{1773E}\u{1773F}\u{17740}\u{17741}\u{17742}\u{17743}\u{17744}\u{17745}\u{17746}\u{17747}\u{17748}\u{17749}\u{1774A}\u{1774B}\u{1774C}\u{1774D}\u{1774E}\u{1774F}\u{17750}\u{17751}\u{17752}\u{17753}\u{17754}\u{17755}\u{17756}\u{17757}\u{17758}\u{17759}\u{1775A}\u{1775B}\u{1775C}\u{1775D}\u{1775E}\u{1775F}\u{17760}\u{17761}\u{17762}\u{17763}\u{17764}\u{17765}\u{17766}\u{17767}\u{17768}\u{17769}\u{1776A}\u{1776B}\u{1776C}\u{1776D}\u{1776E}\u{1776F}\u{17770}\u{17771}\u{17772}\u{17773}\u{17774}\u{17775}\u{17776}\u{17777}\u{17778}\u{17779}\u{1777A}\u{1777B}\u{1777C}\u{1777D}\u{1777E}\u{1777F}\u{17780}\u{17781}\u{17782}\u{17783}\u{17784}\u{17785}\u{17786}\u{17787}\u{17788}\u{17789}\u{1778A}\u{1778B}\u{1778C}\u{1778D}\u{1778E}\u{1778F}\u{17790}\u{17791}\u{17792}\u{17793}\u{17794}\u{17795}\u{17796}\u{17797}\u{17798}\u{17799}\u{1779A}\u{1779B}\u{1779C}\u{1779D}\u{1779E}\u{1779F}\u{177A0}\u{177A1}\u{177A2}\u{177A3}\u{177A4}\u{177A5}\u{177A6}\u{177A7}\u{177A8}\u{177A9}\u{177AA}\u{177AB}\u{177AC}\u{177AD}\u{177AE}\u{177AF}\u{177B0}\u{177B1}\u{177B2}\u{177B3}\u{177B4}\u{177B5}\u{177B6}\u{177B7}\u{177B8}\u{177B9}\u{177BA}\u{177BB}\u{177BC}\u{177BD}\u{177BE}\u{177BF}\u{177C0}\u{177C1}\u{177C2}\u{177C3}\u{177C4}\u{177C5}\u{177C6}\u{177C7}\u{177C8}\u{177C9}\u{177CA}\u{177CB}\u{177CC}\u{177CD}\u{177CE}\u{177CF}\u{177D0}\u{177D1}\u{177D2}\u{177D3}\u{177D4}\u{177D5}\u{177D6}\u{177D7}\u{177D8}\u{177D9}\u{177DA}\u{177DB}\u{177DC}\u{177DD}\u{177DE}\u{177DF}\u{177E0}\u{177E1}\u{177E2}\u{177E3}\u{177E4}\u{177E5}\u{177E6}\u{177E7}\u{177E8}\u{177E9}\u{177EA}\u{177EB}\u{177EC}\u{177ED}\u{177EE}\u{177EF}\u{177F0}\u{177F1}\u{177F2}\u{177F3}\u{177F4}\u{177F5}\u{177F6}\u{177F7}\u{177F8}\u{177F9}\u{177FA}\u{177FB}\u{177FC}\u{177FD}\u{177FE}\u{177FF}\u{17800}\u{17801}\u{17802}\u{17803}\u{17804}\u{17805}\u{17806}\u{17807}\u{17808}\u{17809}\u{1780A}\u{1780B}\u{1780C}\u{1780D}\u{1780E}\u{1780F}\u{17810}\u{17811}\u{17812}\u{17813}\u{17814}\u{17815}\u{17816}\u{17817}\u{17818}\u{17819}\u{1781A}\u{1781B}\u{1781C}\u{1781D}\u{1781E}\u{1781F}\u{17820}\u{17821}\u{17822}\u{17823}\u{17824}\u{17825}\u{17826}\u{17827}\u{17828}\u{17829}\u{1782A}\u{1782B}\u{1782C}\u{1782D}\u{1782E}\u{1782F}\u{17830}\u{17831}\u{17832}\u{17833}\u{17834}\u{17835}\u{17836}\u{17837}\u{17838}\u{17839}\u{1783A}\u{1783B}\u{1783C}\u{1783D}\u{1783E}\u{1783F}\u{17840}\u{17841}\u{17842}\u{17843}\u{17844}\u{17845}\u{17846}\u{17847}\u{17848}\u{17849}\u{1784A}\u{1784B}\u{1784C}\u{1784D}\u{1784E}\u{1784F}\u{17850}\u{17851}\u{17852}\u{17853}\u{17854}\u{17855}\u{17856}\u{17857}\u{17858}\u{17859}\u{1785A}\u{1785B}\u{1785C}\u{1785D}\u{1785E}\u{1785F}\u{17860}\u{17861}\u{17862}\u{17863}\u{17864}\u{17865}\u{17866}\u{17867}\u{17868}\u{17869}\u{1786A}\u{1786B}\u{1786C}\u{1786D}\u{1786E}\u{1786F}\u{17870}\u{17871}\u{17872}\u{17873}\u{17874}\u{17875}\u{17876}\u{17877}\u{17878}\u{17879}\u{1787A}\u{1787B}\u{1787C}\u{1787D}\u{1787E}\u{1787F}\u{17880}\u{17881}\u{17882}\u{17883}\u{17884}\u{17885}\u{17886}\u{17887}\u{17888}\u{17889}\u{1788A}\u{1788B}\u{1788C}\u{1788D}\u{1788E}\u{1788F}\u{17890}\u{17891}\u{17892}\u{17893}\u{17894}\u{17895}\u{17896}\u{17897}\u{17898}\u{17899}\u{1789A}\u{1789B}\u{1789C}\u{1789D}\u{1789E}\u{1789F}\u{178A0}\u{178A1}\u{178A2}\u{178A3}\u{178A4}\u{178A5}\u{178A6}\u{178A7}\u{178A8}\u{178A9}\u{178AA}\u{178AB}\u{178AC}\u{178AD}\u{178AE}\u{178AF}\u{178B0}\u{178B1}\u{178B2}\u{178B3}\u{178B4}\u{178B5}\u{178B6}\u{178B7}\u{178B8}\u{178B9}\u{178BA}\u{178BB}\u{178BC}\u{178BD}\u{178BE}\u{178BF}\u{178C0}\u{178C1}\u{178C2}\u{178C3}\u{178C4}\u{178C5}\u{178C6}\u{178C7}\u{178C8}\u{178C9}\u{178CA}\u{178CB}\u{178CC}\u{178CD}\u{178CE}\u{178CF}\u{178D0}\u{178D1}\u{178D2}\u{178D3}\u{178D4}\u{178D5}\u{178D6}\u{178D7}\u{178D8}\u{178D9}\u{178DA}\u{178DB}\u{178DC}\u{178DD}\u{178DE}\u{178DF}\u{178E0}\u{178E1}\u{178E2}\u{178E3}\u{178E4}\u{178E5}\u{178E6}\u{178E7}\u{178E8}\u{178E9}\u{178EA}\u{178EB}\u{178EC}\u{178ED}\u{178EE}\u{178EF}\u{178F0}\u{178F1}\u{178F2}\u{178F3}\u{178F4}\u{178F5}\u{178F6}\u{178F7}\u{178F8}\u{178F9}\u{178FA}\u{178FB}\u{178FC}\u{178FD}\u{178FE}\u{178FF}\u{17900}\u{17901}\u{17902}\u{17903}\u{17904}\u{17905}\u{17906}\u{17907}\u{17908}\u{17909}\u{1790A}\u{1790B}\u{1790C}\u{1790D}\u{1790E}\u{1790F}\u{17910}\u{17911}\u{17912}\u{17913}\u{17914}\u{17915}\u{17916}\u{17917}\u{17918}\u{17919}\u{1791A}\u{1791B}\u{1791C}\u{1791D}\u{1791E}\u{1791F}\u{17920}\u{17921}\u{17922}\u{17923}\u{17924}\u{17925}\u{17926}\u{17927}\u{17928}\u{17929}\u{1792A}\u{1792B}\u{1792C}\u{1792D}\u{1792E}\u{1792F}\u{17930}\u{17931}\u{17932}\u{17933}\u{17934}\u{17935}\u{17936}\u{17937}\u{17938}\u{17939}\u{1793A}\u{1793B}\u{1793C}\u{1793D}\u{1793E}\u{1793F}\u{17940}\u{17941}\u{17942}\u{17943}\u{17944}\u{17945}\u{17946}\u{17947}\u{17948}\u{17949}\u{1794A}\u{1794B}\u{1794C}\u{1794D}\u{1794E}\u{1794F}\u{17950}\u{17951}\u{17952}\u{17953}\u{17954}\u{17955}\u{17956}\u{17957}\u{17958}\u{17959}\u{1795A}\u{1795B}\u{1795C}\u{1795D}\u{1795E}\u{1795F}\u{17960}\u{17961}\u{17962}\u{17963}\u{17964}\u{17965}\u{17966}\u{17967}\u{17968}\u{17969}\u{1796A}\u{1796B}\u{1796C}\u{1796D}\u{1796E}\u{1796F}\u{17970}\u{17971}\u{17972}\u{17973}\u{17974}\u{17975}\u{17976}\u{17977}\u{17978}\u{17979}\u{1797A}\u{1797B}\u{1797C}\u{1797D}\u{1797E}\u{1797F}\u{17980}\u{17981}\u{17982}\u{17983}\u{17984}\u{17985}\u{17986}\u{17987}\u{17988}\u{17989}\u{1798A}\u{1798B}\u{1798C}\u{1798D}\u{1798E}\u{1798F}\u{17990}\u{17991}\u{17992}\u{17993}\u{17994}\u{17995}\u{17996}\u{17997}\u{17998}\u{17999}\u{1799A}\u{1799B}\u{1799C}\u{1799D}\u{1799E}\u{1799F}\u{179A0}\u{179A1}\u{179A2}\u{179A3}\u{179A4}\u{179A5}\u{179A6}\u{179A7}\u{179A8}\u{179A9}\u{179AA}\u{179AB}\u{179AC}\u{179AD}\u{179AE}\u{179AF}\u{179B0}\u{179B1}\u{179B2}\u{179B3}\u{179B4}\u{179B5}\u{179B6}\u{179B7}\u{179B8}\u{179B9}\u{179BA}\u{179BB}\u{179BC}\u{179BD}\u{179BE}\u{179BF}\u{179C0}\u{179C1}\u{179C2}\u{179C3}\u{179C4}\u{179C5}\u{179C6}\u{179C7}\u{179C8}\u{179C9}\u{179CA}\u{179CB}\u{179CC}\u{179CD}\u{179CE}\u{179CF}\u{179D0}\u{179D1}\u{179D2}\u{179D3}\u{179D4}\u{179D5}\u{179D6}\u{179D7}\u{179D8}\u{179D9}\u{179DA}\u{179DB}\u{179DC}\u{179DD}\u{179DE}\u{179DF}\u{179E0}\u{179E1}\u{179E2}\u{179E3}\u{179E4}\u{179E5}\u{179E6}\u{179E7}\u{179E8}\u{179E9}\u{179EA}\u{179EB}\u{179EC}\u{179ED}\u{179EE}\u{179EF}\u{179F0}\u{179F1}\u{179F2}\u{179F3}\u{179F4}\u{179F5}\u{179F6}\u{179F7}\u{179F8}\u{179F9}\u{179FA}\u{179FB}\u{179FC}\u{179FD}\u{179FE}\u{179FF}\u{17A00}\u{17A01}\u{17A02}\u{17A03}\u{17A04}\u{17A05}\u{17A06}\u{17A07}\u{17A08}\u{17A09}\u{17A0A}\u{17A0B}\u{17A0C}\u{17A0D}\u{17A0E}\u{17A0F}\u{17A10}\u{17A11}\u{17A12}\u{17A13}\u{17A14}\u{17A15}\u{17A16}\u{17A17}\u{17A18}\u{17A19}\u{17A1A}\u{17A1B}\u{17A1C}\u{17A1D}\u{17A1E}\u{17A1F}\u{17A20}\u{17A21}\u{17A22}\u{17A23}\u{17A24}\u{17A25}\u{17A26}\u{17A27}\u{17A28}\u{17A29}\u{17A2A}\u{17A2B}\u{17A2C}\u{17A2D}\u{17A2E}\u{17A2F}\u{17A30}\u{17A31}\u{17A32}\u{17A33}\u{17A34}\u{17A35}\u{17A36}\u{17A37}\u{17A38}\u{17A39}\u{17A3A}\u{17A3B}\u{17A3C}\u{17A3D}\u{17A3E}\u{17A3F}\u{17A40}\u{17A41}\u{17A42}\u{17A43}\u{17A44}\u{17A45}\u{17A46}\u{17A47}\u{17A48}\u{17A49}\u{17A4A}\u{17A4B}\u{17A4C}\u{17A4D}\u{17A4E}\u{17A4F}\u{17A50}\u{17A51}\u{17A52}\u{17A53}\u{17A54}\u{17A55}\u{17A56}\u{17A57}\u{17A58}\u{17A59}\u{17A5A}\u{17A5B}\u{17A5C}\u{17A5D}\u{17A5E}\u{17A5F}\u{17A60}\u{17A61}\u{17A62}\u{17A63}\u{17A64}\u{17A65}\u{17A66}\u{17A67}\u{17A68}\u{17A69}\u{17A6A}\u{17A6B}\u{17A6C}\u{17A6D}\u{17A6E}\u{17A6F}\u{17A70}\u{17A71}\u{17A72}\u{17A73}\u{17A74}\u{17A75}\u{17A76}\u{17A77}\u{17A78}\u{17A79}\u{17A7A}\u{17A7B}\u{17A7C}\u{17A7D}\u{17A7E}\u{17A7F}\u{17A80}\u{17A81}\u{17A82}\u{17A83}\u{17A84}\u{17A85}\u{17A86}\u{17A87}\u{17A88}\u{17A89}\u{17A8A}\u{17A8B}\u{17A8C}\u{17A8D}\u{17A8E}\u{17A8F}\u{17A90}\u{17A91}\u{17A92}\u{17A93}\u{17A94}\u{17A95}\u{17A96}\u{17A97}\u{17A98}\u{17A99}\u{17A9A}\u{17A9B}\u{17A9C}\u{17A9D}\u{17A9E}\u{17A9F}\u{17AA0}\u{17AA1}\u{17AA2}\u{17AA3}\u{17AA4}\u{17AA5}\u{17AA6}\u{17AA7}\u{17AA8}\u{17AA9}\u{17AAA}\u{17AAB}\u{17AAC}\u{17AAD}\u{17AAE}\u{17AAF}\u{17AB0}\u{17AB1}\u{17AB2}\u{17AB3}\u{17AB4}\u{17AB5}\u{17AB6}\u{17AB7}\u{17AB8}\u{17AB9}\u{17ABA}\u{17ABB}\u{17ABC}\u{17ABD}\u{17ABE}\u{17ABF}\u{17AC0}\u{17AC1}\u{17AC2}\u{17AC3}\u{17AC4}\u{17AC5}\u{17AC6}\u{17AC7}\u{17AC8}\u{17AC9}\u{17ACA}\u{17ACB}\u{17ACC}\u{17ACD}\u{17ACE}\u{17ACF}\u{17AD0}\u{17AD1}\u{17AD2}\u{17AD3}\u{17AD4}\u{17AD5}\u{17AD6}\u{17AD7}\u{17AD8}\u{17AD9}\u{17ADA}\u{17ADB}\u{17ADC}\u{17ADD}\u{17ADE}\u{17ADF}\u{17AE0}\u{17AE1}\u{17AE2}\u{17AE3}\u{17AE4}\u{17AE5}\u{17AE6}\u{17AE7}\u{17AE8}\u{17AE9}\u{17AEA}\u{17AEB}\u{17AEC}\u{17AED}\u{17AEE}\u{17AEF}\u{17AF0}\u{17AF1}\u{17AF2}\u{17AF3}\u{17AF4}\u{17AF5}\u{17AF6}\u{17AF7}\u{17AF8}\u{17AF9}\u{17AFA}\u{17AFB}\u{17AFC}\u{17AFD}\u{17AFE}\u{17AFF}\u{17B00}\u{17B01}\u{17B02}\u{17B03}\u{17B04}\u{17B05}\u{17B06}\u{17B07}\u{17B08}\u{17B09}\u{17B0A}\u{17B0B}\u{17B0C}\u{17B0D}\u{17B0E}\u{17B0F}\u{17B10}\u{17B11}\u{17B12}\u{17B13}\u{17B14}\u{17B15}\u{17B16}\u{17B17}\u{17B18}\u{17B19}\u{17B1A}\u{17B1B}\u{17B1C}\u{17B1D}\u{17B1E}\u{17B1F}\u{17B20}\u{17B21}\u{17B22}\u{17B23}\u{17B24}\u{17B25}\u{17B26}\u{17B27}\u{17B28}\u{17B29}\u{17B2A}\u{17B2B}\u{17B2C}\u{17B2D}\u{17B2E}\u{17B2F}\u{17B30}\u{17B31}\u{17B32}\u{17B33}\u{17B34}\u{17B35}\u{17B36}\u{17B37}\u{17B38}\u{17B39}\u{17B3A}\u{17B3B}\u{17B3C}\u{17B3D}\u{17B3E}\u{17B3F}\u{17B40}\u{17B41}\u{17B42}\u{17B43}\u{17B44}\u{17B45}\u{17B46}\u{17B47}\u{17B48}\u{17B49}\u{17B4A}\u{17B4B}\u{17B4C}\u{17B4D}\u{17B4E}\u{17B4F}\u{17B50}\u{17B51}\u{17B52}\u{17B53}\u{17B54}\u{17B55}\u{17B56}\u{17B57}\u{17B58}\u{17B59}\u{17B5A}\u{17B5B}\u{17B5C}\u{17B5D}\u{17B5E}\u{17B5F}\u{17B60}\u{17B61}\u{17B62}\u{17B63}\u{17B64}\u{17B65}\u{17B66}\u{17B67}\u{17B68}\u{17B69}\u{17B6A}\u{17B6B}\u{17B6C}\u{17B6D}\u{17B6E}\u{17B6F}\u{17B70}\u{17B71}\u{17B72}\u{17B73}\u{17B74}\u{17B75}\u{17B76}\u{17B77}\u{17B78}\u{17B79}\u{17B7A}\u{17B7B}\u{17B7C}\u{17B7D}\u{17B7E}\u{17B7F}\u{17B80}\u{17B81}\u{17B82}\u{17B83}\u{17B84}\u{17B85}\u{17B86}\u{17B87}\u{17B88}\u{17B89}\u{17B8A}\u{17B8B}\u{17B8C}\u{17B8D}\u{17B8E}\u{17B8F}\u{17B90}\u{17B91}\u{17B92}\u{17B93}\u{17B94}\u{17B95}\u{17B96}\u{17B97}\u{17B98}\u{17B99}\u{17B9A}\u{17B9B}\u{17B9C}\u{17B9D}\u{17B9E}\u{17B9F}\u{17BA0}\u{17BA1}\u{17BA2}\u{17BA3}\u{17BA4}\u{17BA5}\u{17BA6}\u{17BA7}\u{17BA8}\u{17BA9}\u{17BAA}\u{17BAB}\u{17BAC}\u{17BAD}\u{17BAE}\u{17BAF}\u{17BB0}\u{17BB1}\u{17BB2}\u{17BB3}\u{17BB4}\u{17BB5}\u{17BB6}\u{17BB7}\u{17BB8}\u{17BB9}\u{17BBA}\u{17BBB}\u{17BBC}\u{17BBD}\u{17BBE}\u{17BBF}\u{17BC0}\u{17BC1}\u{17BC2}\u{17BC3}\u{17BC4}\u{17BC5}\u{17BC6}\u{17BC7}\u{17BC8}\u{17BC9}\u{17BCA}\u{17BCB}\u{17BCC}\u{17BCD}\u{17BCE}\u{17BCF}\u{17BD0}\u{17BD1}\u{17BD2}\u{17BD3}\u{17BD4}\u{17BD5}\u{17BD6}\u{17BD7}\u{17BD8}\u{17BD9}\u{17BDA}\u{17BDB}\u{17BDC}\u{17BDD}\u{17BDE}\u{17BDF}\u{17BE0}\u{17BE1}\u{17BE2}\u{17BE3}\u{17BE4}\u{17BE5}\u{17BE6}\u{17BE7}\u{17BE8}\u{17BE9}\u{17BEA}\u{17BEB}\u{17BEC}\u{17BED}\u{17BEE}\u{17BEF}\u{17BF0}\u{17BF1}\u{17BF2}\u{17BF3}\u{17BF4}\u{17BF5}\u{17BF6}\u{17BF7}\u{17BF8}\u{17BF9}\u{17BFA}\u{17BFB}\u{17BFC}\u{17BFD}\u{17BFE}\u{17BFF}\u{17C00}\u{17C01}\u{17C02}\u{17C03}\u{17C04}\u{17C05}\u{17C06}\u{17C07}\u{17C08}\u{17C09}\u{17C0A}\u{17C0B}\u{17C0C}\u{17C0D}\u{17C0E}\u{17C0F}\u{17C10}\u{17C11}\u{17C12}\u{17C13}\u{17C14}\u{17C15}\u{17C16}\u{17C17}\u{17C18}\u{17C19}\u{17C1A}\u{17C1B}\u{17C1C}\u{17C1D}\u{17C1E}\u{17C1F}\u{17C20}\u{17C21}\u{17C22}\u{17C23}\u{17C24}\u{17C25}\u{17C26}\u{17C27}\u{17C28}\u{17C29}\u{17C2A}\u{17C2B}\u{17C2C}\u{17C2D}\u{17C2E}\u{17C2F}\u{17C30}\u{17C31}\u{17C32}\u{17C33}\u{17C34}\u{17C35}\u{17C36}\u{17C37}\u{17C38}\u{17C39}\u{17C3A}\u{17C3B}\u{17C3C}\u{17C3D}\u{17C3E}\u{17C3F}\u{17C40}\u{17C41}\u{17C42}\u{17C43}\u{17C44}\u{17C45}\u{17C46}\u{17C47}\u{17C48}\u{17C49}\u{17C4A}\u{17C4B}\u{17C4C}\u{17C4D}\u{17C4E}\u{17C4F}\u{17C50}\u{17C51}\u{17C52}\u{17C53}\u{17C54}\u{17C55}\u{17C56}\u{17C57}\u{17C58}\u{17C59}\u{17C5A}\u{17C5B}\u{17C5C}\u{17C5D}\u{17C5E}\u{17C5F}\u{17C60}\u{17C61}\u{17C62}\u{17C63}\u{17C64}\u{17C65}\u{17C66}\u{17C67}\u{17C68}\u{17C69}\u{17C6A}\u{17C6B}\u{17C6C}\u{17C6D}\u{17C6E}\u{17C6F}\u{17C70}\u{17C71}\u{17C72}\u{17C73}\u{17C74}\u{17C75}\u{17C76}\u{17C77}\u{17C78}\u{17C79}\u{17C7A}\u{17C7B}\u{17C7C}\u{17C7D}\u{17C7E}\u{17C7F}\u{17C80}\u{17C81}\u{17C82}\u{17C83}\u{17C84}\u{17C85}\u{17C86}\u{17C87}\u{17C88}\u{17C89}\u{17C8A}\u{17C8B}\u{17C8C}\u{17C8D}\u{17C8E}\u{17C8F}\u{17C90}\u{17C91}\u{17C92}\u{17C93}\u{17C94}\u{17C95}\u{17C96}\u{17C97}\u{17C98}\u{17C99}\u{17C9A}\u{17C9B}\u{17C9C}\u{17C9D}\u{17C9E}\u{17C9F}\u{17CA0}\u{17CA1}\u{17CA2}\u{17CA3}\u{17CA4}\u{17CA5}\u{17CA6}\u{17CA7}\u{17CA8}\u{17CA9}\u{17CAA}\u{17CAB}\u{17CAC}\u{17CAD}\u{17CAE}\u{17CAF}\u{17CB0}\u{17CB1}\u{17CB2}\u{17CB3}\u{17CB4}\u{17CB5}\u{17CB6}\u{17CB7}\u{17CB8}\u{17CB9}\u{17CBA}\u{17CBB}\u{17CBC}\u{17CBD}\u{17CBE}\u{17CBF}\u{17CC0}\u{17CC1}\u{17CC2}\u{17CC3}\u{17CC4}\u{17CC5}\u{17CC6}\u{17CC7}\u{17CC8}\u{17CC9}\u{17CCA}\u{17CCB}\u{17CCC}\u{17CCD}\u{17CCE}\u{17CCF}\u{17CD0}\u{17CD1}\u{17CD2}\u{17CD3}\u{17CD4}\u{17CD5}\u{17CD6}\u{17CD7}\u{17CD8}\u{17CD9}\u{17CDA}\u{17CDB}\u{17CDC}\u{17CDD}\u{17CDE}\u{17CDF}\u{17CE0}\u{17CE1}\u{17CE2}\u{17CE3}\u{17CE4}\u{17CE5}\u{17CE6}\u{17CE7}\u{17CE8}\u{17CE9}\u{17CEA}\u{17CEB}\u{17CEC}\u{17CED}\u{17CEE}\u{17CEF}\u{17CF0}\u{17CF1}\u{17CF2}\u{17CF3}\u{17CF4}\u{17CF5}\u{17CF6}\u{17CF7}\u{17CF8}\u{17CF9}\u{17CFA}\u{17CFB}\u{17CFC}\u{17CFD}\u{17CFE}\u{17CFF}\u{17D00}\u{17D01}\u{17D02}\u{17D03}\u{17D04}\u{17D05}\u{17D06}\u{17D07}\u{17D08}\u{17D09}\u{17D0A}\u{17D0B}\u{17D0C}\u{17D0D}\u{17D0E}\u{17D0F}\u{17D10}\u{17D11}\u{17D12}\u{17D13}\u{17D14}\u{17D15}\u{17D16}\u{17D17}\u{17D18}\u{17D19}\u{17D1A}\u{17D1B}\u{17D1C}\u{17D1D}\u{17D1E}\u{17D1F}\u{17D20}\u{17D21}\u{17D22}\u{17D23}\u{17D24}\u{17D25}\u{17D26}\u{17D27}\u{17D28}\u{17D29}\u{17D2A}\u{17D2B}\u{17D2C}\u{17D2D}\u{17D2E}\u{17D2F}\u{17D30}\u{17D31}\u{17D32}\u{17D33}\u{17D34}\u{17D35}\u{17D36}\u{17D37}\u{17D38}\u{17D39}\u{17D3A}\u{17D3B}\u{17D3C}\u{17D3D}\u{17D3E}\u{17D3F}\u{17D40}\u{17D41}\u{17D42}\u{17D43}\u{17D44}\u{17D45}\u{17D46}\u{17D47}\u{17D48}\u{17D49}\u{17D4A}\u{17D4B}\u{17D4C}\u{17D4D}\u{17D4E}\u{17D4F}\u{17D50}\u{17D51}\u{17D52}\u{17D53}\u{17D54}\u{17D55}\u{17D56}\u{17D57}\u{17D58}\u{17D59}\u{17D5A}\u{17D5B}\u{17D5C}\u{17D5D}\u{17D5E}\u{17D5F}\u{17D60}\u{17D61}\u{17D62}\u{17D63}\u{17D64}\u{17D65}\u{17D66}\u{17D67}\u{17D68}\u{17D69}\u{17D6A}\u{17D6B}\u{17D6C}\u{17D6D}\u{17D6E}\u{17D6F}\u{17D70}\u{17D71}\u{17D72}\u{17D73}\u{17D74}\u{17D75}\u{17D76}\u{17D77}\u{17D78}\u{17D79}\u{17D7A}\u{17D7B}\u{17D7C}\u{17D7D}\u{17D7E}\u{17D7F}\u{17D80}\u{17D81}\u{17D82}\u{17D83}\u{17D84}\u{17D85}\u{17D86}\u{17D87}\u{17D88}\u{17D89}\u{17D8A}\u{17D8B}\u{17D8C}\u{17D8D}\u{17D8E}\u{17D8F}\u{17D90}\u{17D91}\u{17D92}\u{17D93}\u{17D94}\u{17D95}\u{17D96}\u{17D97}\u{17D98}\u{17D99}\u{17D9A}\u{17D9B}\u{17D9C}\u{17D9D}\u{17D9E}\u{17D9F}\u{17DA0}\u{17DA1}\u{17DA2}\u{17DA3}\u{17DA4}\u{17DA5}\u{17DA6}\u{17DA7}\u{17DA8}\u{17DA9}\u{17DAA}\u{17DAB}\u{17DAC}\u{17DAD}\u{17DAE}\u{17DAF}\u{17DB0}\u{17DB1}\u{17DB2}\u{17DB3}\u{17DB4}\u{17DB5}\u{17DB6}\u{17DB7}\u{17DB8}\u{17DB9}\u{17DBA}\u{17DBB}\u{17DBC}\u{17DBD}\u{17DBE}\u{17DBF}\u{17DC0}\u{17DC1}\u{17DC2}\u{17DC3}\u{17DC4}\u{17DC5}\u{17DC6}\u{17DC7}\u{17DC8}\u{17DC9}\u{17DCA}\u{17DCB}\u{17DCC}\u{17DCD}\u{17DCE}\u{17DCF}\u{17DD0}\u{17DD1}\u{17DD2}\u{17DD3}\u{17DD4}\u{17DD5}\u{17DD6}\u{17DD7}\u{17DD8}\u{17DD9}\u{17DDA}\u{17DDB}\u{17DDC}\u{17DDD}\u{17DDE}\u{17DDF}\u{17DE0}\u{17DE1}\u{17DE2}\u{17DE3}\u{17DE4}\u{17DE5}\u{17DE6}\u{17DE7}\u{17DE8}\u{17DE9}\u{17DEA}\u{17DEB}\u{17DEC}\u{17DED}\u{17DEE}\u{17DEF}\u{17DF0}\u{17DF1}\u{17DF2}\u{17DF3}\u{17DF4}\u{17DF5}\u{17DF6}\u{17DF7}\u{17DF8}\u{17DF9}\u{17DFA}\u{17DFB}\u{17DFC}\u{17DFD}\u{17DFE}\u{17DFF}\u{17E00}\u{17E01}\u{17E02}\u{17E03}\u{17E04}\u{17E05}\u{17E06}\u{17E07}\u{17E08}\u{17E09}\u{17E0A}\u{17E0B}\u{17E0C}\u{17E0D}\u{17E0E}\u{17E0F}\u{17E10}\u{17E11}\u{17E12}\u{17E13}\u{17E14}\u{17E15}\u{17E16}\u{17E17}\u{17E18}\u{17E19}\u{17E1A}\u{17E1B}\u{17E1C}\u{17E1D}\u{17E1E}\u{17E1F}\u{17E20}\u{17E21}\u{17E22}\u{17E23}\u{17E24}\u{17E25}\u{17E26}\u{17E27}\u{17E28}\u{17E29}\u{17E2A}\u{17E2B}\u{17E2C}\u{17E2D}\u{17E2E}\u{17E2F}\u{17E30}\u{17E31}\u{17E32}\u{17E33}\u{17E34}\u{17E35}\u{17E36}\u{17E37}\u{17E38}\u{17E39}\u{17E3A}\u{17E3B}\u{17E3C}\u{17E3D}\u{17E3E}\u{17E3F}\u{17E40}\u{17E41}\u{17E42}\u{17E43}\u{17E44}\u{17E45}\u{17E46}\u{17E47}\u{17E48}\u{17E49}\u{17E4A}\u{17E4B}\u{17E4C}\u{17E4D}\u{17E4E}\u{17E4F}\u{17E50}\u{17E51}\u{17E52}\u{17E53}\u{17E54}\u{17E55}\u{17E56}\u{17E57}\u{17E58}\u{17E59}\u{17E5A}\u{17E5B}\u{17E5C}\u{17E5D}\u{17E5E}\u{17E5F}\u{17E60}\u{17E61}\u{17E62}\u{17E63}\u{17E64}\u{17E65}\u{17E66}\u{17E67}\u{17E68}\u{17E69}\u{17E6A}\u{17E6B}\u{17E6C}\u{17E6D}\u{17E6E}\u{17E6F}\u{17E70}\u{17E71}\u{17E72}\u{17E73}\u{17E74}\u{17E75}\u{17E76}\u{17E77}\u{17E78}\u{17E79}\u{17E7A}\u{17E7B}\u{17E7C}\u{17E7D}\u{17E7E}\u{17E7F}\u{17E80}\u{17E81}\u{17E82}\u{17E83}\u{17E84}\u{17E85}\u{17E86}\u{17E87}\u{17E88}\u{17E89}\u{17E8A}\u{17E8B}\u{17E8C}\u{17E8D}\u{17E8E}\u{17E8F}\u{17E90}\u{17E91}\u{17E92}\u{17E93}\u{17E94}\u{17E95}\u{17E96}\u{17E97}\u{17E98}\u{17E99}\u{17E9A}\u{17E9B}\u{17E9C}\u{17E9D}\u{17E9E}\u{17E9F}\u{17EA0}\u{17EA1}\u{17EA2}\u{17EA3}\u{17EA4}\u{17EA5}\u{17EA6}\u{17EA7}\u{17EA8}\u{17EA9}\u{17EAA}\u{17EAB}\u{17EAC}\u{17EAD}\u{17EAE}\u{17EAF}\u{17EB0}\u{17EB1}\u{17EB2}\u{17EB3}\u{17EB4}\u{17EB5}\u{17EB6}\u{17EB7}\u{17EB8}\u{17EB9}\u{17EBA}\u{17EBB}\u{17EBC}\u{17EBD}\u{17EBE}\u{17EBF}\u{17EC0}\u{17EC1}\u{17EC2}\u{17EC3}\u{17EC4}\u{17EC5}\u{17EC6}\u{17EC7}\u{17EC8}\u{17EC9}\u{17ECA}\u{17ECB}\u{17ECC}\u{17ECD}\u{17ECE}\u{17ECF}\u{17ED0}\u{17ED1}\u{17ED2}\u{17ED3}\u{17ED4}\u{17ED5}\u{17ED6}\u{17ED7}\u{17ED8}\u{17ED9}\u{17EDA}\u{17EDB}\u{17EDC}\u{17EDD}\u{17EDE}\u{17EDF}\u{17EE0}\u{17EE1}\u{17EE2}\u{17EE3}\u{17EE4}\u{17EE5}\u{17EE6}\u{17EE7}\u{17EE8}\u{17EE9}\u{17EEA}\u{17EEB}\u{17EEC}\u{17EED}\u{17EEE}\u{17EEF}\u{17EF0}\u{17EF1}\u{17EF2}\u{17EF3}\u{17EF4}\u{17EF5}\u{17EF6}\u{17EF7}\u{17EF8}\u{17EF9}\u{17EFA}\u{17EFB}\u{17EFC}\u{17EFD}\u{17EFE}\u{17EFF}\u{17F00}\u{17F01}\u{17F02}\u{17F03}\u{17F04}\u{17F05}\u{17F06}\u{17F07}\u{17F08}\u{17F09}\u{17F0A}\u{17F0B}\u{17F0C}\u{17F0D}\u{17F0E}\u{17F0F}\u{17F10}\u{17F11}\u{17F12}\u{17F13}\u{17F14}\u{17F15}\u{17F16}\u{17F17}\u{17F18}\u{17F19}\u{17F1A}\u{17F1B}\u{17F1C}\u{17F1D}\u{17F1E}\u{17F1F}\u{17F20}\u{17F21}\u{17F22}\u{17F23}\u{17F24}\u{17F25}\u{17F26}\u{17F27}\u{17F28}\u{17F29}\u{17F2A}\u{17F2B}\u{17F2C}\u{17F2D}\u{17F2E}\u{17F2F}\u{17F30}\u{17F31}\u{17F32}\u{17F33}\u{17F34}\u{17F35}\u{17F36}\u{17F37}\u{17F38}\u{17F39}\u{17F3A}\u{17F3B}\u{17F3C}\u{17F3D}\u{17F3E}\u{17F3F}\u{17F40}\u{17F41}\u{17F42}\u{17F43}\u{17F44}\u{17F45}\u{17F46}\u{17F47}\u{17F48}\u{17F49}\u{17F4A}\u{17F4B}\u{17F4C}\u{17F4D}\u{17F4E}\u{17F4F}\u{17F50}\u{17F51}\u{17F52}\u{17F53}\u{17F54}\u{17F55}\u{17F56}\u{17F57}\u{17F58}\u{17F59}\u{17F5A}\u{17F5B}\u{17F5C}\u{17F5D}\u{17F5E}\u{17F5F}\u{17F60}\u{17F61}\u{17F62}\u{17F63}\u{17F64}\u{17F65}\u{17F66}\u{17F67}\u{17F68}\u{17F69}\u{17F6A}\u{17F6B}\u{17F6C}\u{17F6D}\u{17F6E}\u{17F6F}\u{17F70}\u{17F71}\u{17F72}\u{17F73}\u{17F74}\u{17F75}\u{17F76}\u{17F77}\u{17F78}\u{17F79}\u{17F7A}\u{17F7B}\u{17F7C}\u{17F7D}\u{17F7E}\u{17F7F}\u{17F80}\u{17F81}\u{17F82}\u{17F83}\u{17F84}\u{17F85}\u{17F86}\u{17F87}\u{17F88}\u{17F89}\u{17F8A}\u{17F8B}\u{17F8C}\u{17F8D}\u{17F8E}\u{17F8F}\u{17F90}\u{17F91}\u{17F92}\u{17F93}\u{17F94}\u{17F95}\u{17F96}\u{17F97}\u{17F98}\u{17F99}\u{17F9A}\u{17F9B}\u{17F9C}\u{17F9D}\u{17F9E}\u{17F9F}\u{17FA0}\u{17FA1}\u{17FA2}\u{17FA3}\u{17FA4}\u{17FA5}\u{17FA6}\u{17FA7}\u{17FA8}\u{17FA9}\u{17FAA}\u{17FAB}\u{17FAC}\u{17FAD}\u{17FAE}\u{17FAF}\u{17FB0}\u{17FB1}\u{17FB2}\u{17FB3}\u{17FB4}\u{17FB5}\u{17FB6}\u{17FB7}\u{17FB8}\u{17FB9}\u{17FBA}\u{17FBB}\u{17FBC}\u{17FBD}\u{17FBE}\u{17FBF}\u{17FC0}\u{17FC1}\u{17FC2}\u{17FC3}\u{17FC4}\u{17FC5}\u{17FC6}\u{17FC7}\u{17FC8}\u{17FC9}\u{17FCA}\u{17FCB}\u{17FCC}\u{17FCD}\u{17FCE}\u{17FCF}\u{17FD0}\u{17FD1}\u{17FD2}\u{17FD3}\u{17FD4}\u{17FD5}\u{17FD6}\u{17FD7}\u{17FD8}\u{17FD9}\u{17FDA}\u{17FDB}\u{17FDC}\u{17FDD}\u{17FDE}\u{17FDF}\u{17FE0}\u{17FE1}\u{17FE2}\u{17FE3}\u{17FE4}\u{17FE5}\u{17FE6}\u{17FE7}\u{17FE8}\u{17FE9}\u{17FEA}\u{17FEB}\u{17FEC}\u{17FED}\u{17FEE}\u{17FEF}\u{17FF0}\u{17FF1}\u{17FF2}\u{17FF3}\u{17FF4}\u{17FF5}\u{17FF6}\u{17FF7}\u{17FF8}\u{17FF9}\u{17FFA}\u{17FFB}\u{17FFC}\u{17FFD}\u{17FFE}\u{17FFF}\u{18000}\u{18001}\u{18002}\u{18003}\u{18004}\u{18005}\u{18006}\u{18007}\u{18008}\u{18009}\u{1800A}\u{1800B}\u{1800C}\u{1800D}\u{1800E}\u{1800F}\u{18010}\u{18011}\u{18012}\u{18013}\u{18014}\u{18015}\u{18016}\u{18017}\u{18018}\u{18019}\u{1801A}\u{1801B}\u{1801C}\u{1801D}\u{1801E}\u{1801F}\u{18020}\u{18021}\u{18022}\u{18023}\u{18024}\u{18025}\u{18026}\u{18027}\u{18028}\u{18029}\u{1802A}\u{1802B}\u{1802C}\u{1802D}\u{1802E}\u{1802F}\u{18030}\u{18031}\u{18032}\u{18033}\u{18034}\u{18035}\u{18036}\u{18037}\u{18038}\u{18039}\u{1803A}\u{1803B}\u{1803C}\u{1803D}\u{1803E}\u{1803F}\u{18040}\u{18041}\u{18042}\u{18043}\u{18044}\u{18045}\u{18046}\u{18047}\u{18048}\u{18049}\u{1804A}\u{1804B}\u{1804C}\u{1804D}\u{1804E}\u{1804F}\u{18050}\u{18051}\u{18052}\u{18053}\u{18054}\u{18055}\u{18056}\u{18057}\u{18058}\u{18059}\u{1805A}\u{1805B}\u{1805C}\u{1805D}\u{1805E}\u{1805F}\u{18060}\u{18061}\u{18062}\u{18063}\u{18064}\u{18065}\u{18066}\u{18067}\u{18068}\u{18069}\u{1806A}\u{1806B}\u{1806C}\u{1806D}\u{1806E}\u{1806F}\u{18070}\u{18071}\u{18072}\u{18073}\u{18074}\u{18075}\u{18076}\u{18077}\u{18078}\u{18079}\u{1807A}\u{1807B}\u{1807C}\u{1807D}\u{1807E}\u{1807F}\u{18080}\u{18081}\u{18082}\u{18083}\u{18084}\u{18085}\u{18086}\u{18087}\u{18088}\u{18089}\u{1808A}\u{1808B}\u{1808C}\u{1808D}\u{1808E}\u{1808F}\u{18090}\u{18091}\u{18092}\u{18093}\u{18094}\u{18095}\u{18096}\u{18097}\u{18098}\u{18099}\u{1809A}\u{1809B}\u{1809C}\u{1809D}\u{1809E}\u{1809F}\u{180A0}\u{180A1}\u{180A2}\u{180A3}\u{180A4}\u{180A5}\u{180A6}\u{180A7}\u{180A8}\u{180A9}\u{180AA}\u{180AB}\u{180AC}\u{180AD}\u{180AE}\u{180AF}\u{180B0}\u{180B1}\u{180B2}\u{180B3}\u{180B4}\u{180B5}\u{180B6}\u{180B7}\u{180B8}\u{180B9}\u{180BA}\u{180BB}\u{180BC}\u{180BD}\u{180BE}\u{180BF}\u{180C0}\u{180C1}\u{180C2}\u{180C3}\u{180C4}\u{180C5}\u{180C6}\u{180C7}\u{180C8}\u{180C9}\u{180CA}\u{180CB}\u{180CC}\u{180CD}\u{180CE}\u{180CF}\u{180D0}\u{180D1}\u{180D2}\u{180D3}\u{180D4}\u{180D5}\u{180D6}\u{180D7}\u{180D8}\u{180D9}\u{180DA}\u{180DB}\u{180DC}\u{180DD}\u{180DE}\u{180DF}\u{180E0}\u{180E1}\u{180E2}\u{180E3}\u{180E4}\u{180E5}\u{180E6}\u{180E7}\u{180E8}\u{180E9}\u{180EA}\u{180EB}\u{180EC}\u{180ED}\u{180EE}\u{180EF}\u{180F0}\u{180F1}\u{180F2}\u{180F3}\u{180F4}\u{180F5}\u{180F6}\u{180F7}\u{180F8}\u{180F9}\u{180FA}\u{180FB}\u{180FC}\u{180FD}\u{180FE}\u{180FF}\u{18100}\u{18101}\u{18102}\u{18103}\u{18104}\u{18105}\u{18106}\u{18107}\u{18108}\u{18109}\u{1810A}\u{1810B}\u{1810C}\u{1810D}\u{1810E}\u{1810F}\u{18110}\u{18111}\u{18112}\u{18113}\u{18114}\u{18115}\u{18116}\u{18117}\u{18118}\u{18119}\u{1811A}\u{1811B}\u{1811C}\u{1811D}\u{1811E}\u{1811F}\u{18120}\u{18121}\u{18122}\u{18123}\u{18124}\u{18125}\u{18126}\u{18127}\u{18128}\u{18129}\u{1812A}\u{1812B}\u{1812C}\u{1812D}\u{1812E}\u{1812F}\u{18130}\u{18131}\u{18132}\u{18133}\u{18134}\u{18135}\u{18136}\u{18137}\u{18138}\u{18139}\u{1813A}\u{1813B}\u{1813C}\u{1813D}\u{1813E}\u{1813F}\u{18140}\u{18141}\u{18142}\u{18143}\u{18144}\u{18145}\u{18146}\u{18147}\u{18148}\u{18149}\u{1814A}\u{1814B}\u{1814C}\u{1814D}\u{1814E}\u{1814F}\u{18150}\u{18151}\u{18152}\u{18153}\u{18154}\u{18155}\u{18156}\u{18157}\u{18158}\u{18159}\u{1815A}\u{1815B}\u{1815C}\u{1815D}\u{1815E}\u{1815F}\u{18160}\u{18161}\u{18162}\u{18163}\u{18164}\u{18165}\u{18166}\u{18167}\u{18168}\u{18169}\u{1816A}\u{1816B}\u{1816C}\u{1816D}\u{1816E}\u{1816F}\u{18170}\u{18171}\u{18172}\u{18173}\u{18174}\u{18175}\u{18176}\u{18177}\u{18178}\u{18179}\u{1817A}\u{1817B}\u{1817C}\u{1817D}\u{1817E}\u{1817F}\u{18180}\u{18181}\u{18182}\u{18183}\u{18184}\u{18185}\u{18186}\u{18187}\u{18188}\u{18189}\u{1818A}\u{1818B}\u{1818C}\u{1818D}\u{1818E}\u{1818F}\u{18190}\u{18191}\u{18192}\u{18193}\u{18194}\u{18195}\u{18196}\u{18197}\u{18198}\u{18199}\u{1819A}\u{1819B}\u{1819C}\u{1819D}\u{1819E}\u{1819F}\u{181A0}\u{181A1}\u{181A2}\u{181A3}\u{181A4}\u{181A5}\u{181A6}\u{181A7}\u{181A8}\u{181A9}\u{181AA}\u{181AB}\u{181AC}\u{181AD}\u{181AE}\u{181AF}\u{181B0}\u{181B1}\u{181B2}\u{181B3}\u{181B4}\u{181B5}\u{181B6}\u{181B7}\u{181B8}\u{181B9}\u{181BA}\u{181BB}\u{181BC}\u{181BD}\u{181BE}\u{181BF}\u{181C0}\u{181C1}\u{181C2}\u{181C3}\u{181C4}\u{181C5}\u{181C6}\u{181C7}\u{181C8}\u{181C9}\u{181CA}\u{181CB}\u{181CC}\u{181CD}\u{181CE}\u{181CF}\u{181D0}\u{181D1}\u{181D2}\u{181D3}\u{181D4}\u{181D5}\u{181D6}\u{181D7}\u{181D8}\u{181D9}\u{181DA}\u{181DB}\u{181DC}\u{181DD}\u{181DE}\u{181DF}\u{181E0}\u{181E1}\u{181E2}\u{181E3}\u{181E4}\u{181E5}\u{181E6}\u{181E7}\u{181E8}\u{181E9}\u{181EA}\u{181EB}\u{181EC}\u{181ED}\u{181EE}\u{181EF}\u{181F0}\u{181F1}\u{181F2}\u{181F3}\u{181F4}\u{181F5}\u{181F6}\u{181F7}\u{181F8}\u{181F9}\u{181FA}\u{181FB}\u{181FC}\u{181FD}\u{181FE}\u{181FF}\u{18200}\u{18201}\u{18202}\u{18203}\u{18204}\u{18205}\u{18206}\u{18207}\u{18208}\u{18209}\u{1820A}\u{1820B}\u{1820C}\u{1820D}\u{1820E}\u{1820F}\u{18210}\u{18211}\u{18212}\u{18213}\u{18214}\u{18215}\u{18216}\u{18217}\u{18218}\u{18219}\u{1821A}\u{1821B}\u{1821C}\u{1821D}\u{1821E}\u{1821F}\u{18220}\u{18221}\u{18222}\u{18223}\u{18224}\u{18225}\u{18226}\u{18227}\u{18228}\u{18229}\u{1822A}\u{1822B}\u{1822C}\u{1822D}\u{1822E}\u{1822F}\u{18230}\u{18231}\u{18232}\u{18233}\u{18234}\u{18235}\u{18236}\u{18237}\u{18238}\u{18239}\u{1823A}\u{1823B}\u{1823C}\u{1823D}\u{1823E}\u{1823F}\u{18240}\u{18241}\u{18242}\u{18243}\u{18244}\u{18245}\u{18246}\u{18247}\u{18248}\u{18249}\u{1824A}\u{1824B}\u{1824C}\u{1824D}\u{1824E}\u{1824F}\u{18250}\u{18251}\u{18252}\u{18253}\u{18254}\u{18255}\u{18256}\u{18257}\u{18258}\u{18259}\u{1825A}\u{1825B}\u{1825C}\u{1825D}\u{1825E}\u{1825F}\u{18260}\u{18261}\u{18262}\u{18263}\u{18264}\u{18265}\u{18266}\u{18267}\u{18268}\u{18269}\u{1826A}\u{1826B}\u{1826C}\u{1826D}\u{1826E}\u{1826F}\u{18270}\u{18271}\u{18272}\u{18273}\u{18274}\u{18275}\u{18276}\u{18277}\u{18278}\u{18279}\u{1827A}\u{1827B}\u{1827C}\u{1827D}\u{1827E}\u{1827F}\u{18280}\u{18281}\u{18282}\u{18283}\u{18284}\u{18285}\u{18286}\u{18287}\u{18288}\u{18289}\u{1828A}\u{1828B}\u{1828C}\u{1828D}\u{1828E}\u{1828F}\u{18290}\u{18291}\u{18292}\u{18293}\u{18294}\u{18295}\u{18296}\u{18297}\u{18298}\u{18299}\u{1829A}\u{1829B}\u{1829C}\u{1829D}\u{1829E}\u{1829F}\u{182A0}\u{182A1}\u{182A2}\u{182A3}\u{182A4}\u{182A5}\u{182A6}\u{182A7}\u{182A8}\u{182A9}\u{182AA}\u{182AB}\u{182AC}\u{182AD}\u{182AE}\u{182AF}\u{182B0}\u{182B1}\u{182B2}\u{182B3}\u{182B4}\u{182B5}\u{182B6}\u{182B7}\u{182B8}\u{182B9}\u{182BA}\u{182BB}\u{182BC}\u{182BD}\u{182BE}\u{182BF}\u{182C0}\u{182C1}\u{182C2}\u{182C3}\u{182C4}\u{182C5}\u{182C6}\u{182C7}\u{182C8}\u{182C9}\u{182CA}\u{182CB}\u{182CC}\u{182CD}\u{182CE}\u{182CF}\u{182D0}\u{182D1}\u{182D2}\u{182D3}\u{182D4}\u{182D5}\u{182D6}\u{182D7}\u{182D8}\u{182D9}\u{182DA}\u{182DB}\u{182DC}\u{182DD}\u{182DE}\u{182DF}\u{182E0}\u{182E1}\u{182E2}\u{182E3}\u{182E4}\u{182E5}\u{182E6}\u{182E7}\u{182E8}\u{182E9}\u{182EA}\u{182EB}\u{182EC}\u{182ED}\u{182EE}\u{182EF}\u{182F0}\u{182F1}\u{182F2}\u{182F3}\u{182F4}\u{182F5}\u{182F6}\u{182F7}\u{182F8}\u{182F9}\u{182FA}\u{182FB}\u{182FC}\u{182FD}\u{182FE}\u{182FF}\u{18300}\u{18301}\u{18302}\u{18303}\u{18304}\u{18305}\u{18306}\u{18307}\u{18308}\u{18309}\u{1830A}\u{1830B}\u{1830C}\u{1830D}\u{1830E}\u{1830F}\u{18310}\u{18311}\u{18312}\u{18313}\u{18314}\u{18315}\u{18316}\u{18317}\u{18318}\u{18319}\u{1831A}\u{1831B}\u{1831C}\u{1831D}\u{1831E}\u{1831F}\u{18320}\u{18321}\u{18322}\u{18323}\u{18324}\u{18325}\u{18326}\u{18327}\u{18328}\u{18329}\u{1832A}\u{1832B}\u{1832C}\u{1832D}\u{1832E}\u{1832F}\u{18330}\u{18331}\u{18332}\u{18333}\u{18334}\u{18335}\u{18336}\u{18337}\u{18338}\u{18339}\u{1833A}\u{1833B}\u{1833C}\u{1833D}\u{1833E}\u{1833F}\u{18340}\u{18341}\u{18342}\u{18343}\u{18344}\u{18345}\u{18346}\u{18347}\u{18348}\u{18349}\u{1834A}\u{1834B}\u{1834C}\u{1834D}\u{1834E}\u{1834F}\u{18350}\u{18351}\u{18352}\u{18353}\u{18354}\u{18355}\u{18356}\u{18357}\u{18358}\u{18359}\u{1835A}\u{1835B}\u{1835C}\u{1835D}\u{1835E}\u{1835F}\u{18360}\u{18361}\u{18362}\u{18363}\u{18364}\u{18365}\u{18366}\u{18367}\u{18368}\u{18369}\u{1836A}\u{1836B}\u{1836C}\u{1836D}\u{1836E}\u{1836F}\u{18370}\u{18371}\u{18372}\u{18373}\u{18374}\u{18375}\u{18376}\u{18377}\u{18378}\u{18379}\u{1837A}\u{1837B}\u{1837C}\u{1837D}\u{1837E}\u{1837F}\u{18380}\u{18381}\u{18382}\u{18383}\u{18384}\u{18385}\u{18386}\u{18387}\u{18388}\u{18389}\u{1838A}\u{1838B}\u{1838C}\u{1838D}\u{1838E}\u{1838F}\u{18390}\u{18391}\u{18392}\u{18393}\u{18394}\u{18395}\u{18396}\u{18397}\u{18398}\u{18399}\u{1839A}\u{1839B}\u{1839C}\u{1839D}\u{1839E}\u{1839F}\u{183A0}\u{183A1}\u{183A2}\u{183A3}\u{183A4}\u{183A5}\u{183A6}\u{183A7}\u{183A8}\u{183A9}\u{183AA}\u{183AB}\u{183AC}\u{183AD}\u{183AE}\u{183AF}\u{183B0}\u{183B1}\u{183B2}\u{183B3}\u{183B4}\u{183B5}\u{183B6}\u{183B7}\u{183B8}\u{183B9}\u{183BA}\u{183BB}\u{183BC}\u{183BD}\u{183BE}\u{183BF}\u{183C0}\u{183C1}\u{183C2}\u{183C3}\u{183C4}\u{183C5}\u{183C6}\u{183C7}\u{183C8}\u{183C9}\u{183CA}\u{183CB}\u{183CC}\u{183CD}\u{183CE}\u{183CF}\u{183D0}\u{183D1}\u{183D2}\u{183D3}\u{183D4}\u{183D5}\u{183D6}\u{183D7}\u{183D8}\u{183D9}\u{183DA}\u{183DB}\u{183DC}\u{183DD}\u{183DE}\u{183DF}\u{183E0}\u{183E1}\u{183E2}\u{183E3}\u{183E4}\u{183E5}\u{183E6}\u{183E7}\u{183E8}\u{183E9}\u{183EA}\u{183EB}\u{183EC}\u{183ED}\u{183EE}\u{183EF}\u{183F0}\u{183F1}\u{183F2}\u{183F3}\u{183F4}\u{183F5}\u{183F6}\u{183F7}\u{183F8}\u{183F9}\u{183FA}\u{183FB}\u{183FC}\u{183FD}\u{183FE}\u{183FF}\u{18400}\u{18401}\u{18402}\u{18403}\u{18404}\u{18405}\u{18406}\u{18407}\u{18408}\u{18409}\u{1840A}\u{1840B}\u{1840C}\u{1840D}\u{1840E}\u{1840F}\u{18410}\u{18411}\u{18412}\u{18413}\u{18414}\u{18415}\u{18416}\u{18417}\u{18418}\u{18419}\u{1841A}\u{1841B}\u{1841C}\u{1841D}\u{1841E}\u{1841F}\u{18420}\u{18421}\u{18422}\u{18423}\u{18424}\u{18425}\u{18426}\u{18427}\u{18428}\u{18429}\u{1842A}\u{1842B}\u{1842C}\u{1842D}\u{1842E}\u{1842F}\u{18430}\u{18431}\u{18432}\u{18433}\u{18434}\u{18435}\u{18436}\u{18437}\u{18438}\u{18439}\u{1843A}\u{1843B}\u{1843C}\u{1843D}\u{1843E}\u{1843F}\u{18440}\u{18441}\u{18442}\u{18443}\u{18444}\u{18445}\u{18446}\u{18447}\u{18448}\u{18449}\u{1844A}\u{1844B}\u{1844C}\u{1844D}\u{1844E}\u{1844F}\u{18450}\u{18451}\u{18452}\u{18453}\u{18454}\u{18455}\u{18456}\u{18457}\u{18458}\u{18459}\u{1845A}\u{1845B}\u{1845C}\u{1845D}\u{1845E}\u{1845F}\u{18460}\u{18461}\u{18462}\u{18463}\u{18464}\u{18465}\u{18466}\u{18467}\u{18468}\u{18469}\u{1846A}\u{1846B}\u{1846C}\u{1846D}\u{1846E}\u{1846F}\u{18470}\u{18471}\u{18472}\u{18473}\u{18474}\u{18475}\u{18476}\u{18477}\u{18478}\u{18479}\u{1847A}\u{1847B}\u{1847C}\u{1847D}\u{1847E}\u{1847F}\u{18480}\u{18481}\u{18482}\u{18483}\u{18484}\u{18485}\u{18486}\u{18487}\u{18488}\u{18489}\u{1848A}\u{1848B}\u{1848C}\u{1848D}\u{1848E}\u{1848F}\u{18490}\u{18491}\u{18492}\u{18493}\u{18494}\u{18495}\u{18496}\u{18497}\u{18498}\u{18499}\u{1849A}\u{1849B}\u{1849C}\u{1849D}\u{1849E}\u{1849F}\u{184A0}\u{184A1}\u{184A2}\u{184A3}\u{184A4}\u{184A5}\u{184A6}\u{184A7}\u{184A8}\u{184A9}\u{184AA}\u{184AB}\u{184AC}\u{184AD}\u{184AE}\u{184AF}\u{184B0}\u{184B1}\u{184B2}\u{184B3}\u{184B4}\u{184B5}\u{184B6}\u{184B7}\u{184B8}\u{184B9}\u{184BA}\u{184BB}\u{184BC}\u{184BD}\u{184BE}\u{184BF}\u{184C0}\u{184C1}\u{184C2}\u{184C3}\u{184C4}\u{184C5}\u{184C6}\u{184C7}\u{184C8}\u{184C9}\u{184CA}\u{184CB}\u{184CC}\u{184CD}\u{184CE}\u{184CF}\u{184D0}\u{184D1}\u{184D2}\u{184D3}\u{184D4}\u{184D5}\u{184D6}\u{184D7}\u{184D8}\u{184D9}\u{184DA}\u{184DB}\u{184DC}\u{184DD}\u{184DE}\u{184DF}\u{184E0}\u{184E1}\u{184E2}\u{184E3}\u{184E4}\u{184E5}\u{184E6}\u{184E7}\u{184E8}\u{184E9}\u{184EA}\u{184EB}\u{184EC}\u{184ED}\u{184EE}\u{184EF}\u{184F0}\u{184F1}\u{184F2}\u{184F3}\u{184F4}\u{184F5}\u{184F6}\u{184F7}\u{184F8}\u{184F9}\u{184FA}\u{184FB}\u{184FC}\u{184FD}\u{184FE}\u{184FF}\u{18500}\u{18501}\u{18502}\u{18503}\u{18504}\u{18505}\u{18506}\u{18507}\u{18508}\u{18509}\u{1850A}\u{1850B}\u{1850C}\u{1850D}\u{1850E}\u{1850F}\u{18510}\u{18511}\u{18512}\u{18513}\u{18514}\u{18515}\u{18516}\u{18517}\u{18518}\u{18519}\u{1851A}\u{1851B}\u{1851C}\u{1851D}\u{1851E}\u{1851F}\u{18520}\u{18521}\u{18522}\u{18523}\u{18524}\u{18525}\u{18526}\u{18527}\u{18528}\u{18529}\u{1852A}\u{1852B}\u{1852C}\u{1852D}\u{1852E}\u{1852F}\u{18530}\u{18531}\u{18532}\u{18533}\u{18534}\u{18535}\u{18536}\u{18537}\u{18538}\u{18539}\u{1853A}\u{1853B}\u{1853C}\u{1853D}\u{1853E}\u{1853F}\u{18540}\u{18541}\u{18542}\u{18543}\u{18544}\u{18545}\u{18546}\u{18547}\u{18548}\u{18549}\u{1854A}\u{1854B}\u{1854C}\u{1854D}\u{1854E}\u{1854F}\u{18550}\u{18551}\u{18552}\u{18553}\u{18554}\u{18555}\u{18556}\u{18557}\u{18558}\u{18559}\u{1855A}\u{1855B}\u{1855C}\u{1855D}\u{1855E}\u{1855F}\u{18560}\u{18561}\u{18562}\u{18563}\u{18564}\u{18565}\u{18566}\u{18567}\u{18568}\u{18569}\u{1856A}\u{1856B}\u{1856C}\u{1856D}\u{1856E}\u{1856F}\u{18570}\u{18571}\u{18572}\u{18573}\u{18574}\u{18575}\u{18576}\u{18577}\u{18578}\u{18579}\u{1857A}\u{1857B}\u{1857C}\u{1857D}\u{1857E}\u{1857F}\u{18580}\u{18581}\u{18582}\u{18583}\u{18584}\u{18585}\u{18586}\u{18587}\u{18588}\u{18589}\u{1858A}\u{1858B}\u{1858C}\u{1858D}\u{1858E}\u{1858F}\u{18590}\u{18591}\u{18592}\u{18593}\u{18594}\u{18595}\u{18596}\u{18597}\u{18598}\u{18599}\u{1859A}\u{1859B}\u{1859C}\u{1859D}\u{1859E}\u{1859F}\u{185A0}\u{185A1}\u{185A2}\u{185A3}\u{185A4}\u{185A5}\u{185A6}\u{185A7}\u{185A8}\u{185A9}\u{185AA}\u{185AB}\u{185AC}\u{185AD}\u{185AE}\u{185AF}\u{185B0}\u{185B1}\u{185B2}\u{185B3}\u{185B4}\u{185B5}\u{185B6}\u{185B7}\u{185B8}\u{185B9}\u{185BA}\u{185BB}\u{185BC}\u{185BD}\u{185BE}\u{185BF}\u{185C0}\u{185C1}\u{185C2}\u{185C3}\u{185C4}\u{185C5}\u{185C6}\u{185C7}\u{185C8}\u{185C9}\u{185CA}\u{185CB}\u{185CC}\u{185CD}\u{185CE}\u{185CF}\u{185D0}\u{185D1}\u{185D2}\u{185D3}\u{185D4}\u{185D5}\u{185D6}\u{185D7}\u{185D8}\u{185D9}\u{185DA}\u{185DB}\u{185DC}\u{185DD}\u{185DE}\u{185DF}\u{185E0}\u{185E1}\u{185E2}\u{185E3}\u{185E4}\u{185E5}\u{185E6}\u{185E7}\u{185E8}\u{185E9}\u{185EA}\u{185EB}\u{185EC}\u{185ED}\u{185EE}\u{185EF}\u{185F0}\u{185F1}\u{185F2}\u{185F3}\u{185F4}\u{185F5}\u{185F6}\u{185F7}\u{185F8}\u{185F9}\u{185FA}\u{185FB}\u{185FC}\u{185FD}\u{185FE}\u{185FF}\u{18600}\u{18601}\u{18602}\u{18603}\u{18604}\u{18605}\u{18606}\u{18607}\u{18608}\u{18609}\u{1860A}\u{1860B}\u{1860C}\u{1860D}\u{1860E}\u{1860F}\u{18610}\u{18611}\u{18612}\u{18613}\u{18614}\u{18615}\u{18616}\u{18617}\u{18618}\u{18619}\u{1861A}\u{1861B}\u{1861C}\u{1861D}\u{1861E}\u{1861F}\u{18620}\u{18621}\u{18622}\u{18623}\u{18624}\u{18625}\u{18626}\u{18627}\u{18628}\u{18629}\u{1862A}\u{1862B}\u{1862C}\u{1862D}\u{1862E}\u{1862F}\u{18630}\u{18631}\u{18632}\u{18633}\u{18634}\u{18635}\u{18636}\u{18637}\u{18638}\u{18639}\u{1863A}\u{1863B}\u{1863C}\u{1863D}\u{1863E}\u{1863F}\u{18640}\u{18641}\u{18642}\u{18643}\u{18644}\u{18645}\u{18646}\u{18647}\u{18648}\u{18649}\u{1864A}\u{1864B}\u{1864C}\u{1864D}\u{1864E}\u{1864F}\u{18650}\u{18651}\u{18652}\u{18653}\u{18654}\u{18655}\u{18656}\u{18657}\u{18658}\u{18659}\u{1865A}\u{1865B}\u{1865C}\u{1865D}\u{1865E}\u{1865F}\u{18660}\u{18661}\u{18662}\u{18663}\u{18664}\u{18665}\u{18666}\u{18667}\u{18668}\u{18669}\u{1866A}\u{1866B}\u{1866C}\u{1866D}\u{1866E}\u{1866F}\u{18670}\u{18671}\u{18672}\u{18673}\u{18674}\u{18675}\u{18676}\u{18677}\u{18678}\u{18679}\u{1867A}\u{1867B}\u{1867C}\u{1867D}\u{1867E}\u{1867F}\u{18680}\u{18681}\u{18682}\u{18683}\u{18684}\u{18685}\u{18686}\u{18687}\u{18688}\u{18689}\u{1868A}\u{1868B}\u{1868C}\u{1868D}\u{1868E}\u{1868F}\u{18690}\u{18691}\u{18692}\u{18693}\u{18694}\u{18695}\u{18696}\u{18697}\u{18698}\u{18699}\u{1869A}\u{1869B}\u{1869C}\u{1869D}\u{1869E}\u{1869F}\u{186A0}\u{186A1}\u{186A2}\u{186A3}\u{186A4}\u{186A5}\u{186A6}\u{186A7}\u{186A8}\u{186A9}\u{186AA}\u{186AB}\u{186AC}\u{186AD}\u{186AE}\u{186AF}\u{186B0}\u{186B1}\u{186B2}\u{186B3}\u{186B4}\u{186B5}\u{186B6}\u{186B7}\u{186B8}\u{186B9}\u{186BA}\u{186BB}\u{186BC}\u{186BD}\u{186BE}\u{186BF}\u{186C0}\u{186C1}\u{186C2}\u{186C3}\u{186C4}\u{186C5}\u{186C6}\u{186C7}\u{186C8}\u{186C9}\u{186CA}\u{186CB}\u{186CC}\u{186CD}\u{186CE}\u{186CF}\u{186D0}\u{186D1}\u{186D2}\u{186D3}\u{186D4}\u{186D5}\u{186D6}\u{186D7}\u{186D8}\u{186D9}\u{186DA}\u{186DB}\u{186DC}\u{186DD}\u{186DE}\u{186DF}\u{186E0}\u{186E1}\u{186E2}\u{186E3}\u{186E4}\u{186E5}\u{186E6}\u{186E7}\u{186E8}\u{186E9}\u{186EA}\u{186EB}\u{186EC}\u{186ED}\u{186EE}\u{186EF}\u{186F0}\u{186F1}\u{186F2}\u{186F3}\u{186F4}\u{186F5}\u{186F6}\u{186F7}\u{186F8}\u{186F9}\u{186FA}\u{186FB}\u{186FC}\u{186FD}\u{186FE}\u{186FF}\u{18700}\u{18701}\u{18702}\u{18703}\u{18704}\u{18705}\u{18706}\u{18707}\u{18708}\u{18709}\u{1870A}\u{1870B}\u{1870C}\u{1870D}\u{1870E}\u{1870F}\u{18710}\u{18711}\u{18712}\u{18713}\u{18714}\u{18715}\u{18716}\u{18717}\u{18718}\u{18719}\u{1871A}\u{1871B}\u{1871C}\u{1871D}\u{1871E}\u{1871F}\u{18720}\u{18721}\u{18722}\u{18723}\u{18724}\u{18725}\u{18726}\u{18727}\u{18728}\u{18729}\u{1872A}\u{1872B}\u{1872C}\u{1872D}\u{1872E}\u{1872F}\u{18730}\u{18731}\u{18732}\u{18733}\u{18734}\u{18735}\u{18736}\u{18737}\u{18738}\u{18739}\u{1873A}\u{1873B}\u{1873C}\u{1873D}\u{1873E}\u{1873F}\u{18740}\u{18741}\u{18742}\u{18743}\u{18744}\u{18745}\u{18746}\u{18747}\u{18748}\u{18749}\u{1874A}\u{1874B}\u{1874C}\u{1874D}\u{1874E}\u{1874F}\u{18750}\u{18751}\u{18752}\u{18753}\u{18754}\u{18755}\u{18756}\u{18757}\u{18758}\u{18759}\u{1875A}\u{1875B}\u{1875C}\u{1875D}\u{1875E}\u{1875F}\u{18760}\u{18761}\u{18762}\u{18763}\u{18764}\u{18765}\u{18766}\u{18767}\u{18768}\u{18769}\u{1876A}\u{1876B}\u{1876C}\u{1876D}\u{1876E}\u{1876F}\u{18770}\u{18771}\u{18772}\u{18773}\u{18774}\u{18775}\u{18776}\u{18777}\u{18778}\u{18779}\u{1877A}\u{1877B}\u{1877C}\u{1877D}\u{1877E}\u{1877F}\u{18780}\u{18781}\u{18782}\u{18783}\u{18784}\u{18785}\u{18786}\u{18787}\u{18788}\u{18789}\u{1878A}\u{1878B}\u{1878C}\u{1878D}\u{1878E}\u{1878F}\u{18790}\u{18791}\u{18792}\u{18793}\u{18794}\u{18795}\u{18796}\u{18797}\u{18798}\u{18799}\u{1879A}\u{1879B}\u{1879C}\u{1879D}\u{1879E}\u{1879F}\u{187A0}\u{187A1}\u{187A2}\u{187A3}\u{187A4}\u{187A5}\u{187A6}\u{187A7}\u{187A8}\u{187A9}\u{187AA}\u{187AB}\u{187AC}\u{187AD}\u{187AE}\u{187AF}\u{187B0}\u{187B1}\u{187B2}\u{187B3}\u{187B4}\u{187B5}\u{187B6}\u{187B7}\u{187B8}\u{187B9}\u{187BA}\u{187BB}\u{187BC}\u{187BD}\u{187BE}\u{187BF}\u{187C0}\u{187C1}\u{187C2}\u{187C3}\u{187C4}\u{187C5}\u{187C6}\u{187C7}\u{187C8}\u{187C9}\u{187CA}\u{187CB}\u{187CC}\u{187CD}\u{187CE}\u{187CF}\u{187D0}\u{187D1}\u{187D2}\u{187D3}\u{187D4}\u{187D5}\u{187D6}\u{187D7}\u{187D8}\u{187D9}\u{187DA}\u{187DB}\u{187DC}\u{187DD}\u{187DE}\u{187DF}\u{187E0}\u{187E1}\u{187E2}\u{187E3}\u{187E4}\u{187E5}\u{187E6}\u{187E7}\u{187E8}\u{187E9}\u{187EA}\u{187EB}\u{187EC}\u{18800}\u{18801}\u{18802}\u{18803}\u{18804}\u{18805}\u{18806}\u{18807}\u{18808}\u{18809}\u{1880A}\u{1880B}\u{1880C}\u{1880D}\u{1880E}\u{1880F}\u{18810}\u{18811}\u{18812}\u{18813}\u{18814}\u{18815}\u{18816}\u{18817}\u{18818}\u{18819}\u{1881A}\u{1881B}\u{1881C}\u{1881D}\u{1881E}\u{1881F}\u{18820}\u{18821}\u{18822}\u{18823}\u{18824}\u{18825}\u{18826}\u{18827}\u{18828}\u{18829}\u{1882A}\u{1882B}\u{1882C}\u{1882D}\u{1882E}\u{1882F}\u{18830}\u{18831}\u{18832}\u{18833}\u{18834}\u{18835}\u{18836}\u{18837}\u{18838}\u{18839}\u{1883A}\u{1883B}\u{1883C}\u{1883D}\u{1883E}\u{1883F}\u{18840}\u{18841}\u{18842}\u{18843}\u{18844}\u{18845}\u{18846}\u{18847}\u{18848}\u{18849}\u{1884A}\u{1884B}\u{1884C}\u{1884D}\u{1884E}\u{1884F}\u{18850}\u{18851}\u{18852}\u{18853}\u{18854}\u{18855}\u{18856}\u{18857}\u{18858}\u{18859}\u{1885A}\u{1885B}\u{1885C}\u{1885D}\u{1885E}\u{1885F}\u{18860}\u{18861}\u{18862}\u{18863}\u{18864}\u{18865}\u{18866}\u{18867}\u{18868}\u{18869}\u{1886A}\u{1886B}\u{1886C}\u{1886D}\u{1886E}\u{1886F}\u{18870}\u{18871}\u{18872}\u{18873}\u{18874}\u{18875}\u{18876}\u{18877}\u{18878}\u{18879}\u{1887A}\u{1887B}\u{1887C}\u{1887D}\u{1887E}\u{1887F}\u{18880}\u{18881}\u{18882}\u{18883}\u{18884}\u{18885}\u{18886}\u{18887}\u{18888}\u{18889}\u{1888A}\u{1888B}\u{1888C}\u{1888D}\u{1888E}\u{1888F}\u{18890}\u{18891}\u{18892}\u{18893}\u{18894}\u{18895}\u{18896}\u{18897}\u{18898}\u{18899}\u{1889A}\u{1889B}\u{1889C}\u{1889D}\u{1889E}\u{1889F}\u{188A0}\u{188A1}\u{188A2}\u{188A3}\u{188A4}\u{188A5}\u{188A6}\u{188A7}\u{188A8}\u{188A9}\u{188AA}\u{188AB}\u{188AC}\u{188AD}\u{188AE}\u{188AF}\u{188B0}\u{188B1}\u{188B2}\u{188B3}\u{188B4}\u{188B5}\u{188B6}\u{188B7}\u{188B8}\u{188B9}\u{188BA}\u{188BB}\u{188BC}\u{188BD}\u{188BE}\u{188BF}\u{188C0}\u{188C1}\u{188C2}\u{188C3}\u{188C4}\u{188C5}\u{188C6}\u{188C7}\u{188C8}\u{188C9}\u{188CA}\u{188CB}\u{188CC}\u{188CD}\u{188CE}\u{188CF}\u{188D0}\u{188D1}\u{188D2}\u{188D3}\u{188D4}\u{188D5}\u{188D6}\u{188D7}\u{188D8}\u{188D9}\u{188DA}\u{188DB}\u{188DC}\u{188DD}\u{188DE}\u{188DF}\u{188E0}\u{188E1}\u{188E2}\u{188E3}\u{188E4}\u{188E5}\u{188E6}\u{188E7}\u{188E8}\u{188E9}\u{188EA}\u{188EB}\u{188EC}\u{188ED}\u{188EE}\u{188EF}\u{188F0}\u{188F1}\u{188F2}\u{188F3}\u{188F4}\u{188F5}\u{188F6}\u{188F7}\u{188F8}\u{188F9}\u{188FA}\u{188FB}\u{188FC}\u{188FD}\u{188FE}\u{188FF}\u{18900}\u{18901}\u{18902}\u{18903}\u{18904}\u{18905}\u{18906}\u{18907}\u{18908}\u{18909}\u{1890A}\u{1890B}\u{1890C}\u{1890D}\u{1890E}\u{1890F}\u{18910}\u{18911}\u{18912}\u{18913}\u{18914}\u{18915}\u{18916}\u{18917}\u{18918}\u{18919}\u{1891A}\u{1891B}\u{1891C}\u{1891D}\u{1891E}\u{1891F}\u{18920}\u{18921}\u{18922}\u{18923}\u{18924}\u{18925}\u{18926}\u{18927}\u{18928}\u{18929}\u{1892A}\u{1892B}\u{1892C}\u{1892D}\u{1892E}\u{1892F}\u{18930}\u{18931}\u{18932}\u{18933}\u{18934}\u{18935}\u{18936}\u{18937}\u{18938}\u{18939}\u{1893A}\u{1893B}\u{1893C}\u{1893D}\u{1893E}\u{1893F}\u{18940}\u{18941}\u{18942}\u{18943}\u{18944}\u{18945}\u{18946}\u{18947}\u{18948}\u{18949}\u{1894A}\u{1894B}\u{1894C}\u{1894D}\u{1894E}\u{1894F}\u{18950}\u{18951}\u{18952}\u{18953}\u{18954}\u{18955}\u{18956}\u{18957}\u{18958}\u{18959}\u{1895A}\u{1895B}\u{1895C}\u{1895D}\u{1895E}\u{1895F}\u{18960}\u{18961}\u{18962}\u{18963}\u{18964}\u{18965}\u{18966}\u{18967}\u{18968}\u{18969}\u{1896A}\u{1896B}\u{1896C}\u{1896D}\u{1896E}\u{1896F}\u{18970}\u{18971}\u{18972}\u{18973}\u{18974}\u{18975}\u{18976}\u{18977}\u{18978}\u{18979}\u{1897A}\u{1897B}\u{1897C}\u{1897D}\u{1897E}\u{1897F}\u{18980}\u{18981}\u{18982}\u{18983}\u{18984}\u{18985}\u{18986}\u{18987}\u{18988}\u{18989}\u{1898A}\u{1898B}\u{1898C}\u{1898D}\u{1898E}\u{1898F}\u{18990}\u{18991}\u{18992}\u{18993}\u{18994}\u{18995}\u{18996}\u{18997}\u{18998}\u{18999}\u{1899A}\u{1899B}\u{1899C}\u{1899D}\u{1899E}\u{1899F}\u{189A0}\u{189A1}\u{189A2}\u{189A3}\u{189A4}\u{189A5}\u{189A6}\u{189A7}\u{189A8}\u{189A9}\u{189AA}\u{189AB}\u{189AC}\u{189AD}\u{189AE}\u{189AF}\u{189B0}\u{189B1}\u{189B2}\u{189B3}\u{189B4}\u{189B5}\u{189B6}\u{189B7}\u{189B8}\u{189B9}\u{189BA}\u{189BB}\u{189BC}\u{189BD}\u{189BE}\u{189BF}\u{189C0}\u{189C1}\u{189C2}\u{189C3}\u{189C4}\u{189C5}\u{189C6}\u{189C7}\u{189C8}\u{189C9}\u{189CA}\u{189CB}\u{189CC}\u{189CD}\u{189CE}\u{189CF}\u{189D0}\u{189D1}\u{189D2}\u{189D3}\u{189D4}\u{189D5}\u{189D6}\u{189D7}\u{189D8}\u{189D9}\u{189DA}\u{189DB}\u{189DC}\u{189DD}\u{189DE}\u{189DF}\u{189E0}\u{189E1}\u{189E2}\u{189E3}\u{189E4}\u{189E5}\u{189E6}\u{189E7}\u{189E8}\u{189E9}\u{189EA}\u{189EB}\u{189EC}\u{189ED}\u{189EE}\u{189EF}\u{189F0}\u{189F1}\u{189F2}\u{189F3}\u{189F4}\u{189F5}\u{189F6}\u{189F7}\u{189F8}\u{189F9}\u{189FA}\u{189FB}\u{189FC}\u{189FD}\u{189FE}\u{189FF}\u{18A00}\u{18A01}\u{18A02}\u{18A03}\u{18A04}\u{18A05}\u{18A06}\u{18A07}\u{18A08}\u{18A09}\u{18A0A}\u{18A0B}\u{18A0C}\u{18A0D}\u{18A0E}\u{18A0F}\u{18A10}\u{18A11}\u{18A12}\u{18A13}\u{18A14}\u{18A15}\u{18A16}\u{18A17}\u{18A18}\u{18A19}\u{18A1A}\u{18A1B}\u{18A1C}\u{18A1D}\u{18A1E}\u{18A1F}\u{18A20}\u{18A21}\u{18A22}\u{18A23}\u{18A24}\u{18A25}\u{18A26}\u{18A27}\u{18A28}\u{18A29}\u{18A2A}\u{18A2B}\u{18A2C}\u{18A2D}\u{18A2E}\u{18A2F}\u{18A30}\u{18A31}\u{18A32}\u{18A33}\u{18A34}\u{18A35}\u{18A36}\u{18A37}\u{18A38}\u{18A39}\u{18A3A}\u{18A3B}\u{18A3C}\u{18A3D}\u{18A3E}\u{18A3F}\u{18A40}\u{18A41}\u{18A42}\u{18A43}\u{18A44}\u{18A45}\u{18A46}\u{18A47}\u{18A48}\u{18A49}\u{18A4A}\u{18A4B}\u{18A4C}\u{18A4D}\u{18A4E}\u{18A4F}\u{18A50}\u{18A51}\u{18A52}\u{18A53}\u{18A54}\u{18A55}\u{18A56}\u{18A57}\u{18A58}\u{18A59}\u{18A5A}\u{18A5B}\u{18A5C}\u{18A5D}\u{18A5E}\u{18A5F}\u{18A60}\u{18A61}\u{18A62}\u{18A63}\u{18A64}\u{18A65}\u{18A66}\u{18A67}\u{18A68}\u{18A69}\u{18A6A}\u{18A6B}\u{18A6C}\u{18A6D}\u{18A6E}\u{18A6F}\u{18A70}\u{18A71}\u{18A72}\u{18A73}\u{18A74}\u{18A75}\u{18A76}\u{18A77}\u{18A78}\u{18A79}\u{18A7A}\u{18A7B}\u{18A7C}\u{18A7D}\u{18A7E}\u{18A7F}\u{18A80}\u{18A81}\u{18A82}\u{18A83}\u{18A84}\u{18A85}\u{18A86}\u{18A87}\u{18A88}\u{18A89}\u{18A8A}\u{18A8B}\u{18A8C}\u{18A8D}\u{18A8E}\u{18A8F}\u{18A90}\u{18A91}\u{18A92}\u{18A93}\u{18A94}\u{18A95}\u{18A96}\u{18A97}\u{18A98}\u{18A99}\u{18A9A}\u{18A9B}\u{18A9C}\u{18A9D}\u{18A9E}\u{18A9F}\u{18AA0}\u{18AA1}\u{18AA2}\u{18AA3}\u{18AA4}\u{18AA5}\u{18AA6}\u{18AA7}\u{18AA8}\u{18AA9}\u{18AAA}\u{18AAB}\u{18AAC}\u{18AAD}\u{18AAE}\u{18AAF}\u{18AB0}\u{18AB1}\u{18AB2}\u{18AB3}\u{18AB4}\u{18AB5}\u{18AB6}\u{18AB7}\u{18AB8}\u{18AB9}\u{18ABA}\u{18ABB}\u{18ABC}\u{18ABD}\u{18ABE}\u{18ABF}\u{18AC0}\u{18AC1}\u{18AC2}\u{18AC3}\u{18AC4}\u{18AC5}\u{18AC6}\u{18AC7}\u{18AC8}\u{18AC9}\u{18ACA}\u{18ACB}\u{18ACC}\u{18ACD}\u{18ACE}\u{18ACF}\u{18AD0}\u{18AD1}\u{18AD2}\u{18AD3}\u{18AD4}\u{18AD5}\u{18AD6}\u{18AD7}\u{18AD8}\u{18AD9}\u{18ADA}\u{18ADB}\u{18ADC}\u{18ADD}\u{18ADE}\u{18ADF}\u{18AE0}\u{18AE1}\u{18AE2}\u{18AE3}\u{18AE4}\u{18AE5}\u{18AE6}\u{18AE7}\u{18AE8}\u{18AE9}\u{18AEA}\u{18AEB}\u{18AEC}\u{18AED}\u{18AEE}\u{18AEF}\u{18AF0}\u{18AF1}\u{18AF2}\u{1E900}\u{1E901}\u{1E902}\u{1E903}\u{1E904}\u{1E905}\u{1E906}\u{1E907}\u{1E908}\u{1E909}\u{1E90A}\u{1E90B}\u{1E90C}\u{1E90D}\u{1E90E}\u{1E90F}\u{1E910}\u{1E911}\u{1E912}\u{1E913}\u{1E914}\u{1E915}\u{1E916}\u{1E917}\u{1E918}\u{1E919}\u{1E91A}\u{1E91B}\u{1E91C}\u{1E91D}\u{1E91E}\u{1E91F}\u{1E920}\u{1E921}\u{1E922}\u{1E923}\u{1E924}\u{1E925}\u{1E926}\u{1E927}\u{1E928}\u{1E929}\u{1E92A}\u{1E92B}\u{1E92C}\u{1E92D}\u{1E92E}\u{1E92F}\u{1E930}\u{1E931}\u{1E932}\u{1E933}\u{1E934}\u{1E935}\u{1E936}\u{1E937}\u{1E938}\u{1E939}\u{1E93A}\u{1E93B}\u{1E93C}\u{1E93D}\u{1E93E}\u{1E93F}\u{1E940}\u{1E941}\u{1E942}\u{1E943}; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-class.js b/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-class.js new file mode 100644 index 000000000000..48ce264abe5b --- /dev/null +++ b/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-class.js @@ -0,0 +1,19 @@ +// Copyright 2022 Mathias Bynens. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Mathias Bynens +esid: prod-PrivateIdentifier +description: | + Test that Unicode v9.0.0 ID_Start characters are accepted as + identifier start characters in private class fields. +info: | + Generated by https://github.com/mathiasbynens/caniunicode +features: [class, class-fields-private] +---*/ + +class _ { + #ࢶࢷࢸࢹࢺࢻࢼࢽಀൔൕൖᲀᲁᲂᲃᲄᲅᲆᲇᲈꞮ𐒰𐒱𐒲𐒳𐒴𐒵𐒶𐒷𐒸𐒹𐒺𐒻𐒼𐒽𐒾𐒿𐓀𐓁𐓂𐓃𐓄𐓅𐓆𐓇𐓈𐓉𐓊𐓋𐓌𐓍𐓎𐓏𐓐𐓑𐓒𐓓𐓘𐓙𐓚𐓛𐓜𐓝𐓞𐓟𐓠𐓡𐓢𐓣𐓤𐓥𐓦𐓧𐓨𐓩𐓪𐓫𐓬𐓭𐓮𐓯𐓰𐓱𐓲𐓳𐓴𐓵𐓶𐓷𐓸𐓹𐓺𐓻𑐀𑐁𑐂𑐃𑐄𑐅𑐆𑐇𑐈𑐉𑐊𑐋𑐌𑐍𑐎𑐏𑐐𑐑𑐒𑐓𑐔𑐕𑐖𑐗𑐘𑐙𑐚𑐛𑐜𑐝𑐞𑐟𑐠𑐡𑐢𑐣𑐤𑐥𑐦𑐧𑐨𑐩𑐪𑐫𑐬𑐭𑐮𑐯𑐰𑐱𑐲𑐳𑐴𑑇𑑈𑑉𑑊𑰀𑰁𑰂𑰃𑰄𑰅𑰆𑰇𑰈𑰊𑰋𑰌𑰍𑰎𑰏𑰐𑰑𑰒𑰓𑰔𑰕𑰖𑰗𑰘𑰙𑰚𑰛𑰜𑰝𑰞𑰟𑰠𑰡𑰢𑰣𑰤𑰥𑰦𑰧𑰨𑰩𑰪𑰫𑰬𑰭𑰮𑱀𑱲𑱳𑱴𑱵𑱶𑱷𑱸𑱹𑱺𑱻𑱼𑱽𑱾𑱿𑲀𑲁𑲂𑲃𑲄𑲅𑲆𑲇𑲈𑲉𑲊𑲋𑲌𑲍𑲎𑲏𖿠𗀀𗀁𗀂𗀃𗀄𗀅𗀆𗀇𗀈𗀉𗀊𗀋𗀌𗀍𗀎𗀏𗀐𗀑𗀒𗀓𗀔𗀕𗀖𗀗𗀘𗀙𗀚𗀛𗀜𗀝𗀞𗀟𗀠𗀡𗀢𗀣𗀤𗀥𗀦𗀧𗀨𗀩𗀪𗀫𗀬𗀭𗀮𗀯𗀰𗀱𗀲𗀳𗀴𗀵𗀶𗀷𗀸𗀹𗀺𗀻𗀼𗀽𗀾𗀿𗁀𗁁𗁂𗁃𗁄𗁅𗁆𗁇𗁈𗁉𗁊𗁋𗁌𗁍𗁎𗁏𗁐𗁑𗁒𗁓𗁔𗁕𗁖𗁗𗁘𗁙𗁚𗁛𗁜𗁝𗁞𗁟𗁠𗁡𗁢𗁣𗁤𗁥𗁦𗁧𗁨𗁩𗁪𗁫𗁬𗁭𗁮𗁯𗁰𗁱𗁲𗁳𗁴𗁵𗁶𗁷𗁸𗁹𗁺𗁻𗁼𗁽𗁾𗁿𗂀𗂁𗂂𗂃𗂄𗂅𗂆𗂇𗂈𗂉𗂊𗂋𗂌𗂍𗂎𗂏𗂐𗂑𗂒𗂓𗂔𗂕𗂖𗂗𗂘𗂙𗂚𗂛𗂜𗂝𗂞𗂟𗂠𗂡𗂢𗂣𗂤𗂥𗂦𗂧𗂨𗂩𗂪𗂫𗂬𗂭𗂮𗂯𗂰𗂱𗂲𗂳𗂴𗂵𗂶𗂷𗂸𗂹𗂺𗂻𗂼𗂽𗂾𗂿𗃀𗃁𗃂𗃃𗃄𗃅𗃆𗃇𗃈𗃉𗃊𗃋𗃌𗃍𗃎𗃏𗃐𗃑𗃒𗃓𗃔𗃕𗃖𗃗𗃘𗃙𗃚𗃛𗃜𗃝𗃞𗃟𗃠𗃡𗃢𗃣𗃤𗃥𗃦𗃧𗃨𗃩𗃪𗃫𗃬𗃭𗃮𗃯𗃰𗃱𗃲𗃳𗃴𗃵𗃶𗃷𗃸𗃹𗃺𗃻𗃼𗃽𗃾𗃿𗄀𗄁𗄂𗄃𗄄𗄅𗄆𗄇𗄈𗄉𗄊𗄋𗄌𗄍𗄎𗄏𗄐𗄑𗄒𗄓𗄔𗄕𗄖𗄗𗄘𗄙𗄚𗄛𗄜𗄝𗄞𗄟𗄠𗄡𗄢𗄣𗄤𗄥𗄦𗄧𗄨𗄩𗄪𗄫𗄬𗄭𗄮𗄯𗄰𗄱𗄲𗄳𗄴𗄵𗄶𗄷𗄸𗄹𗄺𗄻𗄼𗄽𗄾𗄿𗅀𗅁𗅂𗅃𗅄𗅅𗅆𗅇𗅈𗅉𗅊𗅋𗅌𗅍𗅎𗅏𗅐𗅑𗅒𗅓𗅔𗅕𗅖𗅗𗅘𗅙𗅚𗅛𗅜𗅝𗅞𗅟𗅠𗅡𗅢𗅣𗅤𗅥𗅦𗅧𗅨𗅩𗅪𗅫𗅬𗅭𗅮𗅯𗅰𗅱𗅲𗅳𗅴𗅵𗅶𗅷𗅸𗅹𗅺𗅻𗅼𗅽𗅾𗅿𗆀𗆁𗆂𗆃𗆄𗆅𗆆𗆇𗆈𗆉𗆊𗆋𗆌𗆍𗆎𗆏𗆐𗆑𗆒𗆓𗆔𗆕𗆖𗆗𗆘𗆙𗆚𗆛𗆜𗆝𗆞𗆟𗆠𗆡𗆢𗆣𗆤𗆥𗆦𗆧𗆨𗆩𗆪𗆫𗆬𗆭𗆮𗆯𗆰𗆱𗆲𗆳𗆴𗆵𗆶𗆷𗆸𗆹𗆺𗆻𗆼𗆽𗆾𗆿𗇀𗇁𗇂𗇃𗇄𗇅𗇆𗇇𗇈𗇉𗇊𗇋𗇌𗇍𗇎𗇏𗇐𗇑𗇒𗇓𗇔𗇕𗇖𗇗𗇘𗇙𗇚𗇛𗇜𗇝𗇞𗇟𗇠𗇡𗇢𗇣𗇤𗇥𗇦𗇧𗇨𗇩𗇪𗇫𗇬𗇭𗇮𗇯𗇰𗇱𗇲𗇳𗇴𗇵𗇶𗇷𗇸𗇹𗇺𗇻𗇼𗇽𗇾𗇿𗈀𗈁𗈂𗈃𗈄𗈅𗈆𗈇𗈈𗈉𗈊𗈋𗈌𗈍𗈎𗈏𗈐𗈑𗈒𗈓𗈔𗈕𗈖𗈗𗈘𗈙𗈚𗈛𗈜𗈝𗈞𗈟𗈠𗈡𗈢𗈣𗈤𗈥𗈦𗈧𗈨𗈩𗈪𗈫𗈬𗈭𗈮𗈯𗈰𗈱𗈲𗈳𗈴𗈵𗈶𗈷𗈸𗈹𗈺𗈻𗈼𗈽𗈾𗈿𗉀𗉁𗉂𗉃𗉄𗉅𗉆𗉇𗉈𗉉𗉊𗉋𗉌𗉍𗉎𗉏𗉐𗉑𗉒𗉓𗉔𗉕𗉖𗉗𗉘𗉙𗉚𗉛𗉜𗉝𗉞𗉟𗉠𗉡𗉢𗉣𗉤𗉥𗉦𗉧𗉨𗉩𗉪𗉫𗉬𗉭𗉮𗉯𗉰𗉱𗉲𗉳𗉴𗉵𗉶𗉷𗉸𗉹𗉺𗉻𗉼𗉽𗉾𗉿𗊀𗊁𗊂𗊃𗊄𗊅𗊆𗊇𗊈𗊉𗊊𗊋𗊌𗊍𗊎𗊏𗊐𗊑𗊒𗊓𗊔𗊕𗊖𗊗𗊘𗊙𗊚𗊛𗊜𗊝𗊞𗊟𗊠𗊡𗊢𗊣𗊤𗊥𗊦𗊧𗊨𗊩𗊪𗊫𗊬𗊭𗊮𗊯𗊰𗊱𗊲𗊳𗊴𗊵𗊶𗊷𗊸𗊹𗊺𗊻𗊼𗊽𗊾𗊿𗋀𗋁𗋂𗋃𗋄𗋅𗋆𗋇𗋈𗋉𗋊𗋋𗋌𗋍𗋎𗋏𗋐𗋑𗋒𗋓𗋔𗋕𗋖𗋗𗋘𗋙𗋚𗋛𗋜𗋝𗋞𗋟𗋠𗋡𗋢𗋣𗋤𗋥𗋦𗋧𗋨𗋩𗋪𗋫𗋬𗋭𗋮𗋯𗋰𗋱𗋲𗋳𗋴𗋵𗋶𗋷𗋸𗋹𗋺𗋻𗋼𗋽𗋾𗋿𗌀𗌁𗌂𗌃𗌄𗌅𗌆𗌇𗌈𗌉𗌊𗌋𗌌𗌍𗌎𗌏𗌐𗌑𗌒𗌓𗌔𗌕𗌖𗌗𗌘𗌙𗌚𗌛𗌜𗌝𗌞𗌟𗌠𗌡𗌢𗌣𗌤𗌥𗌦𗌧𗌨𗌩𗌪𗌫𗌬𗌭𗌮𗌯𗌰𗌱𗌲𗌳𗌴𗌵𗌶𗌷𗌸𗌹𗌺𗌻𗌼𗌽𗌾𗌿𗍀𗍁𗍂𗍃𗍄𗍅𗍆𗍇𗍈𗍉𗍊𗍋𗍌𗍍𗍎𗍏𗍐𗍑𗍒𗍓𗍔𗍕𗍖𗍗𗍘𗍙𗍚𗍛𗍜𗍝𗍞𗍟𗍠𗍡𗍢𗍣𗍤𗍥𗍦𗍧𗍨𗍩𗍪𗍫𗍬𗍭𗍮𗍯𗍰𗍱𗍲𗍳𗍴𗍵𗍶𗍷𗍸𗍹𗍺𗍻𗍼𗍽𗍾𗍿𗎀𗎁𗎂𗎃𗎄𗎅𗎆𗎇𗎈𗎉𗎊𗎋𗎌𗎍𗎎𗎏𗎐𗎑𗎒𗎓𗎔𗎕𗎖𗎗𗎘𗎙𗎚𗎛𗎜𗎝𗎞𗎟𗎠𗎡𗎢𗎣𗎤𗎥𗎦𗎧𗎨𗎩𗎪𗎫𗎬𗎭𗎮𗎯𗎰𗎱𗎲𗎳𗎴𗎵𗎶𗎷𗎸𗎹𗎺𗎻𗎼𗎽𗎾𗎿𗏀𗏁𗏂𗏃𗏄𗏅𗏆𗏇𗏈𗏉𗏊𗏋𗏌𗏍𗏎𗏏𗏐𗏑𗏒𗏓𗏔𗏕𗏖𗏗𗏘𗏙𗏚𗏛𗏜𗏝𗏞𗏟𗏠𗏡𗏢𗏣𗏤𗏥𗏦𗏧𗏨𗏩𗏪𗏫𗏬𗏭𗏮𗏯𗏰𗏱𗏲𗏳𗏴𗏵𗏶𗏷𗏸𗏹𗏺𗏻𗏼𗏽𗏾𗏿𗐀𗐁𗐂𗐃𗐄𗐅𗐆𗐇𗐈𗐉𗐊𗐋𗐌𗐍𗐎𗐏𗐐𗐑𗐒𗐓𗐔𗐕𗐖𗐗𗐘𗐙𗐚𗐛𗐜𗐝𗐞𗐟𗐠𗐡𗐢𗐣𗐤𗐥𗐦𗐧𗐨𗐩𗐪𗐫𗐬𗐭𗐮𗐯𗐰𗐱𗐲𗐳𗐴𗐵𗐶𗐷𗐸𗐹𗐺𗐻𗐼𗐽𗐾𗐿𗑀𗑁𗑂𗑃𗑄𗑅𗑆𗑇𗑈𗑉𗑊𗑋𗑌𗑍𗑎𗑏𗑐𗑑𗑒𗑓𗑔𗑕𗑖𗑗𗑘𗑙𗑚𗑛𗑜𗑝𗑞𗑟𗑠𗑡𗑢𗑣𗑤𗑥𗑦𗑧𗑨𗑩𗑪𗑫𗑬𗑭𗑮𗑯𗑰𗑱𗑲𗑳𗑴𗑵𗑶𗑷𗑸𗑹𗑺𗑻𗑼𗑽𗑾𗑿𗒀𗒁𗒂𗒃𗒄𗒅𗒆𗒇𗒈𗒉𗒊𗒋𗒌𗒍𗒎𗒏𗒐𗒑𗒒𗒓𗒔𗒕𗒖𗒗𗒘𗒙𗒚𗒛𗒜𗒝𗒞𗒟𗒠𗒡𗒢𗒣𗒤𗒥𗒦𗒧𗒨𗒩𗒪𗒫𗒬𗒭𗒮𗒯𗒰𗒱𗒲𗒳𗒴𗒵𗒶𗒷𗒸𗒹𗒺𗒻𗒼𗒽𗒾𗒿𗓀𗓁𗓂𗓃𗓄𗓅𗓆𗓇𗓈𗓉𗓊𗓋𗓌𗓍𗓎𗓏𗓐𗓑𗓒𗓓𗓔𗓕𗓖𗓗𗓘𗓙𗓚𗓛𗓜𗓝𗓞𗓟𗓠𗓡𗓢𗓣𗓤𗓥𗓦𗓧𗓨𗓩𗓪𗓫𗓬𗓭𗓮𗓯𗓰𗓱𗓲𗓳𗓴𗓵𗓶𗓷𗓸𗓹𗓺𗓻𗓼𗓽𗓾𗓿𗔀𗔁𗔂𗔃𗔄𗔅𗔆𗔇𗔈𗔉𗔊𗔋𗔌𗔍𗔎𗔏𗔐𗔑𗔒𗔓𗔔𗔕𗔖𗔗𗔘𗔙𗔚𗔛𗔜𗔝𗔞𗔟𗔠𗔡𗔢𗔣𗔤𗔥𗔦𗔧𗔨𗔩𗔪𗔫𗔬𗔭𗔮𗔯𗔰𗔱𗔲𗔳𗔴𗔵𗔶𗔷𗔸𗔹𗔺𗔻𗔼𗔽𗔾𗔿𗕀𗕁𗕂𗕃𗕄𗕅𗕆𗕇𗕈𗕉𗕊𗕋𗕌𗕍𗕎𗕏𗕐𗕑𗕒𗕓𗕔𗕕𗕖𗕗𗕘𗕙𗕚𗕛𗕜𗕝𗕞𗕟𗕠𗕡𗕢𗕣𗕤𗕥𗕦𗕧𗕨𗕩𗕪𗕫𗕬𗕭𗕮𗕯𗕰𗕱𗕲𗕳𗕴𗕵𗕶𗕷𗕸𗕹𗕺𗕻𗕼𗕽𗕾𗕿𗖀𗖁𗖂𗖃𗖄𗖅𗖆𗖇𗖈𗖉𗖊𗖋𗖌𗖍𗖎𗖏𗖐𗖑𗖒𗖓𗖔𗖕𗖖𗖗𗖘𗖙𗖚𗖛𗖜𗖝𗖞𗖟𗖠𗖡𗖢𗖣𗖤𗖥𗖦𗖧𗖨𗖩𗖪𗖫𗖬𗖭𗖮𗖯𗖰𗖱𗖲𗖳𗖴𗖵𗖶𗖷𗖸𗖹𗖺𗖻𗖼𗖽𗖾𗖿𗗀𗗁𗗂𗗃𗗄𗗅𗗆𗗇𗗈𗗉𗗊𗗋𗗌𗗍𗗎𗗏𗗐𗗑𗗒𗗓𗗔𗗕𗗖𗗗𗗘𗗙𗗚𗗛𗗜𗗝𗗞𗗟𗗠𗗡𗗢𗗣𗗤𗗥𗗦𗗧𗗨𗗩𗗪𗗫𗗬𗗭𗗮𗗯𗗰𗗱𗗲𗗳𗗴𗗵𗗶𗗷𗗸𗗹𗗺𗗻𗗼𗗽𗗾𗗿𗘀𗘁𗘂𗘃𗘄𗘅𗘆𗘇𗘈𗘉𗘊𗘋𗘌𗘍𗘎𗘏𗘐𗘑𗘒𗘓𗘔𗘕𗘖𗘗𗘘𗘙𗘚𗘛𗘜𗘝𗘞𗘟𗘠𗘡𗘢𗘣𗘤𗘥𗘦𗘧𗘨𗘩𗘪𗘫𗘬𗘭𗘮𗘯𗘰𗘱𗘲𗘳𗘴𗘵𗘶𗘷𗘸𗘹𗘺𗘻𗘼𗘽𗘾𗘿𗙀𗙁𗙂𗙃𗙄𗙅𗙆𗙇𗙈𗙉𗙊𗙋𗙌𗙍𗙎𗙏𗙐𗙑𗙒𗙓𗙔𗙕𗙖𗙗𗙘𗙙𗙚𗙛𗙜𗙝𗙞𗙟𗙠𗙡𗙢𗙣𗙤𗙥𗙦𗙧𗙨𗙩𗙪𗙫𗙬𗙭𗙮𗙯𗙰𗙱𗙲𗙳𗙴𗙵𗙶𗙷𗙸𗙹𗙺𗙻𗙼𗙽𗙾𗙿𗚀𗚁𗚂𗚃𗚄𗚅𗚆𗚇𗚈𗚉𗚊𗚋𗚌𗚍𗚎𗚏𗚐𗚑𗚒𗚓𗚔𗚕𗚖𗚗𗚘𗚙𗚚𗚛𗚜𗚝𗚞𗚟𗚠𗚡𗚢𗚣𗚤𗚥𗚦𗚧𗚨𗚩𗚪𗚫𗚬𗚭𗚮𗚯𗚰𗚱𗚲𗚳𗚴𗚵𗚶𗚷𗚸𗚹𗚺𗚻𗚼𗚽𗚾𗚿𗛀𗛁𗛂𗛃𗛄𗛅𗛆𗛇𗛈𗛉𗛊𗛋𗛌𗛍𗛎𗛏𗛐𗛑𗛒𗛓𗛔𗛕𗛖𗛗𗛘𗛙𗛚𗛛𗛜𗛝𗛞𗛟𗛠𗛡𗛢𗛣𗛤𗛥𗛦𗛧𗛨𗛩𗛪𗛫𗛬𗛭𗛮𗛯𗛰𗛱𗛲𗛳𗛴𗛵𗛶𗛷𗛸𗛹𗛺𗛻𗛼𗛽𗛾𗛿𗜀𗜁𗜂𗜃𗜄𗜅𗜆𗜇𗜈𗜉𗜊𗜋𗜌𗜍𗜎𗜏𗜐𗜑𗜒𗜓𗜔𗜕𗜖𗜗𗜘𗜙𗜚𗜛𗜜𗜝𗜞𗜟𗜠𗜡𗜢𗜣𗜤𗜥𗜦𗜧𗜨𗜩𗜪𗜫𗜬𗜭𗜮𗜯𗜰𗜱𗜲𗜳𗜴𗜵𗜶𗜷𗜸𗜹𗜺𗜻𗜼𗜽𗜾𗜿𗝀𗝁𗝂𗝃𗝄𗝅𗝆𗝇𗝈𗝉𗝊𗝋𗝌𗝍𗝎𗝏𗝐𗝑𗝒𗝓𗝔𗝕𗝖𗝗𗝘𗝙𗝚𗝛𗝜𗝝𗝞𗝟𗝠𗝡𗝢𗝣𗝤𗝥𗝦𗝧𗝨𗝩𗝪𗝫𗝬𗝭𗝮𗝯𗝰𗝱𗝲𗝳𗝴𗝵𗝶𗝷𗝸𗝹𗝺𗝻𗝼𗝽𗝾𗝿𗞀𗞁𗞂𗞃𗞄𗞅𗞆𗞇𗞈𗞉𗞊𗞋𗞌𗞍𗞎𗞏𗞐𗞑𗞒𗞓𗞔𗞕𗞖𗞗𗞘𗞙𗞚𗞛𗞜𗞝𗞞𗞟𗞠𗞡𗞢𗞣𗞤𗞥𗞦𗞧𗞨𗞩𗞪𗞫𗞬𗞭𗞮𗞯𗞰𗞱𗞲𗞳𗞴𗞵𗞶𗞷𗞸𗞹𗞺𗞻𗞼𗞽𗞾𗞿𗟀𗟁𗟂𗟃𗟄𗟅𗟆𗟇𗟈𗟉𗟊𗟋𗟌𗟍𗟎𗟏𗟐𗟑𗟒𗟓𗟔𗟕𗟖𗟗𗟘𗟙𗟚𗟛𗟜𗟝𗟞𗟟𗟠𗟡𗟢𗟣𗟤𗟥𗟦𗟧𗟨𗟩𗟪𗟫𗟬𗟭𗟮𗟯𗟰𗟱𗟲𗟳𗟴𗟵𗟶𗟷𗟸𗟹𗟺𗟻𗟼𗟽𗟾𗟿𗠀𗠁𗠂𗠃𗠄𗠅𗠆𗠇𗠈𗠉𗠊𗠋𗠌𗠍𗠎𗠏𗠐𗠑𗠒𗠓𗠔𗠕𗠖𗠗𗠘𗠙𗠚𗠛𗠜𗠝𗠞𗠟𗠠𗠡𗠢𗠣𗠤𗠥𗠦𗠧𗠨𗠩𗠪𗠫𗠬𗠭𗠮𗠯𗠰𗠱𗠲𗠳𗠴𗠵𗠶𗠷𗠸𗠹𗠺𗠻𗠼𗠽𗠾𗠿𗡀𗡁𗡂𗡃𗡄𗡅𗡆𗡇𗡈𗡉𗡊𗡋𗡌𗡍𗡎𗡏𗡐𗡑𗡒𗡓𗡔𗡕𗡖𗡗𗡘𗡙𗡚𗡛𗡜𗡝𗡞𗡟𗡠𗡡𗡢𗡣𗡤𗡥𗡦𗡧𗡨𗡩𗡪𗡫𗡬𗡭𗡮𗡯𗡰𗡱𗡲𗡳𗡴𗡵𗡶𗡷𗡸𗡹𗡺𗡻𗡼𗡽𗡾𗡿𗢀𗢁𗢂𗢃𗢄𗢅𗢆𗢇𗢈𗢉𗢊𗢋𗢌𗢍𗢎𗢏𗢐𗢑𗢒𗢓𗢔𗢕𗢖𗢗𗢘𗢙𗢚𗢛𗢜𗢝𗢞𗢟𗢠𗢡𗢢𗢣𗢤𗢥𗢦𗢧𗢨𗢩𗢪𗢫𗢬𗢭𗢮𗢯𗢰𗢱𗢲𗢳𗢴𗢵𗢶𗢷𗢸𗢹𗢺𗢻𗢼𗢽𗢾𗢿𗣀𗣁𗣂𗣃𗣄𗣅𗣆𗣇𗣈𗣉𗣊𗣋𗣌𗣍𗣎𗣏𗣐𗣑𗣒𗣓𗣔𗣕𗣖𗣗𗣘𗣙𗣚𗣛𗣜𗣝𗣞𗣟𗣠𗣡𗣢𗣣𗣤𗣥𗣦𗣧𗣨𗣩𗣪𗣫𗣬𗣭𗣮𗣯𗣰𗣱𗣲𗣳𗣴𗣵𗣶𗣷𗣸𗣹𗣺𗣻𗣼𗣽𗣾𗣿𗤀𗤁𗤂𗤃𗤄𗤅𗤆𗤇𗤈𗤉𗤊𗤋𗤌𗤍𗤎𗤏𗤐𗤑𗤒𗤓𗤔𗤕𗤖𗤗𗤘𗤙𗤚𗤛𗤜𗤝𗤞𗤟𗤠𗤡𗤢𗤣𗤤𗤥𗤦𗤧𗤨𗤩𗤪𗤫𗤬𗤭𗤮𗤯𗤰𗤱𗤲𗤳𗤴𗤵𗤶𗤷𗤸𗤹𗤺𗤻𗤼𗤽𗤾𗤿𗥀𗥁𗥂𗥃𗥄𗥅𗥆𗥇𗥈𗥉𗥊𗥋𗥌𗥍𗥎𗥏𗥐𗥑𗥒𗥓𗥔𗥕𗥖𗥗𗥘𗥙𗥚𗥛𗥜𗥝𗥞𗥟𗥠𗥡𗥢𗥣𗥤𗥥𗥦𗥧𗥨𗥩𗥪𗥫𗥬𗥭𗥮𗥯𗥰𗥱𗥲𗥳𗥴𗥵𗥶𗥷𗥸𗥹𗥺𗥻𗥼𗥽𗥾𗥿𗦀𗦁𗦂𗦃𗦄𗦅𗦆𗦇𗦈𗦉𗦊𗦋𗦌𗦍𗦎𗦏𗦐𗦑𗦒𗦓𗦔𗦕𗦖𗦗𗦘𗦙𗦚𗦛𗦜𗦝𗦞𗦟𗦠𗦡𗦢𗦣𗦤𗦥𗦦𗦧𗦨𗦩𗦪𗦫𗦬𗦭𗦮𗦯𗦰𗦱𗦲𗦳𗦴𗦵𗦶𗦷𗦸𗦹𗦺𗦻𗦼𗦽𗦾𗦿𗧀𗧁𗧂𗧃𗧄𗧅𗧆𗧇𗧈𗧉𗧊𗧋𗧌𗧍𗧎𗧏𗧐𗧑𗧒𗧓𗧔𗧕𗧖𗧗𗧘𗧙𗧚𗧛𗧜𗧝𗧞𗧟𗧠𗧡𗧢𗧣𗧤𗧥𗧦𗧧𗧨𗧩𗧪𗧫𗧬𗧭𗧮𗧯𗧰𗧱𗧲𗧳𗧴𗧵𗧶𗧷𗧸𗧹𗧺𗧻𗧼𗧽𗧾𗧿𗨀𗨁𗨂𗨃𗨄𗨅𗨆𗨇𗨈𗨉𗨊𗨋𗨌𗨍𗨎𗨏𗨐𗨑𗨒𗨓𗨔𗨕𗨖𗨗𗨘𗨙𗨚𗨛𗨜𗨝𗨞𗨟𗨠𗨡𗨢𗨣𗨤𗨥𗨦𗨧𗨨𗨩𗨪𗨫𗨬𗨭𗨮𗨯𗨰𗨱𗨲𗨳𗨴𗨵𗨶𗨷𗨸𗨹𗨺𗨻𗨼𗨽𗨾𗨿𗩀𗩁𗩂𗩃𗩄𗩅𗩆𗩇𗩈𗩉𗩊𗩋𗩌𗩍𗩎𗩏𗩐𗩑𗩒𗩓𗩔𗩕𗩖𗩗𗩘𗩙𗩚𗩛𗩜𗩝𗩞𗩟𗩠𗩡𗩢𗩣𗩤𗩥𗩦𗩧𗩨𗩩𗩪𗩫𗩬𗩭𗩮𗩯𗩰𗩱𗩲𗩳𗩴𗩵𗩶𗩷𗩸𗩹𗩺𗩻𗩼𗩽𗩾𗩿𗪀𗪁𗪂𗪃𗪄𗪅𗪆𗪇𗪈𗪉𗪊𗪋𗪌𗪍𗪎𗪏𗪐𗪑𗪒𗪓𗪔𗪕𗪖𗪗𗪘𗪙𗪚𗪛𗪜𗪝𗪞𗪟𗪠𗪡𗪢𗪣𗪤𗪥𗪦𗪧𗪨𗪩𗪪𗪫𗪬𗪭𗪮𗪯𗪰𗪱𗪲𗪳𗪴𗪵𗪶𗪷𗪸𗪹𗪺𗪻𗪼𗪽𗪾𗪿𗫀𗫁𗫂𗫃𗫄𗫅𗫆𗫇𗫈𗫉𗫊𗫋𗫌𗫍𗫎𗫏𗫐𗫑𗫒𗫓𗫔𗫕𗫖𗫗𗫘𗫙𗫚𗫛𗫜𗫝𗫞𗫟𗫠𗫡𗫢𗫣𗫤𗫥𗫦𗫧𗫨𗫩𗫪𗫫𗫬𗫭𗫮𗫯𗫰𗫱𗫲𗫳𗫴𗫵𗫶𗫷𗫸𗫹𗫺𗫻𗫼𗫽𗫾𗫿𗬀𗬁𗬂𗬃𗬄𗬅𗬆𗬇𗬈𗬉𗬊𗬋𗬌𗬍𗬎𗬏𗬐𗬑𗬒𗬓𗬔𗬕𗬖𗬗𗬘𗬙𗬚𗬛𗬜𗬝𗬞𗬟𗬠𗬡𗬢𗬣𗬤𗬥𗬦𗬧𗬨𗬩𗬪𗬫𗬬𗬭𗬮𗬯𗬰𗬱𗬲𗬳𗬴𗬵𗬶𗬷𗬸𗬹𗬺𗬻𗬼𗬽𗬾𗬿𗭀𗭁𗭂𗭃𗭄𗭅𗭆𗭇𗭈𗭉𗭊𗭋𗭌𗭍𗭎𗭏𗭐𗭑𗭒𗭓𗭔𗭕𗭖𗭗𗭘𗭙𗭚𗭛𗭜𗭝𗭞𗭟𗭠𗭡𗭢𗭣𗭤𗭥𗭦𗭧𗭨𗭩𗭪𗭫𗭬𗭭𗭮𗭯𗭰𗭱𗭲𗭳𗭴𗭵𗭶𗭷𗭸𗭹𗭺𗭻𗭼𗭽𗭾𗭿𗮀𗮁𗮂𗮃𗮄𗮅𗮆𗮇𗮈𗮉𗮊𗮋𗮌𗮍𗮎𗮏𗮐𗮑𗮒𗮓𗮔𗮕𗮖𗮗𗮘𗮙𗮚𗮛𗮜𗮝𗮞𗮟𗮠𗮡𗮢𗮣𗮤𗮥𗮦𗮧𗮨𗮩𗮪𗮫𗮬𗮭𗮮𗮯𗮰𗮱𗮲𗮳𗮴𗮵𗮶𗮷𗮸𗮹𗮺𗮻𗮼𗮽𗮾𗮿𗯀𗯁𗯂𗯃𗯄𗯅𗯆𗯇𗯈𗯉𗯊𗯋𗯌𗯍𗯎𗯏𗯐𗯑𗯒𗯓𗯔𗯕𗯖𗯗𗯘𗯙𗯚𗯛𗯜𗯝𗯞𗯟𗯠𗯡𗯢𗯣𗯤𗯥𗯦𗯧𗯨𗯩𗯪𗯫𗯬𗯭𗯮𗯯𗯰𗯱𗯲𗯳𗯴𗯵𗯶𗯷𗯸𗯹𗯺𗯻𗯼𗯽𗯾𗯿𗰀𗰁𗰂𗰃𗰄𗰅𗰆𗰇𗰈𗰉𗰊𗰋𗰌𗰍𗰎𗰏𗰐𗰑𗰒𗰓𗰔𗰕𗰖𗰗𗰘𗰙𗰚𗰛𗰜𗰝𗰞𗰟𗰠𗰡𗰢𗰣𗰤𗰥𗰦𗰧𗰨𗰩𗰪𗰫𗰬𗰭𗰮𗰯𗰰𗰱𗰲𗰳𗰴𗰵𗰶𗰷𗰸𗰹𗰺𗰻𗰼𗰽𗰾𗰿𗱀𗱁𗱂𗱃𗱄𗱅𗱆𗱇𗱈𗱉𗱊𗱋𗱌𗱍𗱎𗱏𗱐𗱑𗱒𗱓𗱔𗱕𗱖𗱗𗱘𗱙𗱚𗱛𗱜𗱝𗱞𗱟𗱠𗱡𗱢𗱣𗱤𗱥𗱦𗱧𗱨𗱩𗱪𗱫𗱬𗱭𗱮𗱯𗱰𗱱𗱲𗱳𗱴𗱵𗱶𗱷𗱸𗱹𗱺𗱻𗱼𗱽𗱾𗱿𗲀𗲁𗲂𗲃𗲄𗲅𗲆𗲇𗲈𗲉𗲊𗲋𗲌𗲍𗲎𗲏𗲐𗲑𗲒𗲓𗲔𗲕𗲖𗲗𗲘𗲙𗲚𗲛𗲜𗲝𗲞𗲟𗲠𗲡𗲢𗲣𗲤𗲥𗲦𗲧𗲨𗲩𗲪𗲫𗲬𗲭𗲮𗲯𗲰𗲱𗲲𗲳𗲴𗲵𗲶𗲷𗲸𗲹𗲺𗲻𗲼𗲽𗲾𗲿𗳀𗳁𗳂𗳃𗳄𗳅𗳆𗳇𗳈𗳉𗳊𗳋𗳌𗳍𗳎𗳏𗳐𗳑𗳒𗳓𗳔𗳕𗳖𗳗𗳘𗳙𗳚𗳛𗳜𗳝𗳞𗳟𗳠𗳡𗳢𗳣𗳤𗳥𗳦𗳧𗳨𗳩𗳪𗳫𗳬𗳭𗳮𗳯𗳰𗳱𗳲𗳳𗳴𗳵𗳶𗳷𗳸𗳹𗳺𗳻𗳼𗳽𗳾𗳿𗴀𗴁𗴂𗴃𗴄𗴅𗴆𗴇𗴈𗴉𗴊𗴋𗴌𗴍𗴎𗴏𗴐𗴑𗴒𗴓𗴔𗴕𗴖𗴗𗴘𗴙𗴚𗴛𗴜𗴝𗴞𗴟𗴠𗴡𗴢𗴣𗴤𗴥𗴦𗴧𗴨𗴩𗴪𗴫𗴬𗴭𗴮𗴯𗴰𗴱𗴲𗴳𗴴𗴵𗴶𗴷𗴸𗴹𗴺𗴻𗴼𗴽𗴾𗴿𗵀𗵁𗵂𗵃𗵄𗵅𗵆𗵇𗵈𗵉𗵊𗵋𗵌𗵍𗵎𗵏𗵐𗵑𗵒𗵓𗵔𗵕𗵖𗵗𗵘𗵙𗵚𗵛𗵜𗵝𗵞𗵟𗵠𗵡𗵢𗵣𗵤𗵥𗵦𗵧𗵨𗵩𗵪𗵫𗵬𗵭𗵮𗵯𗵰𗵱𗵲𗵳𗵴𗵵𗵶𗵷𗵸𗵹𗵺𗵻𗵼𗵽𗵾𗵿𗶀𗶁𗶂𗶃𗶄𗶅𗶆𗶇𗶈𗶉𗶊𗶋𗶌𗶍𗶎𗶏𗶐𗶑𗶒𗶓𗶔𗶕𗶖𗶗𗶘𗶙𗶚𗶛𗶜𗶝𗶞𗶟𗶠𗶡𗶢𗶣𗶤𗶥𗶦𗶧𗶨𗶩𗶪𗶫𗶬𗶭𗶮𗶯𗶰𗶱𗶲𗶳𗶴𗶵𗶶𗶷𗶸𗶹𗶺𗶻𗶼𗶽𗶾𗶿𗷀𗷁𗷂𗷃𗷄𗷅𗷆𗷇𗷈𗷉𗷊𗷋𗷌𗷍𗷎𗷏𗷐𗷑𗷒𗷓𗷔𗷕𗷖𗷗𗷘𗷙𗷚𗷛𗷜𗷝𗷞𗷟𗷠𗷡𗷢𗷣𗷤𗷥𗷦𗷧𗷨𗷩𗷪𗷫𗷬𗷭𗷮𗷯𗷰𗷱𗷲𗷳𗷴𗷵𗷶𗷷𗷸𗷹𗷺𗷻𗷼𗷽𗷾𗷿𗸀𗸁𗸂𗸃𗸄𗸅𗸆𗸇𗸈𗸉𗸊𗸋𗸌𗸍𗸎𗸏𗸐𗸑𗸒𗸓𗸔𗸕𗸖𗸗𗸘𗸙𗸚𗸛𗸜𗸝𗸞𗸟𗸠𗸡𗸢𗸣𗸤𗸥𗸦𗸧𗸨𗸩𗸪𗸫𗸬𗸭𗸮𗸯𗸰𗸱𗸲𗸳𗸴𗸵𗸶𗸷𗸸𗸹𗸺𗸻𗸼𗸽𗸾𗸿𗹀𗹁𗹂𗹃𗹄𗹅𗹆𗹇𗹈𗹉𗹊𗹋𗹌𗹍𗹎𗹏𗹐𗹑𗹒𗹓𗹔𗹕𗹖𗹗𗹘𗹙𗹚𗹛𗹜𗹝𗹞𗹟𗹠𗹡𗹢𗹣𗹤𗹥𗹦𗹧𗹨𗹩𗹪𗹫𗹬𗹭𗹮𗹯𗹰𗹱𗹲𗹳𗹴𗹵𗹶𗹷𗹸𗹹𗹺𗹻𗹼𗹽𗹾𗹿𗺀𗺁𗺂𗺃𗺄𗺅𗺆𗺇𗺈𗺉𗺊𗺋𗺌𗺍𗺎𗺏𗺐𗺑𗺒𗺓𗺔𗺕𗺖𗺗𗺘𗺙𗺚𗺛𗺜𗺝𗺞𗺟𗺠𗺡𗺢𗺣𗺤𗺥𗺦𗺧𗺨𗺩𗺪𗺫𗺬𗺭𗺮𗺯𗺰𗺱𗺲𗺳𗺴𗺵𗺶𗺷𗺸𗺹𗺺𗺻𗺼𗺽𗺾𗺿𗻀𗻁𗻂𗻃𗻄𗻅𗻆𗻇𗻈𗻉𗻊𗻋𗻌𗻍𗻎𗻏𗻐𗻑𗻒𗻓𗻔𗻕𗻖𗻗𗻘𗻙𗻚𗻛𗻜𗻝𗻞𗻟𗻠𗻡𗻢𗻣𗻤𗻥𗻦𗻧𗻨𗻩𗻪𗻫𗻬𗻭𗻮𗻯𗻰𗻱𗻲𗻳𗻴𗻵𗻶𗻷𗻸𗻹𗻺𗻻𗻼𗻽𗻾𗻿𗼀𗼁𗼂𗼃𗼄𗼅𗼆𗼇𗼈𗼉𗼊𗼋𗼌𗼍𗼎𗼏𗼐𗼑𗼒𗼓𗼔𗼕𗼖𗼗𗼘𗼙𗼚𗼛𗼜𗼝𗼞𗼟𗼠𗼡𗼢𗼣𗼤𗼥𗼦𗼧𗼨𗼩𗼪𗼫𗼬𗼭𗼮𗼯𗼰𗼱𗼲𗼳𗼴𗼵𗼶𗼷𗼸𗼹𗼺𗼻𗼼𗼽𗼾𗼿𗽀𗽁𗽂𗽃𗽄𗽅𗽆𗽇𗽈𗽉𗽊𗽋𗽌𗽍𗽎𗽏𗽐𗽑𗽒𗽓𗽔𗽕𗽖𗽗𗽘𗽙𗽚𗽛𗽜𗽝𗽞𗽟𗽠𗽡𗽢𗽣𗽤𗽥𗽦𗽧𗽨𗽩𗽪𗽫𗽬𗽭𗽮𗽯𗽰𗽱𗽲𗽳𗽴𗽵𗽶𗽷𗽸𗽹𗽺𗽻𗽼𗽽𗽾𗽿𗾀𗾁𗾂𗾃𗾄𗾅𗾆𗾇𗾈𗾉𗾊𗾋𗾌𗾍𗾎𗾏𗾐𗾑𗾒𗾓𗾔𗾕𗾖𗾗𗾘𗾙𗾚𗾛𗾜𗾝𗾞𗾟𗾠𗾡𗾢𗾣𗾤𗾥𗾦𗾧𗾨𗾩𗾪𗾫𗾬𗾭𗾮𗾯𗾰𗾱𗾲𗾳𗾴𗾵𗾶𗾷𗾸𗾹𗾺𗾻𗾼𗾽𗾾𗾿𗿀𗿁𗿂𗿃𗿄𗿅𗿆𗿇𗿈𗿉𗿊𗿋𗿌𗿍𗿎𗿏𗿐𗿑𗿒𗿓𗿔𗿕𗿖𗿗𗿘𗿙𗿚𗿛𗿜𗿝𗿞𗿟𗿠𗿡𗿢𗿣𗿤𗿥𗿦𗿧𗿨𗿩𗿪𗿫𗿬𗿭𗿮𗿯𗿰𗿱𗿲𗿳𗿴𗿵𗿶𗿷𗿸𗿹𗿺𗿻𗿼𗿽𗿾𗿿𘀀𘀁𘀂𘀃𘀄𘀅𘀆𘀇𘀈𘀉𘀊𘀋𘀌𘀍𘀎𘀏𘀐𘀑𘀒𘀓𘀔𘀕𘀖𘀗𘀘𘀙𘀚𘀛𘀜𘀝𘀞𘀟𘀠𘀡𘀢𘀣𘀤𘀥𘀦𘀧𘀨𘀩𘀪𘀫𘀬𘀭𘀮𘀯𘀰𘀱𘀲𘀳𘀴𘀵𘀶𘀷𘀸𘀹𘀺𘀻𘀼𘀽𘀾𘀿𘁀𘁁𘁂𘁃𘁄𘁅𘁆𘁇𘁈𘁉𘁊𘁋𘁌𘁍𘁎𘁏𘁐𘁑𘁒𘁓𘁔𘁕𘁖𘁗𘁘𘁙𘁚𘁛𘁜𘁝𘁞𘁟𘁠𘁡𘁢𘁣𘁤𘁥𘁦𘁧𘁨𘁩𘁪𘁫𘁬𘁭𘁮𘁯𘁰𘁱𘁲𘁳𘁴𘁵𘁶𘁷𘁸𘁹𘁺𘁻𘁼𘁽𘁾𘁿𘂀𘂁𘂂𘂃𘂄𘂅𘂆𘂇𘂈𘂉𘂊𘂋𘂌𘂍𘂎𘂏𘂐𘂑𘂒𘂓𘂔𘂕𘂖𘂗𘂘𘂙𘂚𘂛𘂜𘂝𘂞𘂟𘂠𘂡𘂢𘂣𘂤𘂥𘂦𘂧𘂨𘂩𘂪𘂫𘂬𘂭𘂮𘂯𘂰𘂱𘂲𘂳𘂴𘂵𘂶𘂷𘂸𘂹𘂺𘂻𘂼𘂽𘂾𘂿𘃀𘃁𘃂𘃃𘃄𘃅𘃆𘃇𘃈𘃉𘃊𘃋𘃌𘃍𘃎𘃏𘃐𘃑𘃒𘃓𘃔𘃕𘃖𘃗𘃘𘃙𘃚𘃛𘃜𘃝𘃞𘃟𘃠𘃡𘃢𘃣𘃤𘃥𘃦𘃧𘃨𘃩𘃪𘃫𘃬𘃭𘃮𘃯𘃰𘃱𘃲𘃳𘃴𘃵𘃶𘃷𘃸𘃹𘃺𘃻𘃼𘃽𘃾𘃿𘄀𘄁𘄂𘄃𘄄𘄅𘄆𘄇𘄈𘄉𘄊𘄋𘄌𘄍𘄎𘄏𘄐𘄑𘄒𘄓𘄔𘄕𘄖𘄗𘄘𘄙𘄚𘄛𘄜𘄝𘄞𘄟𘄠𘄡𘄢𘄣𘄤𘄥𘄦𘄧𘄨𘄩𘄪𘄫𘄬𘄭𘄮𘄯𘄰𘄱𘄲𘄳𘄴𘄵𘄶𘄷𘄸𘄹𘄺𘄻𘄼𘄽𘄾𘄿𘅀𘅁𘅂𘅃𘅄𘅅𘅆𘅇𘅈𘅉𘅊𘅋𘅌𘅍𘅎𘅏𘅐𘅑𘅒𘅓𘅔𘅕𘅖𘅗𘅘𘅙𘅚𘅛𘅜𘅝𘅞𘅟𘅠𘅡𘅢𘅣𘅤𘅥𘅦𘅧𘅨𘅩𘅪𘅫𘅬𘅭𘅮𘅯𘅰𘅱𘅲𘅳𘅴𘅵𘅶𘅷𘅸𘅹𘅺𘅻𘅼𘅽𘅾𘅿𘆀𘆁𘆂𘆃𘆄𘆅𘆆𘆇𘆈𘆉𘆊𘆋𘆌𘆍𘆎𘆏𘆐𘆑𘆒𘆓𘆔𘆕𘆖𘆗𘆘𘆙𘆚𘆛𘆜𘆝𘆞𘆟𘆠𘆡𘆢𘆣𘆤𘆥𘆦𘆧𘆨𘆩𘆪𘆫𘆬𘆭𘆮𘆯𘆰𘆱𘆲𘆳𘆴𘆵𘆶𘆷𘆸𘆹𘆺𘆻𘆼𘆽𘆾𘆿𘇀𘇁𘇂𘇃𘇄𘇅𘇆𘇇𘇈𘇉𘇊𘇋𘇌𘇍𘇎𘇏𘇐𘇑𘇒𘇓𘇔𘇕𘇖𘇗𘇘𘇙𘇚𘇛𘇜𘇝𘇞𘇟𘇠𘇡𘇢𘇣𘇤𘇥𘇦𘇧𘇨𘇩𘇪𘇫𘇬𘇭𘇮𘇯𘇰𘇱𘇲𘇳𘇴𘇵𘇶𘇷𘇸𘇹𘇺𘇻𘇼𘇽𘇾𘇿𘈀𘈁𘈂𘈃𘈄𘈅𘈆𘈇𘈈𘈉𘈊𘈋𘈌𘈍𘈎𘈏𘈐𘈑𘈒𘈓𘈔𘈕𘈖𘈗𘈘𘈙𘈚𘈛𘈜𘈝𘈞𘈟𘈠𘈡𘈢𘈣𘈤𘈥𘈦𘈧𘈨𘈩𘈪𘈫𘈬𘈭𘈮𘈯𘈰𘈱𘈲𘈳𘈴𘈵𘈶𘈷𘈸𘈹𘈺𘈻𘈼𘈽𘈾𘈿𘉀𘉁𘉂𘉃𘉄𘉅𘉆𘉇𘉈𘉉𘉊𘉋𘉌𘉍𘉎𘉏𘉐𘉑𘉒𘉓𘉔𘉕𘉖𘉗𘉘𘉙𘉚𘉛𘉜𘉝𘉞𘉟𘉠𘉡𘉢𘉣𘉤𘉥𘉦𘉧𘉨𘉩𘉪𘉫𘉬𘉭𘉮𘉯𘉰𘉱𘉲𘉳𘉴𘉵𘉶𘉷𘉸𘉹𘉺𘉻𘉼𘉽𘉾𘉿𘊀𘊁𘊂𘊃𘊄𘊅𘊆𘊇𘊈𘊉𘊊𘊋𘊌𘊍𘊎𘊏𘊐𘊑𘊒𘊓𘊔𘊕𘊖𘊗𘊘𘊙𘊚𘊛𘊜𘊝𘊞𘊟𘊠𘊡𘊢𘊣𘊤𘊥𘊦𘊧𘊨𘊩𘊪𘊫𘊬𘊭𘊮𘊯𘊰𘊱𘊲𘊳𘊴𘊵𘊶𘊷𘊸𘊹𘊺𘊻𘊼𘊽𘊾𘊿𘋀𘋁𘋂𘋃𘋄𘋅𘋆𘋇𘋈𘋉𘋊𘋋𘋌𘋍𘋎𘋏𘋐𘋑𘋒𘋓𘋔𘋕𘋖𘋗𘋘𘋙𘋚𘋛𘋜𘋝𘋞𘋟𘋠𘋡𘋢𘋣𘋤𘋥𘋦𘋧𘋨𘋩𘋪𘋫𘋬𘋭𘋮𘋯𘋰𘋱𘋲𘋳𘋴𘋵𘋶𘋷𘋸𘋹𘋺𘋻𘋼𘋽𘋾𘋿𘌀𘌁𘌂𘌃𘌄𘌅𘌆𘌇𘌈𘌉𘌊𘌋𘌌𘌍𘌎𘌏𘌐𘌑𘌒𘌓𘌔𘌕𘌖𘌗𘌘𘌙𘌚𘌛𘌜𘌝𘌞𘌟𘌠𘌡𘌢𘌣𘌤𘌥𘌦𘌧𘌨𘌩𘌪𘌫𘌬𘌭𘌮𘌯𘌰𘌱𘌲𘌳𘌴𘌵𘌶𘌷𘌸𘌹𘌺𘌻𘌼𘌽𘌾𘌿𘍀𘍁𘍂𘍃𘍄𘍅𘍆𘍇𘍈𘍉𘍊𘍋𘍌𘍍𘍎𘍏𘍐𘍑𘍒𘍓𘍔𘍕𘍖𘍗𘍘𘍙𘍚𘍛𘍜𘍝𘍞𘍟𘍠𘍡𘍢𘍣𘍤𘍥𘍦𘍧𘍨𘍩𘍪𘍫𘍬𘍭𘍮𘍯𘍰𘍱𘍲𘍳𘍴𘍵𘍶𘍷𘍸𘍹𘍺𘍻𘍼𘍽𘍾𘍿𘎀𘎁𘎂𘎃𘎄𘎅𘎆𘎇𘎈𘎉𘎊𘎋𘎌𘎍𘎎𘎏𘎐𘎑𘎒𘎓𘎔𘎕𘎖𘎗𘎘𘎙𘎚𘎛𘎜𘎝𘎞𘎟𘎠𘎡𘎢𘎣𘎤𘎥𘎦𘎧𘎨𘎩𘎪𘎫𘎬𘎭𘎮𘎯𘎰𘎱𘎲𘎳𘎴𘎵𘎶𘎷𘎸𘎹𘎺𘎻𘎼𘎽𘎾𘎿𘏀𘏁𘏂𘏃𘏄𘏅𘏆𘏇𘏈𘏉𘏊𘏋𘏌𘏍𘏎𘏏𘏐𘏑𘏒𘏓𘏔𘏕𘏖𘏗𘏘𘏙𘏚𘏛𘏜𘏝𘏞𘏟𘏠𘏡𘏢𘏣𘏤𘏥𘏦𘏧𘏨𘏩𘏪𘏫𘏬𘏭𘏮𘏯𘏰𘏱𘏲𘏳𘏴𘏵𘏶𘏷𘏸𘏹𘏺𘏻𘏼𘏽𘏾𘏿𘐀𘐁𘐂𘐃𘐄𘐅𘐆𘐇𘐈𘐉𘐊𘐋𘐌𘐍𘐎𘐏𘐐𘐑𘐒𘐓𘐔𘐕𘐖𘐗𘐘𘐙𘐚𘐛𘐜𘐝𘐞𘐟𘐠𘐡𘐢𘐣𘐤𘐥𘐦𘐧𘐨𘐩𘐪𘐫𘐬𘐭𘐮𘐯𘐰𘐱𘐲𘐳𘐴𘐵𘐶𘐷𘐸𘐹𘐺𘐻𘐼𘐽𘐾𘐿𘑀𘑁𘑂𘑃𘑄𘑅𘑆𘑇𘑈𘑉𘑊𘑋𘑌𘑍𘑎𘑏𘑐𘑑𘑒𘑓𘑔𘑕𘑖𘑗𘑘𘑙𘑚𘑛𘑜𘑝𘑞𘑟𘑠𘑡𘑢𘑣𘑤𘑥𘑦𘑧𘑨𘑩𘑪𘑫𘑬𘑭𘑮𘑯𘑰𘑱𘑲𘑳𘑴𘑵𘑶𘑷𘑸𘑹𘑺𘑻𘑼𘑽𘑾𘑿𘒀𘒁𘒂𘒃𘒄𘒅𘒆𘒇𘒈𘒉𘒊𘒋𘒌𘒍𘒎𘒏𘒐𘒑𘒒𘒓𘒔𘒕𘒖𘒗𘒘𘒙𘒚𘒛𘒜𘒝𘒞𘒟𘒠𘒡𘒢𘒣𘒤𘒥𘒦𘒧𘒨𘒩𘒪𘒫𘒬𘒭𘒮𘒯𘒰𘒱𘒲𘒳𘒴𘒵𘒶𘒷𘒸𘒹𘒺𘒻𘒼𘒽𘒾𘒿𘓀𘓁𘓂𘓃𘓄𘓅𘓆𘓇𘓈𘓉𘓊𘓋𘓌𘓍𘓎𘓏𘓐𘓑𘓒𘓓𘓔𘓕𘓖𘓗𘓘𘓙𘓚𘓛𘓜𘓝𘓞𘓟𘓠𘓡𘓢𘓣𘓤𘓥𘓦𘓧𘓨𘓩𘓪𘓫𘓬𘓭𘓮𘓯𘓰𘓱𘓲𘓳𘓴𘓵𘓶𘓷𘓸𘓹𘓺𘓻𘓼𘓽𘓾𘓿𘔀𘔁𘔂𘔃𘔄𘔅𘔆𘔇𘔈𘔉𘔊𘔋𘔌𘔍𘔎𘔏𘔐𘔑𘔒𘔓𘔔𘔕𘔖𘔗𘔘𘔙𘔚𘔛𘔜𘔝𘔞𘔟𘔠𘔡𘔢𘔣𘔤𘔥𘔦𘔧𘔨𘔩𘔪𘔫𘔬𘔭𘔮𘔯𘔰𘔱𘔲𘔳𘔴𘔵𘔶𘔷𘔸𘔹𘔺𘔻𘔼𘔽𘔾𘔿𘕀𘕁𘕂𘕃𘕄𘕅𘕆𘕇𘕈𘕉𘕊𘕋𘕌𘕍𘕎𘕏𘕐𘕑𘕒𘕓𘕔𘕕𘕖𘕗𘕘𘕙𘕚𘕛𘕜𘕝𘕞𘕟𘕠𘕡𘕢𘕣𘕤𘕥𘕦𘕧𘕨𘕩𘕪𘕫𘕬𘕭𘕮𘕯𘕰𘕱𘕲𘕳𘕴𘕵𘕶𘕷𘕸𘕹𘕺𘕻𘕼𘕽𘕾𘕿𘖀𘖁𘖂𘖃𘖄𘖅𘖆𘖇𘖈𘖉𘖊𘖋𘖌𘖍𘖎𘖏𘖐𘖑𘖒𘖓𘖔𘖕𘖖𘖗𘖘𘖙𘖚𘖛𘖜𘖝𘖞𘖟𘖠𘖡𘖢𘖣𘖤𘖥𘖦𘖧𘖨𘖩𘖪𘖫𘖬𘖭𘖮𘖯𘖰𘖱𘖲𘖳𘖴𘖵𘖶𘖷𘖸𘖹𘖺𘖻𘖼𘖽𘖾𘖿𘗀𘗁𘗂𘗃𘗄𘗅𘗆𘗇𘗈𘗉𘗊𘗋𘗌𘗍𘗎𘗏𘗐𘗑𘗒𘗓𘗔𘗕𘗖𘗗𘗘𘗙𘗚𘗛𘗜𘗝𘗞𘗟𘗠𘗡𘗢𘗣𘗤𘗥𘗦𘗧𘗨𘗩𘗪𘗫𘗬𘗭𘗮𘗯𘗰𘗱𘗲𘗳𘗴𘗵𘗶𘗷𘗸𘗹𘗺𘗻𘗼𘗽𘗾𘗿𘘀𘘁𘘂𘘃𘘄𘘅𘘆𘘇𘘈𘘉𘘊𘘋𘘌𘘍𘘎𘘏𘘐𘘑𘘒𘘓𘘔𘘕𘘖𘘗𘘘𘘙𘘚𘘛𘘜𘘝𘘞𘘟𘘠𘘡𘘢𘘣𘘤𘘥𘘦𘘧𘘨𘘩𘘪𘘫𘘬𘘭𘘮𘘯𘘰𘘱𘘲𘘳𘘴𘘵𘘶𘘷𘘸𘘹𘘺𘘻𘘼𘘽𘘾𘘿𘙀𘙁𘙂𘙃𘙄𘙅𘙆𘙇𘙈𘙉𘙊𘙋𘙌𘙍𘙎𘙏𘙐𘙑𘙒𘙓𘙔𘙕𘙖𘙗𘙘𘙙𘙚𘙛𘙜𘙝𘙞𘙟𘙠𘙡𘙢𘙣𘙤𘙥𘙦𘙧𘙨𘙩𘙪𘙫𘙬𘙭𘙮𘙯𘙰𘙱𘙲𘙳𘙴𘙵𘙶𘙷𘙸𘙹𘙺𘙻𘙼𘙽𘙾𘙿𘚀𘚁𘚂𘚃𘚄𘚅𘚆𘚇𘚈𘚉𘚊𘚋𘚌𘚍𘚎𘚏𘚐𘚑𘚒𘚓𘚔𘚕𘚖𘚗𘚘𘚙𘚚𘚛𘚜𘚝𘚞𘚟𘚠𘚡𘚢𘚣𘚤𘚥𘚦𘚧𘚨𘚩𘚪𘚫𘚬𘚭𘚮𘚯𘚰𘚱𘚲𘚳𘚴𘚵𘚶𘚷𘚸𘚹𘚺𘚻𘚼𘚽𘚾𘚿𘛀𘛁𘛂𘛃𘛄𘛅𘛆𘛇𘛈𘛉𘛊𘛋𘛌𘛍𘛎𘛏𘛐𘛑𘛒𘛓𘛔𘛕𘛖𘛗𘛘𘛙𘛚𘛛𘛜𘛝𘛞𘛟𘛠𘛡𘛢𘛣𘛤𘛥𘛦𘛧𘛨𘛩𘛪𘛫𘛬𘛭𘛮𘛯𘛰𘛱𘛲𘛳𘛴𘛵𘛶𘛷𘛸𘛹𘛺𘛻𘛼𘛽𘛾𘛿𘜀𘜁𘜂𘜃𘜄𘜅𘜆𘜇𘜈𘜉𘜊𘜋𘜌𘜍𘜎𘜏𘜐𘜑𘜒𘜓𘜔𘜕𘜖𘜗𘜘𘜙𘜚𘜛𘜜𘜝𘜞𘜟𘜠𘜡𘜢𘜣𘜤𘜥𘜦𘜧𘜨𘜩𘜪𘜫𘜬𘜭𘜮𘜯𘜰𘜱𘜲𘜳𘜴𘜵𘜶𘜷𘜸𘜹𘜺𘜻𘜼𘜽𘜾𘜿𘝀𘝁𘝂𘝃𘝄𘝅𘝆𘝇𘝈𘝉𘝊𘝋𘝌𘝍𘝎𘝏𘝐𘝑𘝒𘝓𘝔𘝕𘝖𘝗𘝘𘝙𘝚𘝛𘝜𘝝𘝞𘝟𘝠𘝡𘝢𘝣𘝤𘝥𘝦𘝧𘝨𘝩𘝪𘝫𘝬𘝭𘝮𘝯𘝰𘝱𘝲𘝳𘝴𘝵𘝶𘝷𘝸𘝹𘝺𘝻𘝼𘝽𘝾𘝿𘞀𘞁𘞂𘞃𘞄𘞅𘞆𘞇𘞈𘞉𘞊𘞋𘞌𘞍𘞎𘞏𘞐𘞑𘞒𘞓𘞔𘞕𘞖𘞗𘞘𘞙𘞚𘞛𘞜𘞝𘞞𘞟𘞠𘞡𘞢𘞣𘞤𘞥𘞦𘞧𘞨𘞩𘞪𘞫𘞬𘞭𘞮𘞯𘞰𘞱𘞲𘞳𘞴𘞵𘞶𘞷𘞸𘞹𘞺𘞻𘞼𘞽𘞾𘞿𘟀𘟁𘟂𘟃𘟄𘟅𘟆𘟇𘟈𘟉𘟊𘟋𘟌𘟍𘟎𘟏𘟐𘟑𘟒𘟓𘟔𘟕𘟖𘟗𘟘𘟙𘟚𘟛𘟜𘟝𘟞𘟟𘟠𘟡𘟢𘟣𘟤𘟥𘟦𘟧𘟨𘟩𘟪𘟫𘟬𘠀𘠁𘠂𘠃𘠄𘠅𘠆𘠇𘠈𘠉𘠊𘠋𘠌𘠍𘠎𘠏𘠐𘠑𘠒𘠓𘠔𘠕𘠖𘠗𘠘𘠙𘠚𘠛𘠜𘠝𘠞𘠟𘠠𘠡𘠢𘠣𘠤𘠥𘠦𘠧𘠨𘠩𘠪𘠫𘠬𘠭𘠮𘠯𘠰𘠱𘠲𘠳𘠴𘠵𘠶𘠷𘠸𘠹𘠺𘠻𘠼𘠽𘠾𘠿𘡀𘡁𘡂𘡃𘡄𘡅𘡆𘡇𘡈𘡉𘡊𘡋𘡌𘡍𘡎𘡏𘡐𘡑𘡒𘡓𘡔𘡕𘡖𘡗𘡘𘡙𘡚𘡛𘡜𘡝𘡞𘡟𘡠𘡡𘡢𘡣𘡤𘡥𘡦𘡧𘡨𘡩𘡪𘡫𘡬𘡭𘡮𘡯𘡰𘡱𘡲𘡳𘡴𘡵𘡶𘡷𘡸𘡹𘡺𘡻𘡼𘡽𘡾𘡿𘢀𘢁𘢂𘢃𘢄𘢅𘢆𘢇𘢈𘢉𘢊𘢋𘢌𘢍𘢎𘢏𘢐𘢑𘢒𘢓𘢔𘢕𘢖𘢗𘢘𘢙𘢚𘢛𘢜𘢝𘢞𘢟𘢠𘢡𘢢𘢣𘢤𘢥𘢦𘢧𘢨𘢩𘢪𘢫𘢬𘢭𘢮𘢯𘢰𘢱𘢲𘢳𘢴𘢵𘢶𘢷𘢸𘢹𘢺𘢻𘢼𘢽𘢾𘢿𘣀𘣁𘣂𘣃𘣄𘣅𘣆𘣇𘣈𘣉𘣊𘣋𘣌𘣍𘣎𘣏𘣐𘣑𘣒𘣓𘣔𘣕𘣖𘣗𘣘𘣙𘣚𘣛𘣜𘣝𘣞𘣟𘣠𘣡𘣢𘣣𘣤𘣥𘣦𘣧𘣨𘣩𘣪𘣫𘣬𘣭𘣮𘣯𘣰𘣱𘣲𘣳𘣴𘣵𘣶𘣷𘣸𘣹𘣺𘣻𘣼𘣽𘣾𘣿𘤀𘤁𘤂𘤃𘤄𘤅𘤆𘤇𘤈𘤉𘤊𘤋𘤌𘤍𘤎𘤏𘤐𘤑𘤒𘤓𘤔𘤕𘤖𘤗𘤘𘤙𘤚𘤛𘤜𘤝𘤞𘤟𘤠𘤡𘤢𘤣𘤤𘤥𘤦𘤧𘤨𘤩𘤪𘤫𘤬𘤭𘤮𘤯𘤰𘤱𘤲𘤳𘤴𘤵𘤶𘤷𘤸𘤹𘤺𘤻𘤼𘤽𘤾𘤿𘥀𘥁𘥂𘥃𘥄𘥅𘥆𘥇𘥈𘥉𘥊𘥋𘥌𘥍𘥎𘥏𘥐𘥑𘥒𘥓𘥔𘥕𘥖𘥗𘥘𘥙𘥚𘥛𘥜𘥝𘥞𘥟𘥠𘥡𘥢𘥣𘥤𘥥𘥦𘥧𘥨𘥩𘥪𘥫𘥬𘥭𘥮𘥯𘥰𘥱𘥲𘥳𘥴𘥵𘥶𘥷𘥸𘥹𘥺𘥻𘥼𘥽𘥾𘥿𘦀𘦁𘦂𘦃𘦄𘦅𘦆𘦇𘦈𘦉𘦊𘦋𘦌𘦍𘦎𘦏𘦐𘦑𘦒𘦓𘦔𘦕𘦖𘦗𘦘𘦙𘦚𘦛𘦜𘦝𘦞𘦟𘦠𘦡𘦢𘦣𘦤𘦥𘦦𘦧𘦨𘦩𘦪𘦫𘦬𘦭𘦮𘦯𘦰𘦱𘦲𘦳𘦴𘦵𘦶𘦷𘦸𘦹𘦺𘦻𘦼𘦽𘦾𘦿𘧀𘧁𘧂𘧃𘧄𘧅𘧆𘧇𘧈𘧉𘧊𘧋𘧌𘧍𘧎𘧏𘧐𘧑𘧒𘧓𘧔𘧕𘧖𘧗𘧘𘧙𘧚𘧛𘧜𘧝𘧞𘧟𘧠𘧡𘧢𘧣𘧤𘧥𘧦𘧧𘧨𘧩𘧪𘧫𘧬𘧭𘧮𘧯𘧰𘧱𘧲𘧳𘧴𘧵𘧶𘧷𘧸𘧹𘧺𘧻𘧼𘧽𘧾𘧿𘨀𘨁𘨂𘨃𘨄𘨅𘨆𘨇𘨈𘨉𘨊𘨋𘨌𘨍𘨎𘨏𘨐𘨑𘨒𘨓𘨔𘨕𘨖𘨗𘨘𘨙𘨚𘨛𘨜𘨝𘨞𘨟𘨠𘨡𘨢𘨣𘨤𘨥𘨦𘨧𘨨𘨩𘨪𘨫𘨬𘨭𘨮𘨯𘨰𘨱𘨲𘨳𘨴𘨵𘨶𘨷𘨸𘨹𘨺𘨻𘨼𘨽𘨾𘨿𘩀𘩁𘩂𘩃𘩄𘩅𘩆𘩇𘩈𘩉𘩊𘩋𘩌𘩍𘩎𘩏𘩐𘩑𘩒𘩓𘩔𘩕𘩖𘩗𘩘𘩙𘩚𘩛𘩜𘩝𘩞𘩟𘩠𘩡𘩢𘩣𘩤𘩥𘩦𘩧𘩨𘩩𘩪𘩫𘩬𘩭𘩮𘩯𘩰𘩱𘩲𘩳𘩴𘩵𘩶𘩷𘩸𘩹𘩺𘩻𘩼𘩽𘩾𘩿𘪀𘪁𘪂𘪃𘪄𘪅𘪆𘪇𘪈𘪉𘪊𘪋𘪌𘪍𘪎𘪏𘪐𘪑𘪒𘪓𘪔𘪕𘪖𘪗𘪘𘪙𘪚𘪛𘪜𘪝𘪞𘪟𘪠𘪡𘪢𘪣𘪤𘪥𘪦𘪧𘪨𘪩𘪪𘪫𘪬𘪭𘪮𘪯𘪰𘪱𘪲𘪳𘪴𘪵𘪶𘪷𘪸𘪹𘪺𘪻𘪼𘪽𘪾𘪿𘫀𘫁𘫂𘫃𘫄𘫅𘫆𘫇𘫈𘫉𘫊𘫋𘫌𘫍𘫎𘫏𘫐𘫑𘫒𘫓𘫔𘫕𘫖𘫗𘫘𘫙𘫚𘫛𘫜𘫝𘫞𘫟𘫠𘫡𘫢𘫣𘫤𘫥𘫦𘫧𘫨𘫩𘫪𘫫𘫬𘫭𘫮𘫯𘫰𘫱𘫲𞤀𞤁𞤂𞤃𞤄𞤅𞤆𞤇𞤈𞤉𞤊𞤋𞤌𞤍𞤎𞤏𞤐𞤑𞤒𞤓𞤔𞤕𞤖𞤗𞤘𞤙𞤚𞤛𞤜𞤝𞤞𞤟𞤠𞤡𞤢𞤣𞤤𞤥𞤦𞤧𞤨𞤩𞤪𞤫𞤬𞤭𞤮𞤯𞤰𞤱𞤲𞤳𞤴𞤵𞤶𞤷𞤸𞤹𞤺𞤻𞤼𞤽𞤾𞤿𞥀𞥁𞥂𞥃; +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-escaped.js b/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-escaped.js index 7da60bbb1b5f..9d110021def3 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-escaped.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-9.0.0-escaped.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/start-unicode-9.0.0.js b/js/src/tests/test262/language/identifiers/start-unicode-9.0.0.js index 66ae769180f0..2fc54564f6c6 100644 --- a/js/src/tests/test262/language/identifiers/start-unicode-9.0.0.js +++ b/js/src/tests/test262/language/identifiers/start-unicode-9.0.0.js @@ -1,4 +1,4 @@ -// Copyright 2020 Mathias Bynens. All rights reserved. +// Copyright 2022 Mathias Bynens. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/language/identifiers/vertical-tilde-continue-escaped.js b/js/src/tests/test262/language/identifiers/vertical-tilde-continue-escaped.js index bb170b786c99..3740b7ce61ab 100644 --- a/js/src/tests/test262/language/identifiers/vertical-tilde-continue-escaped.js +++ b/js/src/tests/test262/language/identifiers/vertical-tilde-continue-escaped.js @@ -8,8 +8,8 @@ description: Test VERTICAL TILDE (U+2E2F) is not recognized as ID_Continue chara info: | VERTICAL TILDE is in General Category 'Lm' and [:Pattern_Syntax:]. negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/identifiers/vertical-tilde-continue.js b/js/src/tests/test262/language/identifiers/vertical-tilde-continue.js index dd8d79a62acd..3a2ee0aaf0b0 100644 --- a/js/src/tests/test262/language/identifiers/vertical-tilde-continue.js +++ b/js/src/tests/test262/language/identifiers/vertical-tilde-continue.js @@ -8,8 +8,8 @@ description: Test VERTICAL TILDE (U+2E2F) is not recognized as ID_Continue chara info: | VERTICAL TILDE is in General Category 'Lm' and [:Pattern_Syntax:]. negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/identifiers/vertical-tilde-start-escaped.js b/js/src/tests/test262/language/identifiers/vertical-tilde-start-escaped.js index 18db4a5c5b1f..d6f3fb0b5275 100644 --- a/js/src/tests/test262/language/identifiers/vertical-tilde-start-escaped.js +++ b/js/src/tests/test262/language/identifiers/vertical-tilde-start-escaped.js @@ -8,8 +8,8 @@ description: Test VERTICAL TILDE (U+2E2F) is not recognized as ID_Start characte info: | VERTICAL TILDE is in General Category 'Lm' and [:Pattern_Syntax:]. negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/identifiers/vertical-tilde-start.js b/js/src/tests/test262/language/identifiers/vertical-tilde-start.js index 99fa92326757..73388a2c16ca 100644 --- a/js/src/tests/test262/language/identifiers/vertical-tilde-start.js +++ b/js/src/tests/test262/language/identifiers/vertical-tilde-start.js @@ -8,8 +8,8 @@ description: Test VERTICAL TILDE (U+2E2F) is not recognized as ID_Start characte info: | VERTICAL TILDE is in General Category 'Lm' and [:Pattern_Syntax:]. negative: - type: SyntaxError phase: parse + type: SyntaxError ---*/ $DONOTEVALUATE(); diff --git a/js/src/tests/test262/language/module-code/early-dup-lex.js b/js/src/tests/test262/language/module-code/early-dup-lex.js index 0511fb87b496..e3ddf0d7c050 100644 --- a/js/src/tests/test262/language/module-code/early-dup-lex.js +++ b/js/src/tests/test262/language/module-code/early-dup-lex.js @@ -2,7 +2,7 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 10.2.1 +esid: sec-module-semantics-static-semantics-early-errors description: > It is a Syntax Error if the LexicallyDeclaredNames of ModuleItemList contains any duplicate entries. diff --git a/js/src/tests/test262/language/module-code/early-dup-top-function-async-generator.js b/js/src/tests/test262/language/module-code/early-dup-top-function-async-generator.js new file mode 100644 index 000000000000..9a9b0b503245 --- /dev/null +++ b/js/src/tests/test262/language/module-code/early-dup-top-function-async-generator.js @@ -0,0 +1,21 @@ +// |reftest| error:SyntaxError module +// Copyright 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-semantics-static-semantics-early-errors +description: > + It is a Syntax Error if the LexicallyDeclaredNames of ModuleItemList + contains any duplicate entries. + At the top level of a Module, function declarations are treated like + lexical declarations rather than like var declarations. +flags: [module] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +function x() {} +async function* x() {} diff --git a/js/src/tests/test262/language/module-code/early-dup-top-function-async.js b/js/src/tests/test262/language/module-code/early-dup-top-function-async.js new file mode 100644 index 000000000000..dec4dbe90483 --- /dev/null +++ b/js/src/tests/test262/language/module-code/early-dup-top-function-async.js @@ -0,0 +1,21 @@ +// |reftest| error:SyntaxError module +// Copyright 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-semantics-static-semantics-early-errors +description: > + It is a Syntax Error if the LexicallyDeclaredNames of ModuleItemList + contains any duplicate entries. + At the top level of a Module, function declarations are treated like + lexical declarations rather than like var declarations. +flags: [module] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +function x() {} +async function x() {} diff --git a/js/src/tests/test262/language/module-code/early-dup-top-function-generator.js b/js/src/tests/test262/language/module-code/early-dup-top-function-generator.js new file mode 100644 index 000000000000..9e6c9743df8a --- /dev/null +++ b/js/src/tests/test262/language/module-code/early-dup-top-function-generator.js @@ -0,0 +1,21 @@ +// |reftest| error:SyntaxError module +// Copyright 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-semantics-static-semantics-early-errors +description: > + It is a Syntax Error if the LexicallyDeclaredNames of ModuleItemList + contains any duplicate entries. + At the top level of a Module, function declarations are treated like + lexical declarations rather than like var declarations. +flags: [module] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +function x() {} +function* x() {} diff --git a/js/src/tests/test262/language/module-code/early-dup-top-function.js b/js/src/tests/test262/language/module-code/early-dup-top-function.js new file mode 100644 index 000000000000..6b358065cc6d --- /dev/null +++ b/js/src/tests/test262/language/module-code/early-dup-top-function.js @@ -0,0 +1,21 @@ +// |reftest| error:SyntaxError module +// Copyright 2021 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-semantics-static-semantics-early-errors +description: > + It is a Syntax Error if the LexicallyDeclaredNames of ModuleItemList + contains any duplicate entries. + At the top level of a Module, function declarations are treated like + lexical declarations rather than like var declarations. +flags: [module] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +function x() {} +function x() {} diff --git a/js/src/tests/test262/language/module-code/namespace/internals/define-own-property.js b/js/src/tests/test262/language/module-code/namespace/internals/define-own-property.js index e1ee2208a0d0..bb3f73fe0e40 100644 --- a/js/src/tests/test262/language/module-code/namespace/internals/define-own-property.js +++ b/js/src/tests/test262/language/module-code/namespace/internals/define-own-property.js @@ -116,4 +116,25 @@ assert.throws(TypeError, function() { configurable: false}); }, 'Object.defineProperty: Symbol.toStringTag'); + +// Indirect change requested through Object.freeze + +// Try freezing more times than there are exported properties +for (let i = 1; i < exported.length + 2; i++) { + assert.throws( + TypeError, + function () { + Object.freeze(ns); + }, + "Object.freeze: " + String(i) + ); +} + +for (const key of exported) { + const desc = Object.getOwnPropertyDescriptor(ns, key); + assert.sameValue(desc.writable, true, String(key) + " writable"); +} + +assert(!Object.isFrozen(ns), "namespace object not frozen"); + reportCompare(0, 0); diff --git a/js/src/tests/test262/language/rest-parameters/arrow-function.js b/js/src/tests/test262/language/rest-parameters/arrow-function.js index 20bea1981cf3..c06d76b9be0a 100644 --- a/js/src/tests/test262/language/rest-parameters/arrow-function.js +++ b/js/src/tests/test262/language/rest-parameters/arrow-function.js @@ -8,12 +8,12 @@ includes: [compareArray.js] ---*/ var fn = (a, b, ...c) => c; -assert(compareArray(fn(), []), "`compareArray(fn(), [])` returns `true`"); -assert(compareArray(fn(1, 2), []), "`compareArray(fn(1, 2), [])` returns `true`"); -assert(compareArray(fn(1, 2, 3), [3]),"`compareArray(fn(1, 2, 3), [3])` returns `true`"); -assert(compareArray(fn(1, 2, 3, 4), [3, 4]),"`compareArray(fn(1, 2, 3, 4), [3, 4])` returns `true`"); -assert(compareArray(fn(1, 2, 3, 4, 5), [3, 4, 5]),"`compareArray(fn(1, 2, 3, 4, 5), [3, 4, 5])` returns `true`"); -assert(compareArray(((...args) => args)(), []),"`compareArray(((...args) => args)(), [])` returns `true`"); -assert(compareArray(((...args) => args)(1,2,3), [1,2,3]),"`compareArray(((...args) => args)(1,2,3), [1,2,3])` returns `true`"); +assert.compareArray(fn(), []); +assert.compareArray(fn(1, 2), []); +assert.compareArray(fn(1, 2, 3), [3]); +assert.compareArray(fn(1, 2, 3, 4), [3, 4]); +assert.compareArray(fn(1, 2, 3, 4, 5), [3, 4, 5]); +assert.compareArray(((...args) => args)(), []); +assert.compareArray(((...args) => args)(1,2,3), [1,2,3]); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/rest-parameters/no-alias-arguments.js b/js/src/tests/test262/language/rest-parameters/no-alias-arguments.js index bcd5714d99bc..e89eb0f9b83b 100644 --- a/js/src/tests/test262/language/rest-parameters/no-alias-arguments.js +++ b/js/src/tests/test262/language/rest-parameters/no-alias-arguments.js @@ -10,7 +10,7 @@ function f(a, ...rest) { arguments[0] = 1; assert.sameValue(a, 3, "The value of `a` is `3`"); arguments[1] = 2; - assert(compareArray(rest, [4, 5]), "`compareArray(rest, [4, 5])` returns `true`"); + assert.compareArray(rest, [4, 5]); } f(3, 4, 5); diff --git a/js/src/tests/test262/language/rest-parameters/with-new-target.js b/js/src/tests/test262/language/rest-parameters/with-new-target.js index a81e65343f72..c23fc938e75c 100644 --- a/js/src/tests/test262/language/rest-parameters/with-new-target.js +++ b/js/src/tests/test262/language/rest-parameters/with-new-target.js @@ -18,7 +18,7 @@ class Base { for (var i = 0; i < arguments.length; ++i) { args.push(arguments[i]); } - assert(compareArray(args, a), "`compareArray(args, a)` returns `true`"); + assert.compareArray(args, a); } } class Child extends Base { @@ -34,7 +34,7 @@ class Child extends Base { for (var i = 0; i < arguments.length; ++i) { args.push(arguments[i]); } - assert(compareArray(args, b), "`compareArray(args, b)` returns `true`"); + assert.compareArray(args, b); } } @@ -43,13 +43,13 @@ var c = new Child(1, 2, 3); assert.sameValue(c.child.length, 3, "The value of `c.child.length` is `3`"); assert.sameValue(c.base.length, 3, "The value of `c.base.length` is `3`"); -assert( - compareArray(c.child, [1, 2, 3]), - "`compareArray(c.child, [1, 2, 3])` returns `true`" +assert.compareArray( + c.child, + [1, 2, 3] ); -assert( - compareArray(c.base, [1, 2, 3]), - "`compareArray(c.base, [1, 2, 3])` returns `true`" +assert.compareArray( + c.base, + [1, 2, 3] ); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-array-literal-with-item.js b/js/src/tests/test262/language/statementList/block-array-literal-with-item.js index 5d302c8177cb..83fce02a083b 100644 --- a/js/src/tests/test262/language/statementList/block-array-literal-with-item.js +++ b/js/src/tests/test262/language/statementList/block-array-literal-with-item.js @@ -41,6 +41,6 @@ info: | ---*/ -{}[42];; +{}[42]; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-array-literal.js b/js/src/tests/test262/language/statementList/block-array-literal.js index 319377cea5c4..3c3fabd5123b 100644 --- a/js/src/tests/test262/language/statementList/block-array-literal.js +++ b/js/src/tests/test262/language/statementList/block-array-literal.js @@ -41,6 +41,6 @@ info: | ---*/ -{}[];; +{}[]; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-arrow-function-assignment-expr.js b/js/src/tests/test262/language/statementList/block-arrow-function-assignment-expr.js index ead2f79044c8..7e9da64f2f01 100644 --- a/js/src/tests/test262/language/statementList/block-arrow-function-assignment-expr.js +++ b/js/src/tests/test262/language/statementList/block-arrow-function-assignment-expr.js @@ -52,6 +52,6 @@ info: | ---*/ -{}() => 42;; +{}() => 42; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-arrow-function-functionbody.js b/js/src/tests/test262/language/statementList/block-arrow-function-functionbody.js index 3870215d16a5..2c2452cf7d6b 100644 --- a/js/src/tests/test262/language/statementList/block-arrow-function-functionbody.js +++ b/js/src/tests/test262/language/statementList/block-arrow-function-functionbody.js @@ -52,6 +52,6 @@ info: | ---*/ -{}() => { return 42; };; +{}() => { return 42; }; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-block-with-labels.js b/js/src/tests/test262/language/statementList/block-block-with-labels.js index 38fd845bfaa2..04dc5f98b5fc 100644 --- a/js/src/tests/test262/language/statementList/block-block-with-labels.js +++ b/js/src/tests/test262/language/statementList/block-block-with-labels.js @@ -37,6 +37,6 @@ info: | ---*/ -{}{x: 42};; +{}{x: 42}; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-block.js b/js/src/tests/test262/language/statementList/block-block.js index 1c8433a5fd79..bf019e152921 100644 --- a/js/src/tests/test262/language/statementList/block-block.js +++ b/js/src/tests/test262/language/statementList/block-block.js @@ -37,6 +37,6 @@ info: | ---*/ -{}{}; +{}{} reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-expr-arrow-function-boolean-literal.js b/js/src/tests/test262/language/statementList/block-expr-arrow-function-boolean-literal.js index 739221c0a927..134558c9604f 100644 --- a/js/src/tests/test262/language/statementList/block-expr-arrow-function-boolean-literal.js +++ b/js/src/tests/test262/language/statementList/block-expr-arrow-function-boolean-literal.js @@ -54,6 +54,6 @@ info: | ---*/ -{}() => 1, 42;; +{}() => 1, 42; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-let-declaration.js b/js/src/tests/test262/language/statementList/block-let-declaration.js index 45eb225e7a72..1367ef4ffabd 100644 --- a/js/src/tests/test262/language/statementList/block-let-declaration.js +++ b/js/src/tests/test262/language/statementList/block-let-declaration.js @@ -35,6 +35,6 @@ info: | ---*/ -{}let a, b = 42, c;b;; +{}let a, b = 42, c;b; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-regexp-literal-flags.js b/js/src/tests/test262/language/statementList/block-regexp-literal-flags.js index 3c13911cf685..58d9b38fca4d 100644 --- a/js/src/tests/test262/language/statementList/block-regexp-literal-flags.js +++ b/js/src/tests/test262/language/statementList/block-regexp-literal-flags.js @@ -39,6 +39,6 @@ info: | ---*/ -{}/1/g;; +{}/1/g; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-regexp-literal.js b/js/src/tests/test262/language/statementList/block-regexp-literal.js index ca540bb0bbee..d81ccad43fb0 100644 --- a/js/src/tests/test262/language/statementList/block-regexp-literal.js +++ b/js/src/tests/test262/language/statementList/block-regexp-literal.js @@ -39,6 +39,6 @@ info: | ---*/ -{}/1/;; +{}/1/; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-array-literal-with-item.js b/js/src/tests/test262/language/statementList/block-with-statment-array-literal-with-item.js index c8badc187968..25814099d206 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-array-literal-with-item.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-array-literal-with-item.js @@ -42,6 +42,6 @@ info: | // length is a label! -{length: 3000}[42];; +{length: 3000}[42]; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-array-literal.js b/js/src/tests/test262/language/statementList/block-with-statment-array-literal.js index 38fa20836322..85cb52d2f0f2 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-array-literal.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-array-literal.js @@ -42,6 +42,6 @@ info: | // length is a label! -{length: 3000}[];; +{length: 3000}[]; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-arrow-function-assignment-expr.js b/js/src/tests/test262/language/statementList/block-with-statment-arrow-function-assignment-expr.js index bda2b084be88..b273b9f15a26 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-arrow-function-assignment-expr.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-arrow-function-assignment-expr.js @@ -53,6 +53,6 @@ info: | // length is a label! -{length: 3000}() => 42;; +{length: 3000}() => 42; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-arrow-function-functionbody.js b/js/src/tests/test262/language/statementList/block-with-statment-arrow-function-functionbody.js index 7c8401502fe2..9357632fed7f 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-arrow-function-functionbody.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-arrow-function-functionbody.js @@ -53,6 +53,6 @@ info: | // length is a label! -{length: 3000}() => { return 42; };; +{length: 3000}() => { return 42; }; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-block-with-labels.js b/js/src/tests/test262/language/statementList/block-with-statment-block-with-labels.js index acf239f084e7..d5b2e5d86bf4 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-block-with-labels.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-block-with-labels.js @@ -38,6 +38,6 @@ info: | // length is a label! -{length: 3000}{x: 42};; +{length: 3000}{x: 42}; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-block.js b/js/src/tests/test262/language/statementList/block-with-statment-block.js index ed99a2c0aecd..fbab619f28f5 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-block.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-block.js @@ -38,6 +38,6 @@ info: | // length is a label! -{length: 3000}{}; +{length: 3000}{} reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-expr-arrow-function-boolean-literal.js b/js/src/tests/test262/language/statementList/block-with-statment-expr-arrow-function-boolean-literal.js index c342f95e14f2..ea8157f70ab6 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-expr-arrow-function-boolean-literal.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-expr-arrow-function-boolean-literal.js @@ -55,6 +55,6 @@ info: | // length is a label! -{length: 3000}() => 1, 42;; +{length: 3000}() => 1, 42; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-let-declaration.js b/js/src/tests/test262/language/statementList/block-with-statment-let-declaration.js index f8240aa52f04..834ecbd64dbc 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-let-declaration.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-let-declaration.js @@ -36,6 +36,6 @@ info: | // length is a label! -{length: 3000}let a, b = 42, c;b;; +{length: 3000}let a, b = 42, c;b; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-regexp-literal-flags.js b/js/src/tests/test262/language/statementList/block-with-statment-regexp-literal-flags.js index b7d6e7aa53e9..a37f392e60d4 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-regexp-literal-flags.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-regexp-literal-flags.js @@ -40,6 +40,6 @@ info: | // length is a label! -{length: 3000}/1/g;; +{length: 3000}/1/g; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/block-with-statment-regexp-literal.js b/js/src/tests/test262/language/statementList/block-with-statment-regexp-literal.js index caddfc8acdc1..c40c8e95132e 100644 --- a/js/src/tests/test262/language/statementList/block-with-statment-regexp-literal.js +++ b/js/src/tests/test262/language/statementList/block-with-statment-regexp-literal.js @@ -40,6 +40,6 @@ info: | // length is a label! -{length: 3000}/1/;; +{length: 3000}/1/; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-array-literal-with-item.js b/js/src/tests/test262/language/statementList/class-array-literal-with-item.js index 1fb4ab6e4ea7..1aa19aa52423 100644 --- a/js/src/tests/test262/language/statementList/class-array-literal-with-item.js +++ b/js/src/tests/test262/language/statementList/class-array-literal-with-item.js @@ -37,6 +37,6 @@ info: | ---*/ -class C {}[42];; +class C {}[42]; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-array-literal.js b/js/src/tests/test262/language/statementList/class-array-literal.js index 525cb82af232..33c61e98c5d5 100644 --- a/js/src/tests/test262/language/statementList/class-array-literal.js +++ b/js/src/tests/test262/language/statementList/class-array-literal.js @@ -37,6 +37,6 @@ info: | ---*/ -class C {}[];; +class C {}[]; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-arrow-function-assignment-expr.js b/js/src/tests/test262/language/statementList/class-arrow-function-assignment-expr.js index 2b15a6f49a87..07aee9e77794 100644 --- a/js/src/tests/test262/language/statementList/class-arrow-function-assignment-expr.js +++ b/js/src/tests/test262/language/statementList/class-arrow-function-assignment-expr.js @@ -47,6 +47,6 @@ info: | ---*/ -class C {}() => 42;; +class C {}() => 42; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-arrow-function-functionbody.js b/js/src/tests/test262/language/statementList/class-arrow-function-functionbody.js index de5a4b56b974..1ffa8fc9bbf0 100644 --- a/js/src/tests/test262/language/statementList/class-arrow-function-functionbody.js +++ b/js/src/tests/test262/language/statementList/class-arrow-function-functionbody.js @@ -47,6 +47,6 @@ info: | ---*/ -class C {}() => { return 42; };; +class C {}() => { return 42; }; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-block-with-labels.js b/js/src/tests/test262/language/statementList/class-block-with-labels.js index 466c3131c0cd..ddab23b2065e 100644 --- a/js/src/tests/test262/language/statementList/class-block-with-labels.js +++ b/js/src/tests/test262/language/statementList/class-block-with-labels.js @@ -33,6 +33,6 @@ info: | ---*/ -class C {}{x: 42};; +class C {}{x: 42}; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-block.js b/js/src/tests/test262/language/statementList/class-block.js index 82b7faba16c9..4b44b01bf0cf 100644 --- a/js/src/tests/test262/language/statementList/class-block.js +++ b/js/src/tests/test262/language/statementList/class-block.js @@ -33,6 +33,6 @@ info: | ---*/ -class C {}{}; +class C {}{} reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-expr-arrow-function-boolean-literal.js b/js/src/tests/test262/language/statementList/class-expr-arrow-function-boolean-literal.js index 8e08f7d29eb8..3ae44aa17f45 100644 --- a/js/src/tests/test262/language/statementList/class-expr-arrow-function-boolean-literal.js +++ b/js/src/tests/test262/language/statementList/class-expr-arrow-function-boolean-literal.js @@ -49,6 +49,6 @@ info: | ---*/ -class C {}() => 1, 42;; +class C {}() => 1, 42; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-let-declaration.js b/js/src/tests/test262/language/statementList/class-let-declaration.js index 48fdc54e4bc3..f0650cda0175 100644 --- a/js/src/tests/test262/language/statementList/class-let-declaration.js +++ b/js/src/tests/test262/language/statementList/class-let-declaration.js @@ -31,6 +31,6 @@ info: | ---*/ -class C {}let a, b = 42, c;b;; +class C {}let a, b = 42, c;b; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-regexp-literal-flags.js b/js/src/tests/test262/language/statementList/class-regexp-literal-flags.js index 080ec308b56d..91bf33d154cb 100644 --- a/js/src/tests/test262/language/statementList/class-regexp-literal-flags.js +++ b/js/src/tests/test262/language/statementList/class-regexp-literal-flags.js @@ -35,6 +35,6 @@ info: | ---*/ -class C {}/1/g;; +class C {}/1/g; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/class-regexp-literal.js b/js/src/tests/test262/language/statementList/class-regexp-literal.js index c0e658bb19ed..c51ba2917eed 100644 --- a/js/src/tests/test262/language/statementList/class-regexp-literal.js +++ b/js/src/tests/test262/language/statementList/class-regexp-literal.js @@ -35,6 +35,6 @@ info: | ---*/ -class C {}/1/;; +class C {}/1/; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-array-literal-with-item.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-array-literal-with-item.js index af18bc0bf647..d7fadffd0df0 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-array-literal-with-item.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-array-literal-with-item.js @@ -42,7 +42,7 @@ info: | // length is a label! -var result = eval('{length: 3000}[42];;'); +var result = eval('{length: 3000}[42];'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-array-literal.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-array-literal.js index acf26d1435e7..2516710486ee 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-array-literal.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-array-literal.js @@ -42,7 +42,7 @@ info: | // length is a label! -var result = eval('{length: 3000}[];;'); +var result = eval('{length: 3000}[];'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-arrow-function-assignment-expr.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-arrow-function-assignment-expr.js index 28166541e0c4..be6e76218f55 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-arrow-function-assignment-expr.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-arrow-function-assignment-expr.js @@ -53,7 +53,7 @@ info: | // length is a label! -var result = eval('{length: 3000}() => 42;;'); +var result = eval('{length: 3000}() => 42;'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-arrow-function-functionbody.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-arrow-function-functionbody.js index 307813ff99d0..2506b170bf44 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-arrow-function-functionbody.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-arrow-function-functionbody.js @@ -53,7 +53,7 @@ info: | // length is a label! -var result = eval('{length: 3000}() => { return 42; };;'); +var result = eval('{length: 3000}() => { return 42; };'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-block-with-labels.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-block-with-labels.js index 9362d809efdc..f6313f55148c 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-block-with-labels.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-block-with-labels.js @@ -38,7 +38,7 @@ info: | // length is a label! -var result = eval('{length: 3000}{x: 42};;'); +var result = eval('{length: 3000}{x: 42};'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-block.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-block.js index 2a0d2f494484..3098521ad03c 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-block.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-block.js @@ -38,7 +38,7 @@ info: | // length is a label! -var result = eval('{length: 3000}{};'); +var result = eval('{length: 3000}{}'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-expr-arrow-function-boolean-literal.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-expr-arrow-function-boolean-literal.js index cb4a37681a5b..a13a372545dc 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-expr-arrow-function-boolean-literal.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-expr-arrow-function-boolean-literal.js @@ -55,7 +55,7 @@ info: | // length is a label! -var result = eval('{length: 3000}() => 1, 42;;'); +var result = eval('{length: 3000}() => 1, 42;'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-let-declaration.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-let-declaration.js index d76a6fbaa92d..40d02316f980 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-let-declaration.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-let-declaration.js @@ -36,7 +36,7 @@ info: | // length is a label! -var result = eval('{length: 3000}let a, b = 42, c;b;;'); +var result = eval('{length: 3000}let a, b = 42, c;b;'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-regexp-literal-flags.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-regexp-literal-flags.js index 74f207570df7..abac7a6e335b 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-regexp-literal-flags.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-regexp-literal-flags.js @@ -40,7 +40,7 @@ info: | // length is a label! -var result = eval('{length: 3000}/1/g;;'); +var result = eval('{length: 3000}/1/g;'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-block-with-statment-regexp-literal.js b/js/src/tests/test262/language/statementList/eval-block-with-statment-regexp-literal.js index bc7aaecccad7..a09cfd914cf9 100644 --- a/js/src/tests/test262/language/statementList/eval-block-with-statment-regexp-literal.js +++ b/js/src/tests/test262/language/statementList/eval-block-with-statment-regexp-literal.js @@ -40,7 +40,7 @@ info: | // length is a label! -var result = eval('{length: 3000}/1/;;'); +var result = eval('{length: 3000}/1/;'); // Reuse this value for items with empty completions var expected = 3000; diff --git a/js/src/tests/test262/language/statementList/eval-class-array-literal-with-item.js b/js/src/tests/test262/language/statementList/eval-class-array-literal-with-item.js index b05d921ccfe3..1dee5e82dd30 100644 --- a/js/src/tests/test262/language/statementList/eval-class-array-literal-with-item.js +++ b/js/src/tests/test262/language/statementList/eval-class-array-literal-with-item.js @@ -37,7 +37,7 @@ info: | ---*/ -var result = eval('class C {}[42];;'); +var result = eval('class C {}[42];'); assert.sameValue(Object.getPrototypeOf(result), Array.prototype); assert.sameValue(result.length, 1); diff --git a/js/src/tests/test262/language/statementList/eval-class-array-literal.js b/js/src/tests/test262/language/statementList/eval-class-array-literal.js index 52eb55be21fe..34ef5aaf8bc0 100644 --- a/js/src/tests/test262/language/statementList/eval-class-array-literal.js +++ b/js/src/tests/test262/language/statementList/eval-class-array-literal.js @@ -37,7 +37,7 @@ info: | ---*/ -var result = eval('class C {}[];;'); +var result = eval('class C {}[];'); assert.sameValue(Object.getPrototypeOf(result), Array.prototype); assert.sameValue(result.length, 0); diff --git a/js/src/tests/test262/language/statementList/eval-class-arrow-function-assignment-expr.js b/js/src/tests/test262/language/statementList/eval-class-arrow-function-assignment-expr.js index b4eaa74abcf6..c75d84ad5fee 100644 --- a/js/src/tests/test262/language/statementList/eval-class-arrow-function-assignment-expr.js +++ b/js/src/tests/test262/language/statementList/eval-class-arrow-function-assignment-expr.js @@ -47,7 +47,7 @@ info: | ---*/ -var result = eval('class C {}() => 42;;'); +var result = eval('class C {}() => 42;'); assert.sameValue(result(), 42); diff --git a/js/src/tests/test262/language/statementList/eval-class-arrow-function-functionbody.js b/js/src/tests/test262/language/statementList/eval-class-arrow-function-functionbody.js index 4b0db1eaf91a..1ba16b4aa7fa 100644 --- a/js/src/tests/test262/language/statementList/eval-class-arrow-function-functionbody.js +++ b/js/src/tests/test262/language/statementList/eval-class-arrow-function-functionbody.js @@ -47,7 +47,7 @@ info: | ---*/ -var result = eval('class C {}() => { return 42; };;'); +var result = eval('class C {}() => { return 42; };'); assert.sameValue(result(), 42); diff --git a/js/src/tests/test262/language/statementList/eval-class-block-with-labels.js b/js/src/tests/test262/language/statementList/eval-class-block-with-labels.js index 0e6562f0d575..32f5543b4175 100644 --- a/js/src/tests/test262/language/statementList/eval-class-block-with-labels.js +++ b/js/src/tests/test262/language/statementList/eval-class-block-with-labels.js @@ -33,7 +33,7 @@ info: | ---*/ -var result = eval('class C {}{x: 42};;'); +var result = eval('class C {}{x: 42};'); assert.sameValue(result, 42, 'it does not evaluate to an Object with the property x'); diff --git a/js/src/tests/test262/language/statementList/eval-class-block.js b/js/src/tests/test262/language/statementList/eval-class-block.js index 58e54d65da4c..1682bca69f58 100644 --- a/js/src/tests/test262/language/statementList/eval-class-block.js +++ b/js/src/tests/test262/language/statementList/eval-class-block.js @@ -33,7 +33,7 @@ info: | ---*/ -var result = eval('class C {}{};'); +var result = eval('class C {}{}'); assert.sameValue(result, undefined); diff --git a/js/src/tests/test262/language/statementList/eval-class-expr-arrow-function-boolean-literal.js b/js/src/tests/test262/language/statementList/eval-class-expr-arrow-function-boolean-literal.js index 6e417c7370b5..0ea869d92e97 100644 --- a/js/src/tests/test262/language/statementList/eval-class-expr-arrow-function-boolean-literal.js +++ b/js/src/tests/test262/language/statementList/eval-class-expr-arrow-function-boolean-literal.js @@ -49,7 +49,7 @@ info: | ---*/ -var result = eval('class C {}() => 1, 42;;'); +var result = eval('class C {}() => 1, 42;'); assert.sameValue(result, 42); diff --git a/js/src/tests/test262/language/statementList/eval-class-let-declaration.js b/js/src/tests/test262/language/statementList/eval-class-let-declaration.js index fc840d03be18..483f40be29d5 100644 --- a/js/src/tests/test262/language/statementList/eval-class-let-declaration.js +++ b/js/src/tests/test262/language/statementList/eval-class-let-declaration.js @@ -31,7 +31,7 @@ info: | ---*/ -var result = eval('class C {}let a, b = 42, c;b;;'); +var result = eval('class C {}let a, b = 42, c;b;'); assert.sameValue(result, 42); diff --git a/js/src/tests/test262/language/statementList/eval-class-regexp-literal-flags.js b/js/src/tests/test262/language/statementList/eval-class-regexp-literal-flags.js index 8851bc147c55..968cfe8facb3 100644 --- a/js/src/tests/test262/language/statementList/eval-class-regexp-literal-flags.js +++ b/js/src/tests/test262/language/statementList/eval-class-regexp-literal-flags.js @@ -35,7 +35,7 @@ info: | ---*/ -var result = eval('class C {}/1/g;;'); +var result = eval('class C {}/1/g;'); assert.sameValue(Object.getPrototypeOf(result), RegExp.prototype); assert.sameValue(result.flags, 'g'); diff --git a/js/src/tests/test262/language/statementList/eval-class-regexp-literal.js b/js/src/tests/test262/language/statementList/eval-class-regexp-literal.js index c09dd4210f4e..07b0555c476f 100644 --- a/js/src/tests/test262/language/statementList/eval-class-regexp-literal.js +++ b/js/src/tests/test262/language/statementList/eval-class-regexp-literal.js @@ -35,7 +35,7 @@ info: | ---*/ -var result = eval('class C {}/1/;;'); +var result = eval('class C {}/1/;'); assert.sameValue(Object.getPrototypeOf(result), RegExp.prototype); assert.sameValue(result.flags, ''); diff --git a/js/src/tests/test262/language/statementList/eval-fn-array-literal-with-item.js b/js/src/tests/test262/language/statementList/eval-fn-array-literal-with-item.js index b4524fae11e1..1e00eddc4f65 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-array-literal-with-item.js +++ b/js/src/tests/test262/language/statementList/eval-fn-array-literal-with-item.js @@ -38,7 +38,7 @@ info: | ---*/ -var result = eval('function fn() {}[42];;'); +var result = eval('function fn() {}[42];'); assert.sameValue(Object.getPrototypeOf(result), Array.prototype); assert.sameValue(result.length, 1); diff --git a/js/src/tests/test262/language/statementList/eval-fn-array-literal.js b/js/src/tests/test262/language/statementList/eval-fn-array-literal.js index 7430098bb9ac..4debcfa53428 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-array-literal.js +++ b/js/src/tests/test262/language/statementList/eval-fn-array-literal.js @@ -38,7 +38,7 @@ info: | ---*/ -var result = eval('function fn() {}[];;'); +var result = eval('function fn() {}[];'); assert.sameValue(Object.getPrototypeOf(result), Array.prototype); assert.sameValue(result.length, 0); diff --git a/js/src/tests/test262/language/statementList/eval-fn-arrow-function-assignment-expr.js b/js/src/tests/test262/language/statementList/eval-fn-arrow-function-assignment-expr.js index 4e73b4d381a2..29cd258e7ec5 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-arrow-function-assignment-expr.js +++ b/js/src/tests/test262/language/statementList/eval-fn-arrow-function-assignment-expr.js @@ -49,7 +49,7 @@ info: | ---*/ -var result = eval('function fn() {}() => 42;;'); +var result = eval('function fn() {}() => 42;'); assert.sameValue(result(), 42); diff --git a/js/src/tests/test262/language/statementList/eval-fn-arrow-function-functionbody.js b/js/src/tests/test262/language/statementList/eval-fn-arrow-function-functionbody.js index eb0ac8ce865f..d41222aac7f9 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-arrow-function-functionbody.js +++ b/js/src/tests/test262/language/statementList/eval-fn-arrow-function-functionbody.js @@ -49,7 +49,7 @@ info: | ---*/ -var result = eval('function fn() {}() => { return 42; };;'); +var result = eval('function fn() {}() => { return 42; };'); assert.sameValue(result(), 42); diff --git a/js/src/tests/test262/language/statementList/eval-fn-block-with-labels.js b/js/src/tests/test262/language/statementList/eval-fn-block-with-labels.js index 93f9016452d8..9b4ef5366e93 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-block-with-labels.js +++ b/js/src/tests/test262/language/statementList/eval-fn-block-with-labels.js @@ -34,7 +34,7 @@ info: | ---*/ -var result = eval('function fn() {}{x: 42};;'); +var result = eval('function fn() {}{x: 42};'); assert.sameValue(result, 42, 'it does not evaluate to an Object with the property x'); diff --git a/js/src/tests/test262/language/statementList/eval-fn-block.js b/js/src/tests/test262/language/statementList/eval-fn-block.js index 5b4816d8e71d..4d46e8c74fca 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-block.js +++ b/js/src/tests/test262/language/statementList/eval-fn-block.js @@ -34,7 +34,7 @@ info: | ---*/ -var result = eval('function fn() {}{};'); +var result = eval('function fn() {}{}'); assert.sameValue(result, undefined); diff --git a/js/src/tests/test262/language/statementList/eval-fn-expr-arrow-function-boolean-literal.js b/js/src/tests/test262/language/statementList/eval-fn-expr-arrow-function-boolean-literal.js index 5c769792bc07..f9000796766a 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-expr-arrow-function-boolean-literal.js +++ b/js/src/tests/test262/language/statementList/eval-fn-expr-arrow-function-boolean-literal.js @@ -51,7 +51,7 @@ info: | ---*/ -var result = eval('function fn() {}() => 1, 42;;'); +var result = eval('function fn() {}() => 1, 42;'); assert.sameValue(result, 42); diff --git a/js/src/tests/test262/language/statementList/eval-fn-let-declaration.js b/js/src/tests/test262/language/statementList/eval-fn-let-declaration.js index b5c6dc99a704..68ae78bb184b 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-let-declaration.js +++ b/js/src/tests/test262/language/statementList/eval-fn-let-declaration.js @@ -32,7 +32,7 @@ info: | ---*/ -var result = eval('function fn() {}let a, b = 42, c;b;;'); +var result = eval('function fn() {}let a, b = 42, c;b;'); assert.sameValue(result, 42); diff --git a/js/src/tests/test262/language/statementList/eval-fn-regexp-literal-flags.js b/js/src/tests/test262/language/statementList/eval-fn-regexp-literal-flags.js index 5ff481b4eee7..48861d4f3482 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-regexp-literal-flags.js +++ b/js/src/tests/test262/language/statementList/eval-fn-regexp-literal-flags.js @@ -36,7 +36,7 @@ info: | ---*/ -var result = eval('function fn() {}/1/g;;'); +var result = eval('function fn() {}/1/g;'); assert.sameValue(Object.getPrototypeOf(result), RegExp.prototype); assert.sameValue(result.flags, 'g'); diff --git a/js/src/tests/test262/language/statementList/eval-fn-regexp-literal.js b/js/src/tests/test262/language/statementList/eval-fn-regexp-literal.js index a7280b410775..110beae7d8e8 100644 --- a/js/src/tests/test262/language/statementList/eval-fn-regexp-literal.js +++ b/js/src/tests/test262/language/statementList/eval-fn-regexp-literal.js @@ -36,7 +36,7 @@ info: | ---*/ -var result = eval('function fn() {}/1/;;'); +var result = eval('function fn() {}/1/;'); assert.sameValue(Object.getPrototypeOf(result), RegExp.prototype); assert.sameValue(result.flags, ''); diff --git a/js/src/tests/test262/language/statementList/fn-array-literal-with-item.js b/js/src/tests/test262/language/statementList/fn-array-literal-with-item.js index b5e0b5999b09..2eb407c6a140 100644 --- a/js/src/tests/test262/language/statementList/fn-array-literal-with-item.js +++ b/js/src/tests/test262/language/statementList/fn-array-literal-with-item.js @@ -38,6 +38,6 @@ info: | ---*/ -function fn() {}[42];; +function fn() {}[42]; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-array-literal.js b/js/src/tests/test262/language/statementList/fn-array-literal.js index e5ab5b23645e..cd832c2359a2 100644 --- a/js/src/tests/test262/language/statementList/fn-array-literal.js +++ b/js/src/tests/test262/language/statementList/fn-array-literal.js @@ -38,6 +38,6 @@ info: | ---*/ -function fn() {}[];; +function fn() {}[]; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-arrow-function-assignment-expr.js b/js/src/tests/test262/language/statementList/fn-arrow-function-assignment-expr.js index 56e8c27d589c..16b8c869fd98 100644 --- a/js/src/tests/test262/language/statementList/fn-arrow-function-assignment-expr.js +++ b/js/src/tests/test262/language/statementList/fn-arrow-function-assignment-expr.js @@ -49,6 +49,6 @@ info: | ---*/ -function fn() {}() => 42;; +function fn() {}() => 42; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-arrow-function-functionbody.js b/js/src/tests/test262/language/statementList/fn-arrow-function-functionbody.js index ad78d2ac9951..1f153799abf6 100644 --- a/js/src/tests/test262/language/statementList/fn-arrow-function-functionbody.js +++ b/js/src/tests/test262/language/statementList/fn-arrow-function-functionbody.js @@ -49,6 +49,6 @@ info: | ---*/ -function fn() {}() => { return 42; };; +function fn() {}() => { return 42; }; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-block-with-labels.js b/js/src/tests/test262/language/statementList/fn-block-with-labels.js index a092a5ce9cb7..86954a7aced6 100644 --- a/js/src/tests/test262/language/statementList/fn-block-with-labels.js +++ b/js/src/tests/test262/language/statementList/fn-block-with-labels.js @@ -34,6 +34,6 @@ info: | ---*/ -function fn() {}{x: 42};; +function fn() {}{x: 42}; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-block.js b/js/src/tests/test262/language/statementList/fn-block.js index db524f09e3e1..dac598923a4e 100644 --- a/js/src/tests/test262/language/statementList/fn-block.js +++ b/js/src/tests/test262/language/statementList/fn-block.js @@ -34,6 +34,6 @@ info: | ---*/ -function fn() {}{}; +function fn() {}{} reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-expr-arrow-function-boolean-literal.js b/js/src/tests/test262/language/statementList/fn-expr-arrow-function-boolean-literal.js index 16851c0e2c0b..3800df00648b 100644 --- a/js/src/tests/test262/language/statementList/fn-expr-arrow-function-boolean-literal.js +++ b/js/src/tests/test262/language/statementList/fn-expr-arrow-function-boolean-literal.js @@ -51,6 +51,6 @@ info: | ---*/ -function fn() {}() => 1, 42;; +function fn() {}() => 1, 42; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-let-declaration.js b/js/src/tests/test262/language/statementList/fn-let-declaration.js index 87ae5dad0266..de6c28631f0f 100644 --- a/js/src/tests/test262/language/statementList/fn-let-declaration.js +++ b/js/src/tests/test262/language/statementList/fn-let-declaration.js @@ -32,6 +32,6 @@ info: | ---*/ -function fn() {}let a, b = 42, c;b;; +function fn() {}let a, b = 42, c;b; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-regexp-literal-flags.js b/js/src/tests/test262/language/statementList/fn-regexp-literal-flags.js index 2ea71b47725c..5c426ec3fadf 100644 --- a/js/src/tests/test262/language/statementList/fn-regexp-literal-flags.js +++ b/js/src/tests/test262/language/statementList/fn-regexp-literal-flags.js @@ -36,6 +36,6 @@ info: | ---*/ -function fn() {}/1/g;; +function fn() {}/1/g; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statementList/fn-regexp-literal.js b/js/src/tests/test262/language/statementList/fn-regexp-literal.js index 84f3b62e1526..e335e4f1d9d5 100644 --- a/js/src/tests/test262/language/statementList/fn-regexp-literal.js +++ b/js/src/tests/test262/language/statementList/fn-regexp-literal.js @@ -36,6 +36,6 @@ info: | ---*/ -function fn() {}/1/;; +function fn() {}/1/; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/async-generator/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/async-generator/yield-spread-arr-multiple.js index 760d68700e0f..3f22543ccae0 100644 --- a/js/src/tests/test262/language/statements/async-generator/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/async-generator/yield-spread-arr-multiple.js @@ -42,7 +42,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/statements/block/labeled-continue.js b/js/src/tests/test262/language/statements/block/labeled-continue.js new file mode 100644 index 000000000000..dc08215409a4 --- /dev/null +++ b/js/src/tests/test262/language/statements/block/labeled-continue.js @@ -0,0 +1,25 @@ +// |reftest| error:SyntaxError +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-static-semantics-containsundefinedcontinuetarget +description: Clears label set in check for undefined `continue` target +info: | + With arguments iterationSet and labelSet. + + Statement : BlockStatement + + 1. Return ContainsUndefinedContinueTarget of |BlockStatement| with arguments + _iterationSet_ and « ». +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +label: { + for ( ;; ) { + continue label; + } +} diff --git a/js/src/tests/test262/language/statements/class/async-gen-method-static/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/class/async-gen-method-static/yield-spread-arr-multiple.js index 4200b353b44a..a45a13e0bd91 100644 --- a/js/src/tests/test262/language/statements/class/async-gen-method-static/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/class/async-gen-method-static/yield-spread-arr-multiple.js @@ -49,7 +49,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/statements/class/async-gen-method/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/class/async-gen-method/yield-spread-arr-multiple.js index 47dac7453836..1396fedca977 100644 --- a/js/src/tests/test262/language/statements/class/async-gen-method/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/class/async-gen-method/yield-spread-arr-multiple.js @@ -49,7 +49,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/statements/class/cpn-class-decl-accessors-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/statements/class/cpn-class-decl-accessors-computed-property-name-from-yield-expression.js index dbcebbc7c0f7..c3b76eb7c056 100644 --- a/js/src/tests/test262/language/statements/class/cpn-class-decl-accessors-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/statements/class/cpn-class-decl-accessors-computed-property-name-from-yield-expression.js @@ -92,5 +92,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/cpn-class-decl-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/statements/class/cpn-class-decl-computed-property-name-from-yield-expression.js index 5e4883dfdf70..3ad6aa530a1b 100644 --- a/js/src/tests/test262/language/statements/class/cpn-class-decl-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/statements/class/cpn-class-decl-computed-property-name-from-yield-expression.js @@ -65,5 +65,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/cpn-class-decl-fields-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/statements/class/cpn-class-decl-fields-computed-property-name-from-yield-expression.js index 569e93c76006..b48c6f884ce2 100644 --- a/js/src/tests/test262/language/statements/class/cpn-class-decl-fields-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/statements/class/cpn-class-decl-fields-computed-property-name-from-yield-expression.js @@ -62,5 +62,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/cpn-class-decl-fields-methods-computed-property-name-from-yield-expression.js b/js/src/tests/test262/language/statements/class/cpn-class-decl-fields-methods-computed-property-name-from-yield-expression.js index d39098768bc7..24ab16a2c633 100644 --- a/js/src/tests/test262/language/statements/class/cpn-class-decl-fields-methods-computed-property-name-from-yield-expression.js +++ b/js/src/tests/test262/language/statements/class/cpn-class-decl-fields-methods-computed-property-name-from-yield-expression.js @@ -66,5 +66,7 @@ assert.sameValue( ); } +var iter = g(); +while (iter.next().done === false) ; reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/definition/fn-length-static-precedence-order.js b/js/src/tests/test262/language/statements/class/definition/fn-length-static-precedence-order.js index 5b28396e7d38..ec6501c61f8b 100644 --- a/js/src/tests/test262/language/statements/class/definition/fn-length-static-precedence-order.js +++ b/js/src/tests/test262/language/statements/class/definition/fn-length-static-precedence-order.js @@ -33,7 +33,7 @@ class A { } } -assert(compareArray(Object.getOwnPropertyNames(A), ['length', 'name', 'prototype', 'method'])) +assert.compareArray(Object.getOwnPropertyNames(A), ['length', 'name', 'prototype', 'method']) var attr = 'length'; class B { @@ -45,7 +45,7 @@ class B { } } -assert(compareArray(Object.getOwnPropertyNames(B), ['length', 'name', 'prototype'])) +assert.compareArray(Object.getOwnPropertyNames(B), ['length', 'name', 'prototype']) class C { static get length() { @@ -53,7 +53,7 @@ class C { } } -assert(compareArray(Object.getOwnPropertyNames(C), ['length', 'name', 'prototype'])) +assert.compareArray(Object.getOwnPropertyNames(C), ['length', 'name', 'prototype']) class D { static set length(_) { @@ -61,7 +61,7 @@ class D { } } -assert(compareArray(Object.getOwnPropertyNames(D), ['length', 'name', 'prototype'])) +assert.compareArray(Object.getOwnPropertyNames(D), ['length', 'name', 'prototype']) class E { static *length() { @@ -69,6 +69,6 @@ class E { } } -assert(compareArray(Object.getOwnPropertyNames(E), ['length', 'name', 'prototype'])) +assert.compareArray(Object.getOwnPropertyNames(E), ['length', 'name', 'prototype']) reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/definition/fn-name-static-precedence-order.js b/js/src/tests/test262/language/statements/class/definition/fn-name-static-precedence-order.js index 64e9cc1f3a67..b9e64a64b672 100644 --- a/js/src/tests/test262/language/statements/class/definition/fn-name-static-precedence-order.js +++ b/js/src/tests/test262/language/statements/class/definition/fn-name-static-precedence-order.js @@ -30,7 +30,7 @@ class A { } } -assert(compareArray(Object.getOwnPropertyNames(A), ['length', 'name', 'prototype', 'method'])) +assert.compareArray(Object.getOwnPropertyNames(A), ['length', 'name', 'prototype', 'method']) var attr = 'name'; class B { @@ -42,7 +42,7 @@ class B { } } -assert(compareArray(Object.getOwnPropertyNames(B), ['length', 'name', 'prototype'])) +assert.compareArray(Object.getOwnPropertyNames(B), ['length', 'name', 'prototype']) class C { static get name() { @@ -50,7 +50,7 @@ class C { } } -assert(compareArray(Object.getOwnPropertyNames(C), ['length', 'name', 'prototype'])) +assert.compareArray(Object.getOwnPropertyNames(C), ['length', 'name', 'prototype']) class D { static set name(_) { @@ -58,7 +58,7 @@ class D { } } -assert(compareArray(Object.getOwnPropertyNames(D), ['length', 'name', 'prototype'])) +assert.compareArray(Object.getOwnPropertyNames(D), ['length', 'name', 'prototype']) class E { static *name() { @@ -66,6 +66,6 @@ class E { } } -assert(compareArray(Object.getOwnPropertyNames(E), ['length', 'name', 'prototype'])) +assert.compareArray(Object.getOwnPropertyNames(E), ['length', 'name', 'prototype']) reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/elements/async-gen-private-method-static/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/class/elements/async-gen-private-method-static/yield-spread-arr-multiple.js index 6498978fa82e..49d0b7993360 100644 --- a/js/src/tests/test262/language/statements/class/elements/async-gen-private-method-static/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/class/elements/async-gen-private-method-static/yield-spread-arr-multiple.js @@ -54,7 +54,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/statements/class/elements/async-gen-private-method/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/class/elements/async-gen-private-method/yield-spread-arr-multiple.js index ca50c1a37b98..ccf69f754b60 100644 --- a/js/src/tests/test262/language/statements/class/elements/async-gen-private-method/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/class/elements/async-gen-private-method/yield-spread-arr-multiple.js @@ -57,7 +57,7 @@ item.then(({ done, value }) => { item = iter.next(value); item.then(({ done, value }) => { - assert(compareArray(value, arr)); + assert.compareArray(value, arr); assert.sameValue(done, false); }).then($DONE, $DONE); }).catch($DONE); diff --git a/js/src/tests/test262/language/statements/class/elements/gen-private-method-static/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/class/elements/gen-private-method-static/yield-spread-arr-multiple.js index 694d036dcc54..6679592d5c8c 100644 --- a/js/src/tests/test262/language/statements/class/elements/gen-private-method-static/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/class/elements/gen-private-method-static/yield-spread-arr-multiple.js @@ -49,7 +49,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/statements/class/elements/gen-private-method/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/class/elements/gen-private-method/yield-spread-arr-multiple.js index 87a6bcf67cb6..5cd683b5eefe 100644 --- a/js/src/tests/test262/language/statements/class/elements/gen-private-method/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/class/elements/gen-private-method/yield-spread-arr-multiple.js @@ -52,7 +52,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/statements/class/elements/redeclaration-symbol.js b/js/src/tests/test262/language/statements/class/elements/redeclaration-symbol.js index 05bd64a46cb9..e89e0956ee21 100644 --- a/js/src/tests/test262/language/statements/class/elements/redeclaration-symbol.js +++ b/js/src/tests/test262/language/statements/class/elements/redeclaration-symbol.js @@ -52,6 +52,6 @@ verifyProperty(c, y, { configurable: true }); -assert(compareArray(x, ["a", "b", "c"])); +assert.compareArray(x, ["a", "b", "c"]); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/elements/redeclaration.js b/js/src/tests/test262/language/statements/class/elements/redeclaration.js index 449c9596a0b1..474d72a066cf 100644 --- a/js/src/tests/test262/language/statements/class/elements/redeclaration.js +++ b/js/src/tests/test262/language/statements/class/elements/redeclaration.js @@ -52,6 +52,6 @@ verifyProperty(c, "y", { configurable: true }); -assert(compareArray(x, ["a", "b", "c", "d"])); +assert.compareArray(x, ["a", "b", "c", "d"]); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/gen-method-static/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/class/gen-method-static/yield-spread-arr-multiple.js index 7323fb4c8730..c5e27efa2085 100644 --- a/js/src/tests/test262/language/statements/class/gen-method-static/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/class/gen-method-static/yield-spread-arr-multiple.js @@ -44,7 +44,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/statements/class/gen-method/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/class/gen-method/yield-spread-arr-multiple.js index d263eae3436d..5fc963769bc9 100644 --- a/js/src/tests/test262/language/statements/class/gen-method/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/class/gen-method/yield-spread-arr-multiple.js @@ -44,7 +44,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/statements/class/static-init-arguments-functions.js b/js/src/tests/test262/language/statements/class/static-init-arguments-functions.js index 94309ae43aaf..0473586d1d15 100644 --- a/js/src/tests/test262/language/statements/class/static-init-arguments-functions.js +++ b/js/src/tests/test262/language/statements/class/static-init-arguments-functions.js @@ -32,11 +32,11 @@ class C { } } -assert(compareArray(['function'], fn), 'body'); -assert(compareArray(['function'], fnParam), 'parameter'); -assert(compareArray(['generator function'], gen), 'body'); -assert(compareArray(['generator function'], genParam), 'parameter'); -assert(compareArray(['async function'], asyncFn), 'body'); -assert(compareArray(['async function'], asyncFnParam), 'parameter'); +assert.compareArray(['function'], fn, 'body'); +assert.compareArray(['function'], fnParam, 'parameter'); +assert.compareArray(['generator function'], gen, 'body'); +assert.compareArray(['generator function'], genParam, 'parameter'); +assert.compareArray(['async function'], asyncFn, 'body'); +assert.compareArray(['async function'], asyncFnParam, 'parameter'); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/static-init-arguments-methods.js b/js/src/tests/test262/language/statements/class/static-init-arguments-methods.js index 7a53fb9f91d0..bb4f12c008da 100644 --- a/js/src/tests/test262/language/statements/class/static-init-arguments-methods.js +++ b/js/src/tests/test262/language/statements/class/static-init-arguments-methods.js @@ -47,14 +47,14 @@ instance.accessor = 'setter'; instance.gen('generator method').next(); instance.async('async method'); -assert(compareArray(['method'], method), 'body'); -assert(compareArray(['method'], methodParam), 'parameter'); -assert(compareArray([], getter), 'body'); -assert(compareArray(['setter'], setter), 'body'); -assert(compareArray(['setter'], setterParam), 'parameter'); -assert(compareArray(['generator method'], genMethod), 'body'); -assert(compareArray(['generator method'], genMethodParam), 'parameter'); -assert(compareArray(['async method'], asyncMethod), 'body'); -assert(compareArray(['async method'], asyncMethodParam), 'parameter'); +assert.compareArray(['method'], method, 'body'); +assert.compareArray(['method'], methodParam, 'parameter'); +assert.compareArray([], getter, 'body'); +assert.compareArray(['setter'], setter, 'body'); +assert.compareArray(['setter'], setterParam, 'parameter'); +assert.compareArray(['generator method'], genMethod, 'body'); +assert.compareArray(['generator method'], genMethodParam, 'parameter'); +assert.compareArray(['async method'], asyncMethod, 'body'); +assert.compareArray(['async method'], asyncMethodParam, 'parameter'); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/subclass/builtin-objects/Array/contructor-calls-super-multiple-arguments.js b/js/src/tests/test262/language/statements/class/subclass/builtin-objects/Array/contructor-calls-super-multiple-arguments.js index 0a125a951212..e1d285b914a1 100644 --- a/js/src/tests/test262/language/statements/class/subclass/builtin-objects/Array/contructor-calls-super-multiple-arguments.js +++ b/js/src/tests/test262/language/statements/class/subclass/builtin-objects/Array/contructor-calls-super-multiple-arguments.js @@ -23,6 +23,6 @@ class Sub extends Array { var sub = new Sub(42, 'foo'); -assert(compareArray(sub, [42, 'foo'])); +assert.compareArray(sub, [42, 'foo']); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/class/subclass/builtin-objects/Array/regular-subclassing.js b/js/src/tests/test262/language/statements/class/subclass/builtin-objects/Array/regular-subclassing.js index 7cf1bfede55e..3b5df2971965 100644 --- a/js/src/tests/test262/language/statements/class/subclass/builtin-objects/Array/regular-subclassing.js +++ b/js/src/tests/test262/language/statements/class/subclass/builtin-objects/Array/regular-subclassing.js @@ -29,7 +29,7 @@ var a2 = new Sub(7); assert.sameValue(a2.length, 7); var a3 = new Sub(); -assert(compareArray(a3, [])); +assert.compareArray(a3, []); assert.sameValue(a3.length, 0); reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/for-in/S12.6.4_A7_T2.js b/js/src/tests/test262/language/statements/for-in/S12.6.4_A7_T2.js index 9c5fc5b7bcf9..f43fb8b1b1a6 100644 --- a/js/src/tests/test262/language/statements/for-in/S12.6.4_A7_T2.js +++ b/js/src/tests/test262/language/statements/for-in/S12.6.4_A7_T2.js @@ -13,7 +13,10 @@ description: > var __obj, __accum; -__obj={aa:1,ba:2,ca:3}; +__obj = Object.create(null); +__obj.aa = 1; +__obj.ba = 2; +__obj.ca = 3; __accum=""; @@ -25,23 +28,10 @@ for (var __key in __obj){ } - -////////////////////////////////////////////////////////////////////////////// -//CHECK#1 -if (!((__accum.indexOf("aa1")!==-1)&&(__accum.indexOf("ca3")!==-1))) { - throw new Test262Error('#1: (__accum.indexOf("aa1")!==-1)&&(__accum.indexOf("ca3")!==-1)'); -} -// -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -//CHECK#2 -if (__accum.indexOf("ba2")!==-1) { - throw new Test262Error('#2: __accum.indexOf("ba2") === -1. Actual: __accum.indexOf("ba2") ==='+ __accum.indexOf("ba2") ); -} -// -////////////////////////////////////////////////////////////////////////////// - +assert( + __accum === "aa1ca3" || __accum === "ca3aa1", + "Unexpected value: '" + __accum + "'" +); // erasator is the hash map terminator function erasator_T_1000(hash_map, charactr){ diff --git a/js/src/tests/test262/language/statements/for-of/dstr/array-rest-iter-rtrn-close-err.js b/js/src/tests/test262/language/statements/for-of/dstr/array-rest-iter-rtrn-close-err.js index bdf5c91a3410..d35bfcfd0ee2 100644 --- a/js/src/tests/test262/language/statements/for-of/dstr/array-rest-iter-rtrn-close-err.js +++ b/js/src/tests/test262/language/statements/for-of/dstr/array-rest-iter-rtrn-close-err.js @@ -50,7 +50,6 @@ info: | ---*/ var returnCount = 0; var unreachable = 0; -function ReturnError() {} var iterable = {}; var iterator = { return: function() { diff --git a/js/src/tests/test262/language/statements/for-of/dstr/obj-rest-order.js b/js/src/tests/test262/language/statements/for-of/dstr/obj-rest-order.js index 3a5c1865b8c9..8b6767c5026f 100644 --- a/js/src/tests/test262/language/statements/for-of/dstr/obj-rest-order.js +++ b/js/src/tests/test262/language/statements/for-of/dstr/obj-rest-order.js @@ -34,7 +34,7 @@ Object.defineProperty(o, Symbol('foo'), { get: () => { calls.push("Symbol(foo)") var counter = 0; for ({...rest} of [o]) { - assert(compareArray(calls, [1, 'z', 'a', "Symbol(foo)"])); + assert.compareArray(calls, [1, 'z', 'a', "Symbol(foo)"]); assert.sameValue(Object.keys(rest).length, 3); counter += 1; } diff --git a/js/src/tests/test262/language/statements/generators/yield-spread-arr-multiple.js b/js/src/tests/test262/language/statements/generators/yield-spread-arr-multiple.js index ad53124ff01c..25a835d11e1c 100644 --- a/js/src/tests/test262/language/statements/generators/yield-spread-arr-multiple.js +++ b/js/src/tests/test262/language/statements/generators/yield-spread-arr-multiple.js @@ -36,7 +36,7 @@ iter.next(false); item = iter.next(['a', 'b', 'c']); item = iter.next(item.value); -assert(compareArray(item.value, arr)); +assert.compareArray(item.value, arr); assert.sameValue(item.done, false); assert.sameValue(callCount, 1); diff --git a/js/src/tests/test262/language/statements/throw/S12.13_A2_T5.js b/js/src/tests/test262/language/statements/throw/S12.13_A2_T5.js index 43a84772ddba..ed30274884c7 100644 --- a/js/src/tests/test262/language/statements/throw/S12.13_A2_T5.js +++ b/js/src/tests/test262/language/statements/throw/S12.13_A2_T5.js @@ -71,7 +71,7 @@ try{ throw -0; } catch(e){ - if (e!==-0) throw new Test262Error('#8: Exception ===-0. Actual: Exception ==='+ e ); + assert.sameValue(e, -0); } reportCompare(0, 0); diff --git a/js/src/tests/test262/language/statements/try/S12.14_A18_T5.js b/js/src/tests/test262/language/statements/try/S12.14_A18_T5.js index 78953b44a9e0..ac92d818d757 100644 --- a/js/src/tests/test262/language/statements/try/S12.14_A18_T5.js +++ b/js/src/tests/test262/language/statements/try/S12.14_A18_T5.js @@ -96,7 +96,7 @@ try{ throw -0; } catch(e){ - if (e!==-0) throw new Test262Error('#11: Exception ===-0. Actual: Exception ==='+ e ); + assert.sameValue(e, -0); } reportCompare(0, 0); diff --git a/js/src/tests/test262/shell.js b/js/src/tests/test262/shell.js index 137d44de856b..00b83d099455 100644 --- a/js/src/tests/test262/shell.js +++ b/js/src/tests/test262/shell.js @@ -68,6 +68,7 @@ assert.notSameValue = function (actual, unexpected, message) { }; assert.throws = function (expectedErrorConstructor, func, message) { + var expectedName, actualName; if (typeof func !== "function") { throw new Test262Error('assert.throws requires two arguments: the error constructor ' + 'and a function to run'); @@ -86,7 +87,13 @@ assert.throws = function (expectedErrorConstructor, func, message) { message += 'Thrown value was not an object!'; throw new Test262Error(message); } else if (thrown.constructor !== expectedErrorConstructor) { - message += 'Expected a ' + expectedErrorConstructor.name + ' but got a ' + thrown.constructor.name; + expectedName = expectedErrorConstructor.name; + actualName = thrown.constructor.name; + if (expectedName === actualName) { + message += 'Expected a ' + expectedName + ' but got a different error constructor with the same name'; + } else { + message += 'Expected a ' + expectedName + ' but got a ' + actualName; + } throw new Test262Error(message); } return; @@ -141,19 +148,27 @@ compareArray.isSameValue = function(a, b) { return a === b; }; -compareArray.format = function(array) { - return `[${array.map(String).join(', ')}]`; +compareArray.format = function(arrayLike) { + return `[${[].map.call(arrayLike, String).join(', ')}]`; }; assert.compareArray = function(actual, expected, message) { message = message === undefined ? '' : message; + + if (typeof message === 'symbol') { + message = message.toString(); + } + assert(actual != null, `First argument shouldn't be nullish. ${message}`); assert(expected != null, `Second argument shouldn't be nullish. ${message}`); var format = compareArray.format; - assert( - compareArray(actual, expected), - `Expected ${format(actual)} and ${format(expected)} to have the same contents. ${message}` - ); + var result = compareArray(actual, expected); + + // The following prevents actual and expected from being iterated and evaluated + // more than once unless absolutely necessary. + if (!result) { + assert(false, `Expected ${format(actual)} and ${format(expected)} to have the same contents. ${message}`); + } }; // file: propertyHelper.js @@ -165,13 +180,13 @@ description: | property descriptors. defines: - verifyProperty - - verifyEqualTo - - verifyWritable - - verifyNotWritable - - verifyEnumerable - - verifyNotEnumerable - - verifyConfigurable - - verifyNotConfigurable + - verifyEqualTo # deprecated + - verifyWritable # deprecated + - verifyNotWritable # deprecated + - verifyEnumerable # deprecated + - verifyNotEnumerable # deprecated + - verifyConfigurable # deprecated + - verifyNotConfigurable # deprecated ---*/ // @ts-check @@ -332,6 +347,9 @@ function isWritable(obj, name, verifyProp, value) { return writeSucceeded; } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyEqualTo(obj, name, value) { if (!isSameValue(obj[name], value)) { throw new Test262Error("Expected obj[" + String(name) + "] to equal " + value + @@ -339,6 +357,9 @@ function verifyEqualTo(obj, name, value) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyWritable(obj, name, verifyProp, value) { if (!verifyProp) { assert(Object.getOwnPropertyDescriptor(obj, name).writable, @@ -349,6 +370,9 @@ function verifyWritable(obj, name, verifyProp, value) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyNotWritable(obj, name, verifyProp, value) { if (!verifyProp) { assert(!Object.getOwnPropertyDescriptor(obj, name).writable, @@ -359,6 +383,9 @@ function verifyNotWritable(obj, name, verifyProp, value) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyEnumerable(obj, name) { assert(Object.getOwnPropertyDescriptor(obj, name).enumerable, "Expected obj[" + String(name) + "] to have enumerable:true."); @@ -367,6 +394,9 @@ function verifyEnumerable(obj, name) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyNotEnumerable(obj, name) { assert(!Object.getOwnPropertyDescriptor(obj, name).enumerable, "Expected obj[" + String(name) + "] to have enumerable:false."); @@ -375,6 +405,9 @@ function verifyNotEnumerable(obj, name) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyConfigurable(obj, name) { assert(Object.getOwnPropertyDescriptor(obj, name).configurable, "Expected obj[" + String(name) + "] to have configurable:true."); @@ -383,6 +416,9 @@ function verifyConfigurable(obj, name) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyNotConfigurable(obj, name) { assert(!Object.getOwnPropertyDescriptor(obj, name).configurable, "Expected obj[" + String(name) + "] to have configurable:false."); From 20f36004f47ed3055c148a049ce111490c71fe3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Fri, 8 Apr 2022 08:43:06 +0000 Subject: [PATCH 11/11] Bug 1763609 - Part 4: Update test262 exclusion list. r=mgaudet Differential Revision: https://phabricator.services.mozilla.com/D143166 --- js/src/tests/jstests.list | 136 +++++++++----------------------------- 1 file changed, 32 insertions(+), 104 deletions(-) diff --git a/js/src/tests/jstests.list b/js/src/tests/jstests.list index e1d2279d96fc..e3b2b9b11b3d 100644 --- a/js/src/tests/jstests.list +++ b/js/src/tests/jstests.list @@ -606,6 +606,34 @@ fails-if(!xulRuntime.shell) script test262/language/statements/class/subclass-bu # https://bugzilla.mozilla.org/show_bug.cgi?id=1648202 skip script test262/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js +# https://bugzilla.mozilla.org/show_bug.cgi?id=1761989 +skip script test262/built-ins/TypedArrayConstructors/ctors/no-species.js + +# https://bugzilla.mozilla.org/show_bug.cgi?id=1763605 +skip script test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js + +# https://bugzilla.mozilla.org/show_bug.cgi?id=1763606 +skip script test262/built-ins/TypedArray/prototype/sort/sort-tonumber.js + +# https://bugzilla.mozilla.org/show_bug.cgi?id=1763607 +skip script test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js +skip script test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js +skip script test262/intl402/PluralRules/prototype/selectRange/nan-arguments-throws.js +skip script test262/intl402/PluralRules/prototype/selectRange/undefined-arguments-throws.js + ########################################################### # Tests disabled due to issues in test262 importer script # @@ -637,112 +665,12 @@ skip script test262/language/module-code/top-level-await/await-dynamic-import-re # https://github.com/tc39/ecma402/issues/402 skip script test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-default.js -# https://github.com/tc39/test262/issues/3139 -skip script test262/intl402/DisplayNames/prototype/of/type-calendar-valid.js - -# Tests not yet updated for https://github.com/tc39/proposal-intl-numberformat-v3 -skip script test262/intl402/NumberFormat/prototype/resolvedOptions/order.js +# Not yet updated for https://github.com/tc39/proposal-intl-numberformat-v3/pull/92 skip script test262/intl402/NumberFormat/test-option-useGrouping.js -skip script test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js -skip script test262/intl402/PluralRules/prototype/resolvedOptions/order.js +skip script test262/intl402/NumberFormat/test-option-useGrouping-extended.js -# https://github.com/tc39/test262/pull/3199 -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Mark.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Arabic.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Currency_Symbol.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Balinese.js -skip script test262/built-ins/RegExp/property-escapes/generated/Dash.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kannada.js -skip script test262/built-ins/RegExp/property-escapes/generated/Cased.js -skip script test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casefolded.js -skip script test262/built-ins/RegExp/property-escapes/generated/Changes_When_Titlecased.js -skip script test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier_Base.js -skip script test262/built-ins/RegExp/property-escapes/generated/Diacritic.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Han.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Kannada.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Symbol.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Telugu.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Ethiopic.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Katakana.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Canadian_Aboriginal.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Takri.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Unassigned.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Kaithi.js -skip script test262/built-ins/RegExp/property-escapes/generated/ID_Continue.js -skip script test262/built-ins/RegExp/property-escapes/generated/Terminal_Punctuation.js -skip script test262/built-ins/RegExp/property-escapes/generated/Ideographic.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Katakana.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Balinese.js -skip script test262/built-ins/RegExp/property-escapes/generated/Changes_When_Lowercased.js -skip script test262/built-ins/RegExp/property-escapes/generated/Bidi_Mirrored.js -skip script test262/built-ins/RegExp/property-escapes/generated/Lowercase.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Cased_Letter.js -skip script test262/built-ins/RegExp/property-escapes/generated/Alphabetic.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Symbol.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Spacing_Mark.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Format.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Symbol.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Inherited.js -skip script test262/built-ins/RegExp/property-escapes/generated/Grapheme_Base.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Uppercase_Letter.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Kaithi.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Adlam.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Canadian_Aboriginal.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Brahmi.js -skip script test262/built-ins/RegExp/property-escapes/generated/Assigned.js -skip script test262/built-ins/RegExp/property-escapes/generated/Variation_Selector.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Ahom.js -skip script test262/built-ins/RegExp/property-escapes/generated/Soft_Dotted.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ethiopic.js -skip script test262/built-ins/RegExp/property-escapes/generated/Uppercase.js -skip script test262/built-ins/RegExp/property-escapes/generated/Default_Ignorable_Code_Point.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Letter.js -skip script test262/built-ins/RegExp/property-escapes/generated/Sentence_Terminal.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Dash_Punctuation.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Ahom.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Nko.js -skip script test262/built-ins/RegExp/property-escapes/generated/XID_Continue.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Hiragana.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Arabic.js -skip script test262/built-ins/RegExp/property-escapes/generated/Extender.js -skip script test262/built-ins/RegExp/property-escapes/generated/Grapheme_Extend.js -skip script test262/built-ins/RegExp/property-escapes/generated/Unified_Ideograph.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Common.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Number.js -skip script test262/built-ins/RegExp/property-escapes/generated/Emoji_Presentation.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Mongolian.js -skip script test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casemapped.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Close_Punctuation.js -skip script test262/built-ins/RegExp/property-escapes/generated/ID_Start.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Latin.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Takri.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Punctuation.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Common.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Glagolitic.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Brahmi.js -skip script test262/built-ins/RegExp/property-escapes/generated/Changes_When_Uppercased.js -skip script test262/built-ins/RegExp/property-escapes/generated/Emoji.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Telugu.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Glagolitic.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Open_Punctuation.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Han.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Lowercase_Letter.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Mongolian.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Nonspacing_Mark.js -skip script test262/built-ins/RegExp/property-escapes/generated/XID_Start.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Letter.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Inherited.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Tagalog.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Punctuation.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Hiragana.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Syriac.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_-_Latin.js -skip script test262/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Tagalog.js -skip script test262/built-ins/RegExp/property-escapes/generated/Case_Ignorable.js -skip script test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other.js -skip script test262/built-ins/RegExp/property-escapes/generated/Changes_When_NFKC_Casefolded.js +# Missing "SharedArrayBuffer" features tag +fails-if(!xulRuntime.shell) script test262/built-ins/SharedArrayBuffer/prototype/prop-desc.js ##############################################